diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2009-10-11 15:10:43 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2009-10-11 15:10:43 +0000 |
commit | f86519a1181233a5179d8a9e4bbb3f427baaf988 (patch) | |
tree | 6844fa556f7d75cb22db1f17eca781626cc6e034 | |
parent | 794ca3067d66964da3b623872bd50594f6dcbb8a (diff) | |
download | qpid-python-f86519a1181233a5179d8a9e4bbb3f427baaf988.tar.gz |
Migrate 0-8 code to use same Txn code as 0-10
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-0-10@824084 13f79535-47bb-0310-9956-ffa450edef68
94 files changed, 2362 insertions, 3544 deletions
diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java index 615a02a112..47d0749818 100644 --- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java +++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java @@ -197,7 +197,7 @@ public class DiagnosticExchange extends AbstractExchange return false; } - public ArrayList<AMQQueue> route(InboundMessage payload) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage payload) { Long value = new Long(SizeOf.getUsedMemory()); diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java index b64983ccb0..572b123676 100644 --- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java +++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java @@ -113,7 +113,7 @@ public class TestExchange implements Exchange { } - public ArrayList<AMQQueue> route(InboundMessage message) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage message) { return new ArrayList<AMQQueue>(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java index 5cfa8066e5..c2e6a82372 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java @@ -63,7 +63,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.AMQQueueMBean; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; @@ -78,7 +78,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr private final QueueRegistry _queueRegistry; private final ExchangeRegistry _exchangeRegistry; private final ExchangeFactory _exchangeFactory; - private final MessageStore _messageStore; + private final DurableConfigurationStore _durableConfig; private final VirtualHost.VirtualHostMBean _virtualHostMBean; @@ -92,7 +92,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr _queueRegistry = virtualHost.getQueueRegistry(); _exchangeRegistry = virtualHost.getExchangeRegistry(); - _messageStore = virtualHost.getMessageStore(); + _durableConfig = virtualHost.getDurableConfigurationStore(); _exchangeFactory = virtualHost.getExchangeFactory(); } @@ -277,7 +277,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr null); if (queue.isDurable() && !queue.isAutoDelete()) { - _messageStore.createQueue(queue); + _durableConfig.createQueue(queue); } _queueRegistry.registerQueue(queue); @@ -319,7 +319,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr queue.delete(); if (queue.isDurable()) { - _messageStore.removeQueue(queue); + _durableConfig.removeQueue(queue); } } catch (AMQException ex) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index 5aaa18860f..7b966700fb 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -20,24 +20,20 @@ */ package org.apache.qpid.server; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; +import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.framing.*; import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.NoRouteException; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; import org.apache.qpid.server.protocol.AMQProtocolSession; @@ -47,14 +43,11 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.RecordDeliveryMethod; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.LocalTransactionalContext; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; +import org.apache.qpid.server.txn.*; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; import org.apache.qpid.server.logging.actors.AMQPChannelActor; @@ -64,7 +57,11 @@ public class AMQChannel { public static final int DEFAULT_PREFETCH = 5000; - private static final Logger _log = Logger.getLogger(AMQChannel.class); + private static final Logger _logger = Logger.getLogger(AMQChannel.class); + + private static final boolean MSG_AUTH = + ApplicationRegistry.getInstance().getConfiguration().getMsgAuth(); + private final int _channelId; @@ -97,15 +94,13 @@ public class AMQChannel private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH); + // Set of messages being acknoweledged in the current transaction + private SortedSet<QueueEntry> _acknowledgedMessages = new TreeSet<QueueEntry>(); + private final AtomicBoolean _suspended = new AtomicBoolean(false); - private TransactionalContext _txnContext; + private Transaction _transaction; - /** - * A context used by the message store enabling it to track context for a given channel even across thread - * boundaries - */ - private final StoreContext _storeContext; private final List<RequiredDeliveryException> _returnMessages = new LinkedList<RequiredDeliveryException>(); @@ -122,6 +117,10 @@ public class AMQChannel private LogActor _actor; private LogSubject _logSubject; + private volatile boolean _rollingBack; + + private static final Runnable NULL_TASK = new Runnable() { public void run() {} }; + private List<QueueEntry> _resendList = new ArrayList<QueueEntry>(); public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) throws AMQException @@ -131,22 +130,19 @@ public class AMQChannel _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); _logSubject = new ChannelLogSubject(this); - - _actor.message(ChannelMessages.CHN_1001()); - - _storeContext = new StoreContext("Session: " + session.getClientIdentifier() + "; channel: " + channelId); + _actor.message(ChannelMessages.CHN_1001()); _messageStore = messageStore; // by default the session is non-transactional - _txnContext = new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages); + _transaction = new AutoCommitTransaction(_messageStore); } /** Sets this channel to be part of a local transaction */ public void setLocalTransactional() { - _txnContext = new LocalTransactionalContext(this); + _transaction = new LocalTransaction(_messageStore); } public boolean isTransactional() @@ -154,7 +150,7 @@ public class AMQChannel // this does not look great but there should only be one "non-transactional" // transactional context, while there could be several transactional ones in // theory - return !(_txnContext instanceof NonTransactionalContext); + return !(_transaction instanceof AutoCommitTransaction); } public int getChannelId() @@ -165,43 +161,61 @@ public class AMQChannel public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQException { - _currentMessage = new IncomingMessage(_messageStore.getNewMessageId(), info, _txnContext, _session); - _currentMessage.setMessageStore(_messageStore); + _currentMessage = new IncomingMessage(_messageStore.getNewMessageId(), info, _session); _currentMessage.setExchange(e); } public void publishContentHeader(ContentHeaderBody contentHeaderBody) throws AMQException { - StoreContext.setCurrentContext(_storeContext); - try + if (_currentMessage == null) { - if (_currentMessage == null) + throw new AMQException("Received content header without previously receiving a BasicPublish frame"); + } + else + { + if (_logger.isDebugEnabled()) { - throw new AMQException("Received content header without previously receiving a BasicPublish frame"); + _logger.debug("Content header received on channel " + _channelId); } - else - { - if (_log.isDebugEnabled()) - { - _log.debug("Content header received on channel " + _channelId); - } - _currentMessage.setContentHeaderBody(contentHeaderBody); + _currentMessage.setContentHeaderBody(contentHeaderBody); + + _currentMessage.setExpiration(); - _currentMessage.setExpiration(); + routeCurrentMessage(); - routeCurrentMessage(); + MessageMetaData mmd = _currentMessage.routingComplete(_messageStore, _messageHandleFactory); - _currentMessage.routingComplete(_messageStore, _messageHandleFactory); + if(_currentMessage.isPersistent()) + { + final Long messageNumber = _currentMessage.getMessageNumber(); + + _messageStore.storeMessageMetaData(messageNumber, mmd); - deliverCurrentMessageIfComplete(); + _transaction.addPostCommitAction(new Transaction.Action() + { + + public void postCommit() + { + } + public void onRollback() + { + try + { + _messageStore.removeMessage(messageNumber); + } + catch (AMQException e) + { + + } + } + }); } - } - finally - { - StoreContext.clearCurrentContext(); + + deliverCurrentMessageIfComplete(); + } } @@ -213,21 +227,36 @@ public class AMQChannel { try { - _currentMessage.deliverToQueues(); - } - catch (NoRouteException e) - { - _returnMessages.add(e); - } - catch(UnauthorizedAccessException ex) - { - _returnMessages.add(ex); + + final ArrayList<AMQQueue> destinationQueues = _currentMessage.getDestinationQueues(); + + if(!checkMessageUserId(_currentMessage.getContentHeader())) + { + _transaction.addPostCommitAction(new WriteReturnAction(AMQConstant.ACCESS_REFUSED, "Access Refused", createAMQMessage(_currentMessage))); + } + else + { + if(destinationQueues == null || _currentMessage.getDestinationQueues().isEmpty()) + { + if (_currentMessage.isMandatory() || _currentMessage.isImmediate()) + { + _transaction.addPostCommitAction(new WriteReturnAction(AMQConstant.NO_ROUTE, "No Route for message", createAMQMessage(_currentMessage))); + } + else + { + _logger.warn("MESSAGE DISCARDED: No routes for message - " + createAMQMessage(_currentMessage)); + } + + } + else + { + _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues)); + + } + } } finally { - // callback to allow the context to do any post message processing - // primary use is to allow message return processing in the non-tx case - _txnContext.messageProcessed(_session); _currentMessage = null; } } @@ -236,15 +265,14 @@ public class AMQChannel public void publishContentBody(ContentBody contentBody) throws AMQException { - StoreContext.setCurrentContext(_storeContext); if (_currentMessage == null) { throw new AMQException("Received content body without previously receiving a JmsPublishBody"); } - if (_log.isDebugEnabled()) + if (_logger.isDebugEnabled()) { - _log.debug(debugIdentity() + "Content body received on channel " + _channelId); + _logger.debug(debugIdentity() + "Content body received on channel " + _channelId); } try @@ -252,11 +280,20 @@ public class AMQChannel // returns true iff the message was delivered (i.e. if all data was // received - _currentMessage.addContentBodyFrame( - _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk( - contentBody)); + final ContentChunk contentChunk = + _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(contentBody); + + int chunkId = _currentMessage.addContentBodyFrame(contentChunk); + + if(_currentMessage.isPersistent()) + { + final Long messageNumber = _currentMessage.getMessageNumber(); + _messageStore.storeContentBodyChunk(messageNumber, chunkId, + contentChunk, _currentMessage.allContentReceived()); + } + deliverCurrentMessageIfComplete(); } catch (AMQException e) @@ -266,23 +303,11 @@ public class AMQChannel _currentMessage = null; throw e; } - finally - { - StoreContext.clearCurrentContext(); - } } protected void routeCurrentMessage() throws AMQException { - try - { - _currentMessage.route(); - } - catch (NoRouteException e) - { - //_currentMessage.incrementReference(); - _returnMessages.add(e); - } + _currentMessage.route(); } public long getNextDeliveryTag() @@ -359,12 +384,12 @@ public class AMQChannel Subscription sub = _tag2SubscriptionMap.remove(consumerTag); if (sub != null) { - try + try { sub.getSendLock(); sub.getQueue().unregisterSubscription(sub); } - finally + finally { sub.releaseSendLock(); } @@ -372,7 +397,7 @@ public class AMQChannel } else { - _log.warn("Attempt to unsubscribe consumer with tag '"+consumerTag+"' which is not registered."); + _logger.warn("Attempt to unsubscribe consumer with tag '"+consumerTag+"' which is not registered."); } return false; } @@ -384,15 +409,17 @@ public class AMQChannel */ public void close() throws AMQException { - _txnContext.rollback(); + unsubscribeAllConsumers(); + _transaction.rollback(); + try { requeue(); } catch (AMQException e) { - _log.error("Caught AMQException whilst attempting to reque:" + e); + _logger.error("Caught AMQException whilst attempting to reque:" + e); } setClosing(true); @@ -407,23 +434,23 @@ public class AMQChannel private void unsubscribeAllConsumers() throws AMQException { - if (_log.isInfoEnabled()) + if (_logger.isInfoEnabled()) { if (!_tag2SubscriptionMap.isEmpty()) { - _log.info("Unsubscribing all consumers on channel " + toString()); + _logger.info("Unsubscribing all consumers on channel " + toString()); } else { - _log.info("No consumers to unsubscribe on channel " + toString()); + _logger.info("No consumers to unsubscribe on channel " + toString()); } } for (Map.Entry<AMQShortString, Subscription> me : _tag2SubscriptionMap.entrySet()) { - if (_log.isInfoEnabled()) + if (_logger.isInfoEnabled()) { - _log.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString()); + _logger.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString()); } Subscription sub = me.getValue(); @@ -437,7 +464,7 @@ public class AMQChannel { sub.releaseSendLock(); } - + } _tag2SubscriptionMap.clear(); @@ -453,17 +480,17 @@ public class AMQChannel */ public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription) { - if (_log.isDebugEnabled()) + if (_logger.isDebugEnabled()) { if (entry.getQueue() == null) { - _log.debug("Adding unacked message with a null queue:" + entry); + _logger.debug("Adding unacked message with a null queue:" + entry); } else { - if (_log.isDebugEnabled()) + if (_logger.isDebugEnabled()) { - _log.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag + _logger.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag + ") with a queue(" + entry.getQueue() + ") for " + subscription); } } @@ -491,27 +518,13 @@ public class AMQChannel // we must create a new map since all the messages will get a new delivery tag when they are redelivered Collection<QueueEntry> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages(); - // Deliver these messages out of the transaction as their delivery was never - // part of the transaction only the receive. - TransactionalContext deliveryContext = null; - if (!messagesToBeDelivered.isEmpty()) { - if (_log.isInfoEnabled()) + if (_logger.isInfoEnabled()) { - _log.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString()); + _logger.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString()); } - if (!(_txnContext instanceof NonTransactionalContext)) - { - - deliveryContext = - new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages); - } - else - { - deliveryContext = _txnContext; - } } for (QueueEntry unacked : messagesToBeDelivered) @@ -524,13 +537,10 @@ public class AMQChannel // Ensure message is released for redelivery unacked.release(); - // Deliver Message - deliveryContext.requeue(unacked); - } else { - unacked.discard(_storeContext); + unacked.discard(); } } @@ -555,43 +565,22 @@ public class AMQChannel // Ensure message is released for redelivery if (!unacked.isQueueDeleted()) { - unacked.release(); - } + // Ensure message is released for redelivery + unacked.release(); - // Deliver these messages out of the transaction as their delivery was never - // part of the transaction only the receive. - TransactionalContext deliveryContext; - if (!(_txnContext instanceof NonTransactionalContext)) - { - - deliveryContext = - new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages); - - } - else - { - deliveryContext = _txnContext; - } - - if (!unacked.isQueueDeleted()) - { - // Redeliver the messages to the front of the queue - deliveryContext.requeue(unacked); - // Deliver increments the message count but we have already deliverted this once so don't increment it again - // this was because deliver did an increment changed this. } else { - _log.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked + _logger.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked + "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message."); - unacked.discard(_storeContext); + unacked.discard(); } } else { - _log.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists." + _logger.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists." + _unacknowledgedMessageMap.size()); } @@ -612,28 +601,31 @@ public class AMQChannel final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>(); final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>(); - if (_log.isDebugEnabled()) + if (_logger.isDebugEnabled()) { - _log.debug("unacked map Size:" + _unacknowledgedMessageMap.size()); + _logger.debug("unacked map Size:" + _unacknowledgedMessageMap.size()); } // Process the Unacked-Map. // Marking messages who still have a consumer for to be resent // and those that don't to be requeued. - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, requeue, _storeContext)); + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, + msgToRequeue, + msgToResend, + requeue, + _messageStore)); // Process Messages to Resend - if (_log.isDebugEnabled()) + if (_logger.isDebugEnabled()) { if (!msgToResend.isEmpty()) { - _log.debug("Preparing (" + msgToResend.size() + ") message to resend."); + _logger.debug("Preparing (" + msgToResend.size() + ") message to resend."); } else { - _log.debug("No message to resend."); + _logger.debug("No message to resend."); } } @@ -653,7 +645,7 @@ public class AMQChannel // i.e. The channel hasn't been server side suspended. // if (isSuspended()) // { - // _log.info("Channel is suspended so requeuing"); + // _logger.info("Channel is suspended so requeuing"); // //move this message to requeue // msgToRequeue.add(message); // } @@ -669,8 +661,8 @@ public class AMQChannel if (sub != null) { - - if(!queue.resend(message, sub)) + + if(!queue.resend(message,sub)) { msgToRequeue.put(deliveryTag, message); } @@ -678,9 +670,9 @@ public class AMQChannel else { - if (_log.isInfoEnabled()) + if (_logger.isInfoEnabled()) { - _log.info("DeliveredSubscription not recorded so just requeueing(" + message.toString() + _logger.info("DeliveredSubscription not recorded so just requeueing(" + message.toString() + ")to prevent loss"); } // move this message to requeue @@ -689,91 +681,28 @@ public class AMQChannel } // for all messages // } else !isSuspend - if (_log.isInfoEnabled()) + if (_logger.isInfoEnabled()) { if (!msgToRequeue.isEmpty()) { - _log.info("Preparing (" + msgToRequeue.size() + ") message to requeue to."); + _logger.info("Preparing (" + msgToRequeue.size() + ") message to requeue to."); } } - // Deliver these messages out of the transaction as their delivery was never - // part of the transaction only the receive. - TransactionalContext deliveryContext; - if (!(_txnContext instanceof NonTransactionalContext)) - { - - deliveryContext = - new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages); - } - else - { - deliveryContext = _txnContext; - } - // Process Messages to Requeue at the front of the queue for (Map.Entry<Long, QueueEntry> entry : msgToRequeue.entrySet()) { QueueEntry message = entry.getValue(); long deliveryTag = entry.getKey(); - - message.release(); - message.setRedelivered(true); + _unacknowledgedMessageMap.remove(deliveryTag); - deliveryContext.requeue(message); + message.setRedelivered(true); + message.release(); - _unacknowledgedMessageMap.remove(deliveryTag); } } - /** - * Callback indicating that a queue has been deleted. We must update the structure of unacknowledged messages to - * remove the queue reference and also decrement any message reference counts, without actually removing the item - * since we may get an ack for a delivery tag that was generated from the deleted queue. - * - * @param queue the queue that has been deleted - * - */ - /* public void queueDeleted(final AMQQueue queue) - { - try - { - _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor() - { - public boolean callback(UnacknowledgedMessage message) - { - if (message.getQueue() == queue) - { - try - { - message.discard(_storeContext); - message.setQueueDeleted(true); - - } - catch (AMQException e) - { - _log.error( - "Error decrementing ref count on message " + message.getMessage().getMessageId() + ": " + e, e); - throw new RuntimeException(e); - } - } - return false; - } - - public void visitComplete() - { - } - }); - } - catch (AMQException e) - { - _log.error("Unexpected Error while handling deletion of queue", e); - throw new RuntimeException(e); - } - - } -*/ /** * Acknowledge one or more messages. * @@ -785,7 +714,17 @@ public class AMQChannel */ public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException { - _unacknowledgedMessageMap.acknowledgeMessage(deliveryTag, multiple, _txnContext); + Collection<QueueEntry> ackedMessages = getAckedMessages(deliveryTag, multiple); + _transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages)); + } + + private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple) + { + + Map<Long, QueueEntry> ackedMessageMap = new LinkedHashMap<Long,QueueEntry>(); + _unacknowledgedMessageMap.collect(deliveryTag, multiple, ackedMessageMap); + _unacknowledgedMessageMap.remove(ackedMessageMap); + return ackedMessageMap.values(); } /** @@ -879,12 +818,69 @@ public class AMQChannel throw new AMQException("Fatal error: commit called on non-transactional channel"); } - _txnContext.commit(); + _transaction.commit(); + } public void rollback() throws AMQException { - _txnContext.rollback(); + rollback(NULL_TASK); + } + + public void rollback(Runnable postRollbackTask) throws AMQException + { + if (!isTransactional()) + { + throw new AMQException("Fatal error: commit called on non-transactional channel"); + } + + // stop all subscriptions + _rollingBack = true; + boolean requiresSuspend = _suspended.compareAndSet(false,true); + + // ensure all subscriptions have seen the change to the channel state + for(Subscription sub : _tag2SubscriptionMap.values()) + { + sub.getSendLock(); + sub.releaseSendLock(); + } + + try + { + _transaction.rollback(); + } + finally + { + _rollingBack = false; + } + + postRollbackTask.run(); + + for(QueueEntry entry : _resendList) + { + Subscription sub = entry.getDeliveredSubscription(); + if(sub == null || sub.isClosed()) + { + entry.release(); + } + else + { + sub.getQueue().resend(entry, sub); + } + } + _resendList.clear(); + + if(requiresSuspend) + { + _suspended.set(false); + for(Subscription sub : _tag2SubscriptionMap.values()) + { + sub.getQueue().deliverAsync(sub); + } + + } + + } public String toString() @@ -902,23 +898,22 @@ public class AMQChannel return _defaultQueue; } - public StoreContext getStoreContext() - { - return _storeContext; - } - public void processReturns() throws AMQException { if (!_returnMessages.isEmpty()) { - StoreContext sc =StoreContext.setCurrentContext(_storeContext); + for (RequiredDeliveryException bouncedMessage : _returnMessages) { ServerMessage serverMessage = bouncedMessage.getAMQMessage(); if(serverMessage instanceof AMQMessage) { AMQMessage message = (AMQMessage) serverMessage; - _session.getProtocolOutputConverter().writeReturn(message, _channelId, bouncedMessage.getReplyCode().getCode(), + _session.getProtocolOutputConverter().writeReturn(message.getMessagePublishInfo(), + message.getContentHeaderBody(), + message.getBodyFrameIterator(_session,_channelId), + _channelId, + bouncedMessage.getReplyCode().getCode(), new AMQShortString(bouncedMessage.getMessage())); } @@ -929,18 +924,12 @@ public class AMQChannel } bouncedMessage.release(); } - StoreContext.setCurrentContext(sc); + _returnMessages.clear(); } } - - public TransactionalContext getTransactionalContext() - { - return _txnContext; - } - public boolean isClosing() { return _closing; @@ -962,11 +951,6 @@ public class AMQChannel _creditManager.setCreditLimits(prefetchSize, prefetchCount); } - public List<RequiredDeliveryException> getReturnMessages() - { - return _returnMessages; - } - public MessageStore getMessageStore() { return _messageStore; @@ -981,7 +965,7 @@ public class AMQChannel ServerMessage msg = entry.getMessage(); if(msg instanceof AMQMessage) { - getProtocolSession().getProtocolOutputConverter().writeDeliver((AMQMessage)msg, getChannelId(), + getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(), deliveryTag, sub.getConsumerTag()); } else @@ -1011,6 +995,203 @@ public class AMQChannel return _recordDeliveryMethod; } + + private AMQMessage createAMQMessage(IncomingMessage incomingMessage) + throws AMQException + { + + + + final AMQMessageHandle messageHandle = incomingMessage.getMessageHandle(); + final MessagePublishInfo messagePublishInfo = incomingMessage.getMessagePublishInfo(); + final ContentHeaderBody header = incomingMessage.getContentHeader(); + + + + AMQMessage message = new AMQMessage(messageHandle, header, incomingMessage.getSize() ,messagePublishInfo); + + message.setExpiration(incomingMessage.getExpiration()); + message.setClientIdentifier(_session); + return message; + } + + private boolean checkMessageUserId(ContentHeaderBody header) + throws UnauthorizedAccessException + { + AMQShortString userID = + header.properties instanceof BasicContentHeaderProperties + ? ((BasicContentHeaderProperties) header.properties).getUserId() + : null; + + return (!MSG_AUTH || _session.getPrincipal().getName().equals(userID == null? "" : userID.toString())); + + } + + private class MessageDeliveryAction implements Transaction.Action + { + private IncomingMessage _incommingMessage; + private ArrayList<AMQQueue> _destinationQueues; + + public MessageDeliveryAction(IncomingMessage currentMessage, + ArrayList<AMQQueue> destinationQueues) + { + _incommingMessage = currentMessage; + _destinationQueues = destinationQueues; + } + + public void postCommit() + { + try + { + final boolean immediate = _incommingMessage.isImmediate(); + + Transaction txn = null; + + for(AMQQueue queue : _destinationQueues) + { + QueueEntry entry = queue.enqueue(createAMQMessage(_incommingMessage)); + queue.checkCapacity(AMQChannel.this); + + + if(immediate && !entry.getDeliveredToConsumer() && entry.acquire()) + { + if(txn == null) + { + txn = new LocalTransaction(_messageStore); + Collection<QueueEntry> entries = new ArrayList<QueueEntry>(1); + entries.add(entry); + txn.enqueue(queue, entry.getMessage(), new MessageAcknowledgeAction(entries)); + } + + + AMQMessage message = (AMQMessage) entry.getMessage(); + _session.getProtocolOutputConverter().writeReturn(message.getMessagePublishInfo(), + message.getContentHeaderBody(), + message.getBodyFrameIterator(_session,_channelId), + _channelId, + AMQConstant.NO_CONSUMERS.getCode(), + new AMQShortString("Immediate delivery is not possible.")); + + + } + + } + if(txn != null) + { + txn.commit(); + } + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + + + + + + } + + public void onRollback() + { + // Maybe keep track of entries that were created and then delete them here in case of failure + // to in memory enqueue + } + } + + private class MessageAcknowledgeAction implements Transaction.Action + { + private final Collection<QueueEntry> _ackedMessages; + + + public MessageAcknowledgeAction(Collection<QueueEntry> ackedMessages) + { + _ackedMessages = ackedMessages; + } + + public void postCommit() + { + try + { + for(QueueEntry entry : _ackedMessages) + { + entry.discard(); + } + } + finally + { + _acknowledgedMessages.clear(); + } + + } + + public void onRollback() + { + // explicit rollbacks resend the message after the rollback-ok is sent + if(_rollingBack) + { + _resendList.addAll(_ackedMessages); + } + else + { + try + { + for(QueueEntry entry : _ackedMessages) + { + entry.release(); + } + } + finally + { + _acknowledgedMessages.clear(); + } + } + + } + } + + private class WriteReturnAction implements Transaction.Action + { + private final AMQConstant _errorCode; + private final AMQMessage _message; + private final String _description; + + public WriteReturnAction(AMQConstant errorCode, + String description, + AMQMessage message) + { + _errorCode = errorCode; + _message = message; + _description = description; + } + + public void postCommit() + { + try + { + _session.getProtocolOutputConverter().writeReturn(_message.getMessagePublishInfo(), + _message.getContentHeaderBody(), + _message.getBodyFrameIterator(_session,_channelId), + _channelId, + _errorCode.getCode(), + new AMQShortString(_description)); + } + catch (AMQException e) + { + //TODO + throw new RuntimeException(e); + } + + } + + public void onRollback() + { + //To change body of implemented methods use File | Settings | File Templates. + } + } + + public LogActor getLogActor() { return _actor; @@ -1029,7 +1210,7 @@ public class AMQChannel } } - public void unblock(AMQQueue queue) + public void unblock(AMQQueue queue) { if(_blockingQueues.remove(queue)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java index 29c37a0ec8..a0b907c518 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java @@ -21,12 +21,11 @@ package org.apache.qpid.server; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.AMQException; import org.apache.log4j.Logger; @@ -36,23 +35,23 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor { private static final Logger _log = Logger.getLogger(ExtractResendAndRequeue.class); - private Map<Long, QueueEntry> _msgToRequeue; - private Map<Long, QueueEntry> _msgToResend; - private boolean _requeueIfUnabletoResend; - private StoreContext _storeContext; - private UnacknowledgedMessageMap _unacknowledgedMessageMap; + private final Map<Long, QueueEntry> _msgToRequeue; + private final Map<Long, QueueEntry> _msgToResend; + private final boolean _requeueIfUnabletoResend; + private final UnacknowledgedMessageMap _unacknowledgedMessageMap; + private final TransactionLog _transactionLog; - public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap, + public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap, Map<Long, QueueEntry> msgToRequeue, Map<Long, QueueEntry> msgToResend, boolean requeueIfUnabletoResend, - StoreContext storeContext) + TransactionLog txnLog) { _unacknowledgedMessageMap = unacknowledgedMessageMap; _msgToRequeue = msgToRequeue; _msgToResend = msgToResend; _requeueIfUnabletoResend = requeueIfUnabletoResend; - _storeContext = storeContext; + _transactionLog = txnLog; } public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException @@ -85,13 +84,14 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor } else { - message.discard(_storeContext); + + dequeueEntry(message); _log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message); } } else { - message.discard(_storeContext); + dequeueEntry(message); _log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message); } } @@ -100,6 +100,31 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor return false; } + + private void dequeueEntry(final QueueEntry node) + { + Transaction txn = new AutoCommitTransaction(_transactionLog); + dequeueEntry(node, txn); + } + + private void dequeueEntry(final QueueEntry node, Transaction txn) + { + txn.dequeue(node.getQueue(), node.getMessage(), + new Transaction.Action() + { + + public void postCommit() + { + node.discard(); + } + + public void onRollback() + { + + } + }); + } + public void visitComplete() { _unacknowledgedMessageMap.clear(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java index d8b0f7aec7..baa9ba6208 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -335,8 +335,7 @@ public class Main String keystorePassword = serverConfig.getKeystorePassword(); String certType = serverConfig.getCertType(); SSLContextFactory sslFactory = null; - boolean isSsl = false; - + if (!serverConfig.getSSLOnly()) { NetworkDriver driver = new MINANetworkDriver(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java index be6232ed6b..eeb04c9077 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java @@ -82,6 +82,6 @@ public abstract class RequiredDeliveryException extends AMQException public void release() { - _amqMessage.release(); + //_amqMessage.release(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java deleted file mode 100644 index 7322a4add6..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.ack; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.TxnOp; -import org.apache.qpid.server.queue.QueueEntry; - -/** - * A TxnOp implementation for handling accumulated acks - */ -public class TxAck implements TxnOp -{ - private final UnacknowledgedMessageMap _map; - private final Map<Long, QueueEntry> _unacked = new HashMap<Long,QueueEntry>(); - private List<Long> _individual; - private long _deliveryTag; - private boolean _multiple; - - public TxAck(UnacknowledgedMessageMap map) - { - _map = map; - } - - public void update(long deliveryTag, boolean multiple) - { - _unacked.clear(); - if (!multiple) - { - if(_individual == null) - { - _individual = new ArrayList<Long>(); - } - //have acked a single message that is not part of - //the previously acked region so record - //individually - _individual.add(deliveryTag);//_multiple && !multiple - } - else if (deliveryTag > _deliveryTag) - { - //have simply moved the last acked message on a - //bit - _deliveryTag = deliveryTag; - _multiple = true; - } - } - - public void consolidate() - { - if(_unacked.isEmpty()) - { - //lookup all the unacked messages that have been acked in this transaction - if (_multiple) - { - //get all the unacked messages for the accumulated - //multiple acks - _map.collect(_deliveryTag, true, _unacked); - } - if(_individual != null) - { - //get any unacked messages for individual acks outside the - //range covered by multiple acks - for (long tag : _individual) - { - if(_deliveryTag < tag) - { - _map.collect(tag, false, _unacked); - } - } - } - } - } - - public boolean checkPersistent() throws AMQException - { - consolidate(); - //if any of the messages in unacked are persistent the txn - //buffer must be marked as persistent: - for (QueueEntry msg : _unacked.values()) - { - if (msg.getMessage().isPersistent()) - { - return true; - } - } - return false; - } - - public void prepare(StoreContext storeContext) throws AMQException - { - //make persistent changes, i.e. dequeue and decrementReference - for (QueueEntry msg : _unacked.values()) - { - //Message has been ack so discard it. This will dequeue and decrement the reference. - msg.discard(storeContext); - - } - } - - public void undoPrepare() - { - //decrementReference is annoyingly untransactional (due to - //in memory counter) so if we failed in prepare for full - //txn, this op will have to compensate by fixing the count - //in memory (persistent changes will be rolled back by store) - for (QueueEntry msg : _unacked.values()) - { - // TODO - should requeue, whole thing is messed up - } - } - - public void commit(StoreContext storeContext) - { - //remove the unacked messages from the channels map - _map.remove(_unacked); - } - - public void rollback(StoreContext storeContext) - { - } -} - - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java index c80a96f967..3bad73d86d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java @@ -21,14 +21,12 @@ package org.apache.qpid.server.ack; import java.util.Collection; -import java.util.List; import java.util.Set; import java.util.Map; import org.apache.qpid.AMQException; -import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.StoreContext; + public interface UnacknowledgedMessageMap { @@ -50,18 +48,12 @@ public interface UnacknowledgedMessageMap void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs); - boolean contains(long deliveryTag) throws AMQException; - void remove(Map<Long,QueueEntry> msgs); QueueEntry remove(long deliveryTag); - public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException; - Collection<QueueEntry> cancelAllMessages(); - void acknowledgeMessage(long deliveryTag, boolean multiple, TransactionalContext txnContext) throws AMQException; - int size(); void clear(); @@ -75,7 +67,6 @@ public interface UnacknowledgedMessageMap */ Set<Long> getDeliveryTags(); - public long getUnacknowledgeBytes(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java index c567387662..d920d97c1a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java @@ -20,20 +20,13 @@ */ package org.apache.qpid.server.ack; -import org.apache.qpid.server.store.StoreContext; import java.util.Collection; -import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Set; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.txn.TransactionalContext; public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap { @@ -61,19 +54,15 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap } else { - msgs.put(deliveryTag, get(deliveryTag)); + final QueueEntry entry = get(deliveryTag); + if(entry != null) + { + msgs.put(deliveryTag, entry); + } } } - public boolean contains(long deliveryTag) throws AMQException - { - synchronized (_lock) - { - return _map.containsKey(deliveryTag); - } - } - public void remove(Map<Long,QueueEntry> msgs) { synchronized (_lock) @@ -135,15 +124,6 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap } } - public void acknowledgeMessage(long deliveryTag, boolean multiple, TransactionalContext txnContext) - throws AMQException - { - synchronized (_lock) - { - txnContext.acknowledgeMessage(deliveryTag, _lastDeliveryTag, multiple, this); - } - } - public int size() { synchronized (_lock) @@ -161,39 +141,6 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap } } - public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException - - { - synchronized (_lock) - { - Iterator<Map.Entry<Long, QueueEntry>> it = _map.entrySet().iterator(); - while (it.hasNext()) - { - Map.Entry<Long, QueueEntry> unacked = it.next(); - - if (unacked.getKey() > deliveryTag) - { - //This should not occur now. - throw new AMQException("UnacknowledgedMessageMap is out of order:" + unacked.getKey() + - " When deliveryTag is:" + deliveryTag + "ES:" + _map.entrySet().toString()); - } - - //Message has been ack so discard it. This will dequeue and decrement the reference. - unacked.getValue().discard(storeContext); - - it.remove(); - - _unackedSize -= unacked.getValue().getMessage().getSize(); - - - if (unacked.getKey() == deliveryTag) - { - break; - } - } - } - } - public QueueEntry get(long key) { synchronized (_lock) @@ -225,8 +172,4 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap } } - public long getUnacknowledgeBytes() - { - return _unackedSize; - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index e865f319a3..55ff948471 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -25,7 +25,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.protocol.ExchangeInitialiser; import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Collection; @@ -61,9 +61,9 @@ public class DefaultExchangeRegistry implements ExchangeRegistry return getExchange(new AMQShortString(exchangeName)); } - public MessageStore getMessageStore() + public DurableConfigurationStore getDurableConfigurationStore() { - return _host.getMessageStore(); + return _host.getDurableConfigurationStore(); } public void registerExchange(Exchange exchange) throws AMQException @@ -71,7 +71,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry _exchangeMap.put(exchange.getName(), exchange); if (exchange.isDurable()) { - getMessageStore().createExchange(exchange); + getDurableConfigurationStore().createExchange(exchange); } } @@ -98,7 +98,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry { if (e.isDurable()) { - getMessageStore().removeExchange(e); + getDurableConfigurationStore().removeExchange(e); } e.close(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index 036ac4ece8..2832c7f2bd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -209,7 +209,7 @@ public class DirectExchange extends AbstractExchange } } - public ArrayList<AMQQueue> route(InboundMessage payload) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage payload) { final AMQShortString routingKey = payload.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : new AMQShortString(payload.getRoutingKey()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 40a765f420..441996c212 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -56,7 +56,7 @@ public interface Exchange void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; - ArrayList<AMQQueue> route(InboundMessage message) throws AMQException; + ArrayList<AMQQueue> route(InboundMessage message); /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index a4cb3ce44f..62172bbfb2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -199,7 +199,7 @@ public class FanoutExchange extends AbstractExchange } } - public ArrayList<AMQQueue> route(InboundMessage payload) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage payload) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java index db3b023479..35c4a8f9b2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -88,7 +88,7 @@ class HeadersBinding * Creates a binding for a set of mappings. Those mappings whose value is * null or the empty string are assumed only to be required headers, with * no constraint on the value. Those with a non-null value are assumed to - * define a required match of value. + * define a required match of value. * @param mappings the defined mappings this binding should use */ @@ -174,14 +174,21 @@ class HeadersBinding private boolean or(final AMQMessageHeader headers) { - if(required.isEmpty() || passesRequiredOr(headers)) + if(required.isEmpty()) { - return ((!matches.isEmpty()) && passesMatchesOr(headers)) - || (required.isEmpty() && matches.isEmpty()); + return matches.isEmpty() || passesMatchesOr(headers); } else { - return true; + if(!passesRequiredOr(headers)) + { + return !matches.isEmpty() && passesMatchesOr(headers); + } + else + { + return true; + } + } } @@ -190,7 +197,7 @@ class HeadersBinding for(Map.Entry<String,Object> entry : matches.entrySet()) { if(headers.containsHeader(entry.getKey()) - || ((entry.getValue() == null && headers.getHeader(entry.getKey()) == null) + && ((entry.getValue() == null && headers.getHeader(entry.getKey()) == null) || (entry.getValue().equals(headers.getHeader(entry.getKey()))))) { return true; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 12867b224d..fb43f97530 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -253,7 +253,7 @@ public class HeadersExchange extends AbstractExchange } } - public ArrayList<AMQQueue> route(InboundMessage payload) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage payload) { AMQMessageHeader header = payload.getMessageHeader(); if (_logger.isDebugEnabled()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 1b5e3448e1..bffdbe4a80 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -535,7 +535,7 @@ public class TopicExchange extends AbstractExchange return normalizedString; } - public ArrayList<AMQQueue> route(InboundMessage payload) throws AMQException + public ArrayList<AMQQueue> route(InboundMessage payload) { final AMQShortString routingKey = payload.getRoutingKey() == null diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java index d0b4ca6855..55b1802f88 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java @@ -133,7 +133,7 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB singleMessageCredit.useCreditForMessage(entry.getMessage());
if(entry.getMessage() instanceof AMQMessage)
{
- session.getProtocolOutputConverter().writeGetOk((AMQMessage)(entry.getMessage()), channel.getChannelId(),
+ session.getProtocolOutputConverter().writeGetOk(entry, channel.getChannelId(),
deliveryTag, queue.getMessageCount());
}
else
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java index 2b011ae5b6..6132c890c3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java @@ -81,7 +81,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR message = channel.getUnacknowledgedMessageMap().remove(deliveryTag); if(message != null) { - message.discard(channel.getStoreContext()); + message.discard(); } //sendtoDeadLetterQueue(msg) return; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java index 1ab1ea916e..54f8e70965 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java @@ -41,6 +41,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclareBody> @@ -60,11 +61,11 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException { - AMQProtocolSession session = stateManager.getProtocolSession(); + final AMQProtocolSession session = stateManager.getProtocolSession(); VirtualHost virtualHost = session.getVirtualHost(); ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry(); QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - MessageStore store = virtualHost.getMessageStore(); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); if (!body.getPassive()) @@ -115,6 +116,25 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar store.createQueue(queue, body.getArguments()); } queueRegistry.registerQueue(queue); + if(queue.isExclusive() && !queue.isAutoDelete()) + { + final AMQQueue q = queue; + queue.setExclusiveOwner(session); + final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task() + { + public void doTask(AMQProtocolSession session) throws AMQException + { + q.setExclusiveOwner(null); + } + }; + session.addSessionCloseTask(sessionCloseTask); + queue.addQueueDeleteTask(new AMQQueue.Task() { + public void doTask(AMQQueue queue) throws AMQException + { + session.removeSessionCloseTask(sessionCloseTask); + } + }); + } if (autoRegister) { Exchange defaultExchange = exchangeRegistry.getDefaultExchange(); @@ -125,16 +145,17 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar } } else if (queue.getPrincipalHolder() != null - && queue.getPrincipalHolder().getPrincipal() != null - && queue.getPrincipalHolder().getPrincipal().getName() != null - && !session.getContextKey().equals(new AMQShortString(queue.getPrincipalHolder().getPrincipal().getName()))) + && queue.getPrincipalHolder().getPrincipal() != null + && queue.getPrincipalHolder().getPrincipal().getName() != null + && (!queue.getPrincipalHolder().getPrincipal().getName().equals(session.getPrincipal().getName()) + || ((!body.getPassive() && queue.getExclusiveOwner() != null && queue.getExclusiveOwner() != session)))) { throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "')," + " as exclusive queue with same name " + "declared on another client ID('" + queue.getPrincipalHolder().getPrincipal().getName() + "')"); - } + } AMQChannel channel = session.getChannel(channelId); if (channel == null) @@ -201,7 +222,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar } }); }// if exclusive and not durable - + return queue; } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java index b397db9246..8417492171 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java @@ -31,6 +31,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.security.access.Permission; @@ -62,7 +63,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB AMQProtocolSession session = stateManager.getProtocolSession(); VirtualHost virtualHost = session.getVirtualHost(); QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - MessageStore store = virtualHost.getMessageStore(); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); AMQQueue queue; if (body.getQueue() == null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java index 2768518f53..3e0f2182b7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java @@ -33,7 +33,6 @@ import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.access.Permission;
public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
{
@@ -106,7 +105,7 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied");
}
- long purged = queue.clearQueue(channel.getStoreContext());
+ long purged = queue.clearQueue();
if(!body.getNowait())
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java index da4687ac56..abd2bccc8d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java @@ -26,7 +26,6 @@ import org.apache.qpid.framing.TxCommitBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; @@ -62,22 +61,16 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody> { throw body.getChannelNotFoundException(channelId); } - StoreContext.setCurrentContext(channel.getStoreContext()); channel.commit(); MethodRegistry methodRegistry = session.getMethodRegistry(); AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody(); session.writeFrame(responseBody.generateFrame(channelId)); - - channel.processReturns(); + } catch (AMQException e) { throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage()); } - finally - { - StoreContext.clearCurrentContext(); - } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java index 5f402f3fda..4643dee0a3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java @@ -44,9 +44,9 @@ public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBod { } - public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, int channelId) throws AMQException + public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, final int channelId) throws AMQException { - AMQProtocolSession session = stateManager.getProtocolSession(); + final AMQProtocolSession session = stateManager.getProtocolSession(); try { @@ -57,17 +57,22 @@ public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBod throw body.getChannelNotFoundException(channelId); } - channel.rollback(); - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); + final MethodRegistry methodRegistry = session.getMethodRegistry(); + final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody(); + + Runnable task = new Runnable() + { + + public void run() + { + session.writeFrame(responseBody.generateFrame(channelId)); + } + }; + + channel.rollback(task); - //Now resend all the unacknowledged messages back to the original subscribers. - //(Must be done after the TxnRollback-ok response). - // Why, are we not allowed to send messages back to client before the ok method? - channel.resend(false); } catch (AMQException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java index 2ba5eb04d9..1b4b9a270c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java @@ -23,23 +23,37 @@ package org.apache.qpid.server.message; import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.MessageCleanupException; +import javax.swing.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + public class AMQMessageReference extends MessageReference<AMQMessage> { + + public AMQMessageReference(AMQMessage message) { super(message); } - protected void onReference() + protected void onReference(AMQMessage message) { - getMessage().incrementReference(); + message.incrementReference(); } - protected void onRelease() + protected void onRelease(AMQMessage message) { try { - getMessage().decrementReference(); + if(message !=null) + { + message.decrementReference(); + } + else + { + //TODO + System.err.println("Shouldn't happen!!!!"); + } } catch (MessageCleanupException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java new file mode 100755 index 0000000000..c32f80fc5b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java @@ -0,0 +1,27 @@ +/* +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +* +*/ +package org.apache.qpid.server.message; + +public interface EnqueableMessage +{ + Long getMessageNumber(); + boolean isPersistent(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java index 7974c40b04..055403ff08 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java @@ -33,12 +33,12 @@ public abstract class MessageReference<M extends ServerMessage> public MessageReference(M message) { _message = message; - onReference(); + onReference(message); } - abstract protected void onReference(); + abstract protected void onReference(M message); - abstract protected void onRelease(); + abstract protected void onRelease(M message); public M getMessage() { @@ -47,21 +47,11 @@ public abstract class MessageReference<M extends ServerMessage> public void release() { - ServerMessage message = _messageUpdater.getAndSet(this,null); + M message = (M) _messageUpdater.getAndSet(this,null); if(message != null) { - onRelease(); + onRelease(message); } } - @Override - protected void finalize() throws Throwable - { - if(_message != null) - { - onRelease(); - _message = null; - } - super.finalize(); //To change body of overridden methods use File | Settings | File Templates. - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java index e5d15e29f9..7702e4729f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java @@ -20,9 +20,7 @@ */ package org.apache.qpid.server.message; -import org.apache.qpid.server.queue.Filterable; - -public interface ServerMessage extends Filterable +public interface ServerMessage extends EnqueableMessage { String getRoutingKey(); @@ -30,8 +28,6 @@ public interface ServerMessage extends Filterable boolean isPersistent(); - boolean isRedelivered(); - long getSize(); boolean isImmediate(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java index 784d47a840..ed189c49c4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java @@ -27,12 +27,12 @@ public class TransferMessageReference extends MessageReference<MessageTransferMe super(message); } - protected void onReference() + protected void onReference(MessageTransferMessage message) { } - protected void onRelease() + protected void onRelease(MessageTransferMessage message) { } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java index e01c5aabbf..5b6150f964 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java @@ -27,11 +27,16 @@ package org.apache.qpid.server.output;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.AMQException;
+import java.util.Iterator;
+
public interface ProtocolOutputConverter
{
void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag);
@@ -41,16 +46,16 @@ public interface ProtocolOutputConverter ProtocolOutputConverter newInstance(AMQProtocolSession session);
}
- void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException;
- void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
+ void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException;
byte getProtocolMinorVersion();
byte getProtocolMajorVersion();
- void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, Iterator<AMQDataBlock> bodyFrameIterator, int channelId, int replyCode, AMQShortString replyText)
throws AMQException;
void writeFrame(AMQDataBlock block);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java index 34eef881a6..304d543609 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java @@ -29,7 +29,7 @@ package org.apache.qpid.server.output.amqp0_8; import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.abstraction.ContentChunk;
@@ -41,6 +41,7 @@ import java.util.Iterator; public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
+ private final MethodRegistry _methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
public static Factory getInstanceFactory()
{
@@ -67,18 +68,17 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return _protocolSession;
}
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ AMQMessage message = (AMQMessage) entry.getMessage();
+ AMQDataBlock deliver = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
message.getContentHeaderBody());
final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ final int bodyCount = messageHandle.getBodyCount();
if(bodyCount == 0)
{
@@ -95,7 +95,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter // Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
//
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+ ContentChunk cb = messageHandle.getContentChunk(0);
AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
@@ -107,7 +107,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter //
for(int i = 1; i < bodyCount; i++)
{
- cb = messageHandle.getContentChunk(storeContext, i);
+ cb = messageHandle.getContentChunk(i);
writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
}
@@ -118,19 +118,19 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+ AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
message.getContentHeaderBody());
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ final int bodyCount = messageHandle.getBodyCount();
if(bodyCount == 0)
{
SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
@@ -145,7 +145,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter // Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
//
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+ ContentChunk cb = messageHandle.getContentChunk(0);
AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
@@ -157,7 +157,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter //
for(int i = 1; i < bodyCount; i++)
{
- cb = messageHandle.getContentChunk(storeContext, i);
+ cb = messageHandle.getContentChunk(i);
writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
}
@@ -168,17 +168,17 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
- private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ private AMQDataBlock createEncodedDeliverFrame(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+
BasicDeliverBody deliverBody =
- methodRegistry.createBasicDeliverBody(consumerTag,
+ _methodRegistry.createBasicDeliverBody(consumerTag,
deliveryTag,
- messageHandle.isRedelivered(),
+ entry.isRedelivered(),
pb.getExchange(),
pb.getRoutingKey());
AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
@@ -187,16 +187,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return deliverFrame;
}
- private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ private AMQDataBlock createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
throws AMQException
{
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
BasicGetOkBody getOkBody =
- methodRegistry.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
+ _methodRegistry.createBasicGetOkBody(deliveryTag,
+ entry.isRedelivered(),
pb.getExchange(),
pb.getRoutingKey(),
queueSize);
@@ -215,28 +214,33 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
{
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
BasicReturnBody basicReturnBody =
- methodRegistry.createBasicReturnBody(replyCode,
+ _methodRegistry.createBasicReturnBody(replyCode,
replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
return returnFrame;
}
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo,
+ ContentHeaderBody header,
+ Iterator<AMQDataBlock> bodyFrameIterator,
+ int channelId,
+ int replyCode,
+ AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
+
+ AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
+ header);
+
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
//
// Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
@@ -274,8 +278,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
{
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
+ BasicCancelOkBody basicCancelOkBody = _methodRegistry.createBasicCancelOkBody(consumerTag);
writeFrame(basicCancelOkBody.generateFrame(channelId));
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java index 9f2f182138..6363be3dfc 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
@@ -68,18 +68,17 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return _protocolSession;
}
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ AMQMessage message = (AMQMessage) entry.getMessage();
+ AMQBody deliverBody = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ final int bodyCount = messageHandle.getBodyCount();
if(bodyCount == 0)
{
@@ -96,7 +95,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter // Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
//
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+ ContentChunk cb = messageHandle.getContentChunk(0);
AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
@@ -108,7 +107,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter //
for(int i = 1; i < bodyCount; i++)
{
- cb = messageHandle.getContentChunk(storeContext, i);
+ cb = messageHandle.getContentChunk(i);
writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
}
@@ -126,18 +125,17 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
-
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+ AMQFrame deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ final int bodyCount = messageHandle.getBodyCount();
if(bodyCount == 0)
{
SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
@@ -152,7 +150,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter // Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
//
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+ ContentChunk cb = messageHandle.getContentChunk(0);
AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
@@ -164,7 +162,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter //
for(int i = 1; i < bodyCount; i++)
{
- cb = messageHandle.getContentChunk(storeContext, i);
+ cb = messageHandle.getContentChunk(i);
writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
}
@@ -175,14 +173,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
- private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
+ private AMQBody createEncodedDeliverFrame(QueueEntry entry, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
throws AMQException
{
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final MessagePublishInfo pb = message.getMessagePublishInfo();
final AMQMessageHandle messageHandle = message.getMessageHandle();
- final boolean isRedelivered = messageHandle.isRedelivered();
+ final boolean isRedelivered = entry.isRedelivered();
final AMQShortString exchangeName = pb.getExchange();
final AMQShortString routingKey = pb.getRoutingKey();
@@ -237,16 +236,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return returnBlock;
}
- private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ private AMQFrame createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
throws AMQException
{
+ final AMQMessage message = (AMQMessage) entry.getMessage();
final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
BasicGetOkBody getOkBody =
METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
+ entry.isRedelivered(),
pb.getExchange(),
pb.getRoutingKey(),
queueSize);
@@ -265,27 +263,29 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
{
BasicReturnBody basicReturnBody =
METHOD_REGISTRY.createBasicReturnBody(replyCode,
replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
return returnFrame;
}
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, Iterator<AMQDataBlock> bodyFrameIterator, int channelId, int replyCode, AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+ AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
+
+
+ AMQDataBlock contentHeader = createContentHeaderBlock(channelId, header);
+
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
//
// Optimise the case where we have a single content body. In that case we create a composite block
// so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index be23af9d82..5895a22f1a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -200,8 +200,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { return _actor; } - - @Override + public void received(final ByteBuffer msg) { _lastIoTime = System.currentTimeMillis(); @@ -210,7 +209,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable() { - @Override public void run() { // Decode buffer @@ -457,7 +455,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _writtenBytes += buf.remaining(); Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable() { - @Override public void run() { _networkDriver.send(buf); @@ -925,7 +922,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol return _dispatcher; } - @Override public void closed() { try @@ -938,25 +934,21 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } } - @Override public void readerIdle() { // Nothing } - @Override public void setNetworkDriver(NetworkDriver driver) { _networkDriver = driver; } - @Override public void writerIdle() { _networkDriver.send(HeartbeatBody.FRAME.toNioByteBuffer()); } - @Override public void exception(Throwable throwable) { if (throwable instanceof AMQProtocolHeaderException) @@ -985,19 +977,16 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } } - @Override public void init() { // Do nothing } - @Override public void setSender(Sender<ByteBuffer> sender) { // Do nothing } - @Override public long getReadBytes() { return _readBytes; @@ -1023,7 +1012,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol return (_clientVersion == null) ? null : _clientVersion.toString(); } - @Override public void closeIfLingeringClosedChannels() { for (Entry<Integer, Long>id : _closingChannelsList.entrySet()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java index aecf7a6839..924e395521 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java @@ -222,6 +222,8 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin void commitTransactions(AMQChannel channel) throws AMQException; + void rollbackTransactions(AMQChannel channel) throws AMQException; + List<AMQChannel> getChannels(); void closeIfLingeringClosedChannels(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java index 393d4ab4cb..67c1e51f6e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java @@ -227,7 +227,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); } - _protocolSession.commitTransactions(channel); + _protocolSession.rollbackTransactions(channel); } catch (AMQException ex) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java index da682ed11e..7004bac519 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java @@ -31,18 +31,18 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.message.*; import java.util.Iterator; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CopyOnWriteArrayList; /** * A deliverable message. */ -public class AMQMessage implements Filterable, ServerMessage +public class AMQMessage implements ServerMessage { /** Used for debugging purposes. */ private static final Logger _log = Logger.getLogger(AMQMessage.class); @@ -51,9 +51,6 @@ public class AMQMessage implements Filterable, ServerMessage private final AMQMessageHandle _messageHandle; - /** Holds the transactional context in which this message is being processed. */ - private StoreContext _storeContext; - /** Flag to indicate that this message requires 'immediate' delivery. */ private static final byte IMMEDIATE = 0x01; @@ -71,7 +68,7 @@ public class AMQMessage implements Filterable, ServerMessage private final long _size; - private AMQProtocolSession.ProtocolSessionIdentifier _sessionIdentifier; + private Object _sessionIdentifier; private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER); private final AMQMessageHeader _messageHeader; @@ -97,7 +94,7 @@ public class AMQMessage implements Filterable, ServerMessage { try { - return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1); + return _index < (_messageHandle.getBodyCount() - 1); } catch (AMQException e) { @@ -113,8 +110,8 @@ public class AMQMessage implements Filterable, ServerMessage { AMQBody cb = - getProtocolVersionMethodConverter().convertToBody(_messageHandle.getContentChunk(getStoreContext(), - ++_index)); + getProtocolVersionMethodConverter().convertToBody(_messageHandle.getContentChunk( + ++_index)); return new AMQFrame(_channel, cb); } @@ -137,15 +134,6 @@ public class AMQMessage implements Filterable, ServerMessage } } - public void clearStoreContext() - { - _storeContext = new StoreContext(); - } - - public StoreContext getStoreContext() - { - return _storeContext; - } private class BodyContentIterator implements Iterator<ContentChunk> { @@ -156,7 +144,7 @@ public class AMQMessage implements Filterable, ServerMessage { try { - return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1); + return _index < (_messageHandle.getBodyCount() - 1); } catch (AMQException e) { @@ -170,7 +158,7 @@ public class AMQMessage implements Filterable, ServerMessage { try { - return _messageHandle.getContentChunk(getStoreContext(), ++_index); + return _messageHandle.getContentChunk(++_index); } catch (AMQException e) { @@ -197,13 +185,12 @@ public class AMQMessage implements Filterable, ServerMessage * * @throws AMQException */ - public AMQMessage(Long messageId, MessageStore store, MessageHandleFactory factory, TransactionalContext txnConext) + public AMQMessage(Long messageId, MessageStore store, MessageHandleFactory factory) throws AMQException { _messageHandle = factory.createMessageHandle(messageId, store, true); - _storeContext = txnConext.getStoreContext(); - _size = _messageHandle.getBodySize(txnConext.getStoreContext()); - _messageHeader = new ContentHeaderBodyAdapter(_messageHandle.getContentHeaderBody(txnConext.getStoreContext())); + _size = _messageHandle.getBodySize(); + _messageHeader = new ContentHeaderBodyAdapter(_messageHandle.getContentHeaderBody()); } /** @@ -217,19 +204,29 @@ public class AMQMessage implements Filterable, ServerMessage */ public AMQMessage( AMQMessageHandle messageHandle, - StoreContext storeConext, MessagePublishInfo info) throws AMQException { + this(messageHandle, messageHandle.getContentHeaderBody(), messageHandle.getBodySize(), info); + } + + public AMQMessage( + AMQMessageHandle messageHandle, + ContentHeaderBody chb, + long size, + MessagePublishInfo info) + throws AMQException + + { _messageHandle = messageHandle; - _storeContext = storeConext; - _messageHeader = new ContentHeaderBodyAdapter(_messageHandle.getContentHeaderBody(storeConext)); + + _messageHeader = new ContentHeaderBodyAdapter(chb); if(info.isImmediate()) { _flags |= IMMEDIATE; } - _size = messageHandle.getBodySize(storeConext); + _size = size; } @@ -238,7 +235,6 @@ public class AMQMessage implements Filterable, ServerMessage { _messageHandle = msg._messageHandle; _messageHeader = msg._messageHeader; - _storeContext = msg._storeContext; _flags = msg._flags; _size = msg._size; @@ -274,7 +270,7 @@ public class AMQMessage implements Filterable, ServerMessage public ContentHeaderBody getContentHeaderBody() throws AMQException { - return _messageHandle.getContentHeaderBody(getStoreContext()); + return _messageHandle.getContentHeaderBody(); } @@ -303,7 +299,8 @@ public class AMQMessage implements Filterable, ServerMessage /* Threadsafe. Increment the reference count on the message. */ public boolean incrementReference(int count) { - if(_referenceCount.addAndGet(count) <= 1) + + if(_referenceCount.addAndGet(count) <= 0) { _referenceCount.addAndGet(-count); return false; @@ -325,7 +322,6 @@ public class AMQMessage implements Filterable, ServerMessage */ public void decrementReference() throws MessageCleanupException { - int count = _referenceCount.decrementAndGet(); // note that the operation of decrementing the reference count and then removing the message does not @@ -343,9 +339,10 @@ public class AMQMessage implements Filterable, ServerMessage { // must check if the handle is null since there may be cases where we decide to throw away a message // and the handle has not yet been constructed - if (_messageHandle != null) + if (_messageHandle != null && isPersistent()) { - _messageHandle.removeMessage(StoreContext.getCurrentContext()); + _messageHandle.removeMessage(); + } } catch (AMQException e) @@ -397,7 +394,7 @@ public class AMQMessage implements Filterable, ServerMessage * @returns true if the message is marked for immediate delivery but has not been marked as delivered * to a consumer */ - public boolean immediateAndNotDelivered() + public boolean immediateAndNotDelivered() { return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE; @@ -406,17 +403,7 @@ public class AMQMessage implements Filterable, ServerMessage public MessagePublishInfo getMessagePublishInfo() throws AMQException { - return _messageHandle.getMessagePublishInfo(getStoreContext()); - } - - public boolean isRedelivered() - { - return _messageHandle.isRedelivered(); - } - - public void setRedelivered(boolean redelivered) - { - _messageHandle.setRedelivered(redelivered); + return _messageHandle.getMessagePublishInfo(); } public long getArrivalTime() @@ -488,37 +475,18 @@ public class AMQMessage implements Filterable, ServerMessage return getMessageId(); } - public Object getPublisherClientInstance() - { - //todo store sessionIdentifier/client id with message in store - //Currently the _sessionIdentifier will be null if the message has been - // restored from a message Store - if (_sessionIdentifier == null) - { - return null; - } - else - { - return _sessionIdentifier.getSessionInstance(); - } - } - + public Object getPublisherIdentifier() { //todo store sessionIdentifier/client id with message in store //Currently the _sessionIdentifier will be null if the message has been // restored from a message Store - if (_sessionIdentifier == null) - { - return null; - } - else - { - return _sessionIdentifier.getSessionIdentifier(); - } + + return _sessionIdentifier; + } - public void setClientIdentifier(final AMQProtocolSession.ProtocolSessionIdentifier sessionIdentifier) + public void setClientIdentifier(final Object sessionIdentifier) { _sessionIdentifier = sessionIdentifier; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java index 0ddd4e4d92..d8ab6ee9b2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; @@ -32,7 +31,7 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; */ public interface AMQMessageHandle { - ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException; + ContentHeaderBody getContentHeaderBody() throws AMQException; /** * @@ -44,12 +43,12 @@ public interface AMQMessageHandle /** * @return the number of body frames associated with this message */ - int getBodyCount(StoreContext context) throws AMQException; + int getBodyCount() throws AMQException; /** * @return the size of the body */ - long getBodySize(StoreContext context) throws AMQException; + long getBodySize() throws AMQException; /** * Get a particular content body @@ -57,23 +56,18 @@ public interface AMQMessageHandle * @return a content body * @throws IllegalArgumentException if the index is invalid */ - ContentChunk getContentChunk(StoreContext context, int index) throws IllegalArgumentException, AMQException; + ContentChunk getContentChunk(int index) throws IllegalArgumentException, AMQException; - void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody) throws AMQException; + void addContentBodyFrame(ContentChunk contentBody, boolean isLastContentBody) throws AMQException; - MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException; - - boolean isRedelivered(); - - void setRedelivered(boolean redelivered); + MessagePublishInfo getMessagePublishInfo() throws AMQException; boolean isPersistent(); - void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo, - ContentHeaderBody contentHeaderBody) - throws AMQException; + MessageMetaData setPublishAndContentHeaderBody(MessagePublishInfo messagePublishInfo, + ContentHeaderBody contentHeaderBody); - void removeMessage(StoreContext storeContext) throws AMQException; + void removeMessage() throws AMQException; long getArrivalTime(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java index 2383d6e0be..37e8029796 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java @@ -61,19 +61,25 @@ public class AMQPriorityQueue extends SimpleAMQQueue while(subIter.advance() && !entry.isAcquired()) { final Subscription subscription = subIter.getNode().getSubscription(); - QueueContext context = (QueueContext) subscription.getQueueContext(); - QueueEntry subnode = context._lastSeenEntry; - QueueEntry released = context._releasedEntry; - while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired() && (released == null || released.compareTo(entry) < 0)) + if(!subscription.isClosed()) { - if(_releasedUpdater.compareAndSet(context,released,entry)) + QueueContext context = (QueueContext) subscription.getQueueContext(); + if(context != null) { - break; - } - else - { - subnode = context._lastSeenEntry; - released = context._releasedEntry; + QueueEntry subnode = context._lastSeenEntry; + QueueEntry released = context._releasedEntry; + while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired() && (released == null || released.compareTo(entry) < 0)) + { + if(_releasedUpdater.compareAndSet(context,released,entry)) + { + break; + } + else + { + subnode = context._lastSeenEntry; + released = context._releasedEntry; + } + } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index 7daa10578f..c5691792d4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -26,11 +26,11 @@ import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.AMQException; @@ -58,6 +58,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue> PrincipalHolder getPrincipalHolder(); void setPrincipalHolder(PrincipalHolder principalHolder); + void setExclusiveOwner(Object owner); + Object getExclusiveOwner(); + VirtualHost getVirtualHost(); @@ -100,11 +103,11 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue> QueueEntry enqueue(ServerMessage message) throws AMQException; - void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException; + void requeue(QueueEntry entry); void requeue(QueueEntryImpl storeContext, Subscription subscription); - void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException; + void dequeue(QueueEntry entry); @@ -142,7 +145,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue> void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext); - void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext); + void removeMessagesFromQueue(long fromMessageId, long toMessageId); @@ -182,9 +185,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue> - void deleteMessageFromTop(StoreContext storeContext) throws AMQException; + void deleteMessageFromTop(); - long clearQueue(StoreContext storeContext) throws AMQException; + long clearQueue(); /** * Checks the status of messages on the queue, purging expired ones, firing age related alerts etc. diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java index d6309955a2..795da14163 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java @@ -39,7 +39,6 @@ import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.message.ServerMessage; import javax.management.JMException; -import javax.management.MBeanException; import javax.management.MBeanNotificationInfo; import javax.management.Notification; import javax.management.OperationsException; @@ -73,12 +72,6 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que private static final SimpleDateFormat _dateFormat = new SimpleDateFormat("MM-dd-yy HH:mm:ss.SSS z"); - /** - * Since the MBean is not associated with a real channel we can safely create our own store context - * for use in the few methods that require one. - */ - private StoreContext _storeContext = new StoreContext(); - private AMQQueue _queue = null; private String _queueName = null; // OpenMBean data types for viewMessages method @@ -301,14 +294,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que */ public void deleteMessageFromTop() throws JMException { - try - { - _queue.deleteMessageFromTop(_storeContext); - } - catch (AMQException ex) - { - throw new MBeanException(ex, ex.toString()); - } + _queue.deleteMessageFromTop(); } /** @@ -319,14 +305,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que */ public Long clearQueue() throws JMException { - try - { - return _queue.clearQueue(_storeContext); - } - catch (AMQException ex) - { - throw new MBeanException(ex, ex.toString()); - } + return _queue.clearQueue(); } /** @@ -438,14 +417,15 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que for (int i = 0; i < size ; i++) { long position = startPosition + i; - ServerMessage serverMsg = list.get(i).getMessage(); + final QueueEntry queueEntry = list.get(i); + ServerMessage serverMsg = queueEntry.getMessage(); if(serverMsg instanceof AMQMessage) { AMQMessage msg = (AMQMessage) serverMsg; ContentHeaderBody headerBody = msg.getContentHeaderBody(); // Create header attributes list String[] headerAttributes = getMessageHeaderProperties(headerBody); - Object[] itemValues = { msg.getMessageId(), headerAttributes, headerBody.bodySize, msg.isRedelivered(), position}; + Object[] itemValues = { msg.getMessageId(), headerAttributes, headerBody.bodySize, queueEntry.isRedelivered(), position}; CompositeData messageData = new CompositeDataSupport(_messageDataType, VIEW_MSGS_COMPOSITE_ITEM_NAMES, itemValues); _messageList.put(messageData); } @@ -509,7 +489,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); } - _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, _storeContext); + _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, new StoreContext()); } /** @@ -525,7 +505,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); } - _queue.removeMessagesFromQueue(fromMessageId, toMessageId, _storeContext); + _queue.removeMessagesFromQueue(fromMessageId, toMessageId); } /** @@ -542,7 +522,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); } - _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, _storeContext); + _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, new StoreContext()); } /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java index 35ad5be4e0..bf0e803132 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.queue; -import java.util.LinkedList; import java.util.List; import java.util.Collections; import java.util.ArrayList; @@ -29,7 +28,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.server.store.StoreContext; /** */ @@ -42,8 +40,6 @@ public class InMemoryMessageHandle implements AMQMessageHandle private List<ContentChunk> _contentBodies; - private boolean _redelivered; - private long _arrivalTime; private final Long _messageId; @@ -53,7 +49,7 @@ public class InMemoryMessageHandle implements AMQMessageHandle _messageId = messageId; } - public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException + public ContentHeaderBody getContentHeaderBody() throws AMQException { return _contentHeaderBody; } @@ -63,17 +59,17 @@ public class InMemoryMessageHandle implements AMQMessageHandle return _messageId; } - public int getBodyCount(StoreContext context) + public int getBodyCount() { return _contentBodies.size(); } - public long getBodySize(StoreContext context) throws AMQException + public long getBodySize() throws AMQException { - return getContentHeaderBody(context).bodySize; + return getContentHeaderBody().bodySize; } - public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException + public ContentChunk getContentChunk(int index) throws AMQException, IllegalArgumentException { if (index > _contentBodies.size() - 1) { @@ -83,7 +79,7 @@ public class InMemoryMessageHandle implements AMQMessageHandle return _contentBodies.get(index); } - public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody) + public void addContentBodyFrame(ContentChunk contentBody, boolean isLastContentBody) throws AMQException { if(_contentBodies == null) @@ -104,22 +100,11 @@ public class InMemoryMessageHandle implements AMQMessageHandle } } - public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException + public MessagePublishInfo getMessagePublishInfo() throws AMQException { return _messagePublishInfo; } - public boolean isRedelivered() - { - return _redelivered; - } - - - public void setRedelivered(boolean redelivered) - { - _redelivered = redelivered; - } - public boolean isPersistent() { return false; @@ -131,9 +116,8 @@ public class InMemoryMessageHandle implements AMQMessageHandle * @param contentHeaderBody * @throws AMQException */ - public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo, - ContentHeaderBody contentHeaderBody) - throws AMQException + public MessageMetaData setPublishAndContentHeaderBody(MessagePublishInfo messagePublishInfo, + ContentHeaderBody contentHeaderBody) { _messagePublishInfo = messagePublishInfo; _contentHeaderBody = contentHeaderBody; @@ -142,9 +126,11 @@ public class InMemoryMessageHandle implements AMQMessageHandle _contentBodies = Collections.EMPTY_LIST; } _arrivalTime = System.currentTimeMillis(); + MessageMetaData mmd = new MessageMetaData(messagePublishInfo, contentHeaderBody, _contentBodies == null ? 0 : _contentBodies.size(), _arrivalTime); + return mmd; } - public void removeMessage(StoreContext storeContext) throws AMQException + public void removeMessage() throws AMQException { // NO OP } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java index 8553f8bf16..726d99f8b3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java @@ -25,22 +25,20 @@ import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.exchange.NoRouteException; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ContentHeaderBodyAdapter; -import org.apache.qpid.server.message.AMQMessageReference; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.AMQException; import org.apache.log4j.Logger; import java.util.ArrayList; -public class IncomingMessage implements Filterable, InboundMessage +public class IncomingMessage implements Filterable, InboundMessage, EnqueableMessage { /** Used for debugging purposes. */ @@ -51,12 +49,9 @@ public class IncomingMessage implements Filterable, InboundMessage private final MessagePublishInfo _messagePublishInfo; private ContentHeaderBody _contentHeaderBody; + private AMQMessageHandle _messageHandle; private final Long _messageId; - private final TransactionalContext _txnContext; - - private static final boolean MSG_AUTH = - ApplicationRegistry.getInstance().getConfiguration().getMsgAuth(); /** @@ -71,24 +66,21 @@ public class IncomingMessage implements Filterable, InboundMessage */ private ArrayList<AMQQueue> _destinationQueues; - private AMQProtocolSession _publisher; - private MessageStore _messageStore; private long _expiration; - + private Exchange _exchange; private AMQMessageHeader _messageHeader; + private int _receivedChunkCount = 0; + + public IncomingMessage(final Long messageId, final MessagePublishInfo info, - final TransactionalContext txnContext, final AMQProtocolSession publisher) { _messageId = messageId; _messagePublishInfo = info; - _txnContext = txnContext; - _publisher = publisher; - } public void setContentHeaderBody(final ContentHeaderBody contentHeaderBody) throws AMQException @@ -128,132 +120,33 @@ public class IncomingMessage implements Filterable, InboundMessage } - public void routingComplete(final MessageStore store, + public MessageMetaData routingComplete(final MessageStore store, final MessageHandleFactory factory) throws AMQException { - - final boolean persistent = isPersistent(); - _messageHandle = factory.createMessageHandle(_messageId, store, persistent); - if (persistent) - { - _txnContext.beginTranIfNecessary(); - // enqueuing the messages ensure that if required the destinations are recorded to a - // persistent store - - if(_destinationQueues != null) - { - for (int i = 0; i < _destinationQueues.size(); i++) - { - store.enqueueMessage(_txnContext.getStoreContext(), - _destinationQueues.get(i), _messageId); - } - } - } + _messageHandle = factory.createMessageHandle(_messageId, store, isPersistent()); + return _messageHandle.setPublishAndContentHeaderBody(_messagePublishInfo, _contentHeaderBody); } - public AMQMessage deliverToQueues() - throws AMQException - { - - // we get a reference to the destination queues now so that we can clear the - // transient message data as quickly as possible - if (_logger.isDebugEnabled()) - { - _logger.debug("Delivering message " + _messageId + " to " + _destinationQueues); - } - - AMQMessage message = null; - AMQMessageReference ref = null; - - try - { - // first we allow the handle to know that the message has been fully received. This is useful if it is - // maintaining any calculated values based on content chunks - _messageHandle.setPublishAndContentHeaderBody(_txnContext.getStoreContext(), - _messagePublishInfo, getContentHeader()); - - - - message = new AMQMessage(_messageHandle,_txnContext.getStoreContext(), _messagePublishInfo); - ref = (AMQMessageReference) message.newReference(); - - message.setExpiration(_expiration); - message.setClientIdentifier(_publisher.getSessionIdentifier()); - - // we then allow the transactional context to do something with the message content - // now that it has all been received, before we attempt delivery - _txnContext.messageFullyReceived(isPersistent()); - - AMQShortString userID = getContentHeader().properties instanceof BasicContentHeaderProperties ? - ((BasicContentHeaderProperties) getContentHeader().properties).getUserId() : null; - - if (MSG_AUTH && !_publisher.getPrincipal().getName().equals(userID == null? "" : userID.toString())) - { - throw new UnauthorizedAccessException("Acccess Refused",message); - } - - if ((_destinationQueues == null) || _destinationQueues.size() == 0) - { - - if (isMandatory() || isImmediate()) - { - throw new NoRouteException("No Route for message", message); - - } - else - { - _logger.warn("MESSAGE DISCARDED: No routes for message - " + message); - } - } - else - { - int offset; - final int queueCount = _destinationQueues.size(); - - if(queueCount == 1) - { - offset = 0; - } - else - { - offset = ((int)(message.getMessageId().longValue())) % queueCount; - if(offset < 0) - { - offset = -offset; - } - } - for (int i = offset; i < queueCount; i++) - { - // normal deliver so add this message at the end. - _txnContext.deliver(_destinationQueues.get(i), message); - } - for (int i = 0; i < offset; i++) - { - // normal deliver so add this message at the end. - _txnContext.deliver(_destinationQueues.get(i), message); - } - } - message.clearStoreContext(); - return message; - } - finally - { - // Remove refence for routing process . Reference count should now == delivered queue count + public ArrayList<AMQQueue> getDestinationQueues() + { + return _destinationQueues; + } - if(ref != null) ref.release(); - } + public AMQMessageHandle getMessageHandle() + { + return _messageHandle; } - public void addContentBodyFrame(final ContentChunk contentChunk) + + public int addContentBodyFrame(final ContentChunk contentChunk) throws AMQException { _bodyLengthReceived += contentChunk.getSize(); - - _messageHandle.addContentBodyFrame(_txnContext.getStoreContext(), contentChunk, allContentReceived()); - + _messageHandle.addContentBodyFrame(contentChunk, allContentReceived()); + return _receivedChunkCount++; } public boolean allContentReceived() @@ -305,7 +198,7 @@ public class IncomingMessage implements Filterable, InboundMessage ((BasicContentHeaderProperties) getContentHeader().properties).getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT; } - + public boolean isRedelivered() { return false; @@ -316,12 +209,7 @@ public class IncomingMessage implements Filterable, InboundMessage return getContentHeader().bodySize; } - public void setMessageStore(final MessageStore messageStore) - { - _messageStore = messageStore; - } - - public Long getMessageId() + public Long getMessageNumber() { return _messageId; } @@ -331,7 +219,7 @@ public class IncomingMessage implements Filterable, InboundMessage _exchange = e; } - public void route() throws AMQException + public void route() { enqueue(_exchange.route(this)); @@ -341,4 +229,21 @@ public class IncomingMessage implements Filterable, InboundMessage { _destinationQueues = queues; } + + public MessagePublishInfo getMessagePublishInfo() + { + return _messagePublishInfo; + } + + public long getExpiration() + { + return _expiration; + } + + public int getReceivedChunkCount() + { + return _receivedChunkCount; + } + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java index 7e4871158c..87b0267b0f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java @@ -1,9 +1,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.message.ServerMessage; /* @@ -26,18 +24,18 @@ import org.apache.qpid.server.message.ServerMessage; * under the License. * */ -public interface QueueEntry extends Comparable<QueueEntry> +public interface QueueEntry extends Comparable<QueueEntry>, Filterable { - - public static enum State { AVAILABLE, ACQUIRED, EXPIRED, DEQUEUED, - DELETED + DELETED; + + } public static interface StateChangeListener @@ -123,6 +121,27 @@ public interface QueueEntry extends Comparable<QueueEntry> } } + public final class SubscriptionAssignedState extends EntryState + { + private final Subscription _subscription; + + public SubscriptionAssignedState(Subscription subscription) + { + _subscription = subscription; + } + + + public State getState() + { + return State.AVAILABLE; + } + + public Subscription getSubscription() + { + return _subscription; + } + } + final static EntryState AVAILABLE_STATE = new AvailableState(); final static EntryState DELETED_STATE = new DeletedState(); @@ -154,9 +173,9 @@ public interface QueueEntry extends Comparable<QueueEntry> boolean acquiredBySubscription(); boolean isAcquiredBy(Subscription subscription); - void setDeliveredToSubscription(); - void release(); + boolean releaseButRetain(); + boolean immediateAndNotDelivered(); @@ -172,15 +191,13 @@ public interface QueueEntry extends Comparable<QueueEntry> boolean isRejectedBy(Subscription subscription); - void requeue(StoreContext storeContext) throws AMQException; - void requeue(Subscription subscription); - void dequeue(final StoreContext storeContext) throws FailedDequeueException; + void dequeue(); - void dispose(final StoreContext storeContext) throws MessageCleanupException; + void dispose(); - void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException; + void discard(); boolean isQueueDeleted(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 4f43695b13..f10a4175db 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -21,10 +21,10 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.log4j.Logger; import java.util.Set; @@ -161,6 +161,24 @@ public class QueueEntryImpl implements QueueEntry private boolean acquire(final EntryState state) { boolean acquired = _stateUpdater.compareAndSet(this,AVAILABLE_STATE, state); + + // deal with the case where the node has been assigned to a given subscription already + // including the case that the node is assigned to a closed subscription + if(!acquired) + { + if(state != NON_SUBSCRIPTION_ACQUIRED_STATE) + { + EntryState currentState = _state; + if(currentState.getState() == State.AVAILABLE + && ((currentState == AVAILABLE_STATE) + || (((SubscriptionAcquiredState)state).getSubscription() == + ((SubscriptionAssignedState)currentState).getSubscription()) + || ((SubscriptionAssignedState)currentState).getSubscription().isClosed() )) + { + acquired = _stateUpdater.compareAndSet(this,currentState, state); + } + } + } if(acquired && _stateChangeListeners != null) { notifyStateChange(State.AVAILABLE, State.ACQUIRED); @@ -171,7 +189,12 @@ public class QueueEntryImpl implements QueueEntry public boolean acquire(Subscription sub) { - return acquire(sub.getOwningState()); + final boolean acquired = acquire(sub.getOwningState()); + if(acquired && !_deliveredToConsumer) + { + _deliveredToConsumer = true; + } + return acquired; } public boolean acquiredBySubscription() @@ -187,19 +210,51 @@ public class QueueEntryImpl implements QueueEntry && ((SubscriptionAcquiredState)state).getSubscription() == subscription; } - public void setDeliveredToSubscription() + public void release() { - _deliveredToConsumer = true; + _stateUpdater.set(this,AVAILABLE_STATE); + getQueue().requeue(this); + if(_stateChangeListeners != null) + { + notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE); + } + } - public void release() + public boolean releaseButRetain() { - _stateUpdater.set(this,AVAILABLE_STATE); + EntryState state = _state; + + boolean stateUpdated = false; + + if(state instanceof SubscriptionAcquiredState) + { + Subscription sub = ((SubscriptionAcquiredState) state).getSubscription(); + if(_stateUpdater.compareAndSet(this, state, sub.getAssignedState())) + { + System.err.println("Message released (and retained)" + getMessage().getMessageNumber()); + getQueue().requeue(this); + if(_stateChangeListeners != null) + { + notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE); + } + stateUpdated = true; + } + } + + return stateUpdated; + } public boolean immediateAndNotDelivered() { - return getMessage().isImmediate() && !_deliveredToConsumer; + return !_deliveredToConsumer && isImmediate(); + } + + private boolean isImmediate() + { + final ServerMessage message = getMessage(); + return message != null && message.isImmediate(); } public void setRedelivered(boolean b) @@ -207,6 +262,18 @@ public class QueueEntryImpl implements QueueEntry _redelivered = b; } + public AMQMessageHeader getMessageHeader() + { + final ServerMessage message = getMessage(); + return message == null ? null : message.getMessageHeader(); + } + + public boolean isPersistent() + { + final ServerMessage message = getMessage(); + return message != null && message.isPersistent(); + } + public boolean isRedelivered() { return _redelivered; @@ -261,16 +328,6 @@ public class QueueEntryImpl implements QueueEntry } } - - public void requeue(final StoreContext storeContext) throws AMQException - { - getQueue().requeue(storeContext, this); - if(_stateChangeListeners != null) - { - notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE); - } - } - public void requeue(Subscription subscription) { getQueue().requeue(this, subscription); @@ -280,7 +337,7 @@ public class QueueEntryImpl implements QueueEntry } } - public void dequeue(final StoreContext storeContext) throws FailedDequeueException + public void dequeue() { EntryState state = _state; @@ -292,7 +349,7 @@ public class QueueEntryImpl implements QueueEntry s.onDequeue(this); } - getQueue().dequeue(storeContext, this); + getQueue().dequeue(this); if(_stateChangeListeners != null) { notifyStateChange(state.getState() , QueueEntry.State.DEQUEUED); @@ -310,25 +367,23 @@ public class QueueEntryImpl implements QueueEntry } } - public void dispose(final StoreContext storeContext) throws MessageCleanupException + public void dispose() { if(delete()) { - StoreContext sc = StoreContext.setCurrentContext(storeContext); _message.release(); - StoreContext.setCurrentContext(sc); } } - public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException + public void discard() { //if the queue is null then the message is waiting to be acked, but has been removed. if (getQueue() != null) { - dequeue(storeContext); + dequeue(); } - dispose(storeContext); + dispose(); } public boolean isQueueDeleted() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index ab5972b26f..8865c7946a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -33,6 +33,9 @@ import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.messages.QueueMessages; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.LocalTransaction; /* * @@ -62,6 +65,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private PrincipalHolder _prinicpalHolder; + private Object _exclusiveOwner; + + static final class QueueContext implements Context { volatile QueueEntry _lastSeenEntry; @@ -258,12 +264,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public boolean isExclusive() { - return _owner != null; + return _exclusiveOwner != null; } public Map<String, Object> getArguments() { - return null; + return null; } public boolean isAutoDelete() @@ -301,11 +307,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener AMQShortString routingKey = new AMQShortString(bindingKey); exchange.registerQueue(routingKey, this, fieldTable); - + if (isDurable() && exchange.isDurable()) { - _virtualHost.getMessageStore().bindQueue(exchange, routingKey, this, fieldTable); + _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, fieldTable); } _bindings.addBinding(routingKey, fieldTable, exchange); @@ -318,7 +324,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener exchange.registerQueue(routingKey, this, arguments); if (isDurable() && exchange.isDurable()) { - _virtualHost.getMessageStore().bindQueue(exchange, routingKey, this, arguments); + _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, arguments); } _bindings.addBinding(routingKey, arguments, exchange); @@ -329,7 +335,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener exchange.deregisterQueue(routingKey, this, arguments); if (isDurable() && exchange.isDurable()) { - _virtualHost.getMessageStore().unbindQueue(exchange, routingKey, this, arguments); + _virtualHost.getDurableConfigurationStore().unbindQueue(exchange, routingKey, this, arguments); } boolean removed = _bindings.remove(routingKey, arguments, exchange); @@ -446,14 +452,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener entry = _entries.add(message); deliverToSubscription(exclusiveSub, entry); - - // where there is more than one producer there's a reasonable chance that even though there is - // no "queueing" we do not deliver because we get an interleving of _entries.add and - // deliverToSubscription between threads. Therefore have one more try. - if (!(entry.isAcquired() || entry.isDeleted())) - { - deliverToSubscription(exclusiveSub, entry); - } } finally { @@ -514,13 +512,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } - if (entry.immediateAndNotDelivered()) - { - StoreContext storeContext = StoreContext.getCurrentContext(); - dequeue(storeContext, entry); - entry.dispose(storeContext); - } - else if (!(entry.isAcquired() || entry.isDeleted())) + if (!(entry.isAcquired() || entry.isDeleted())) { checkSubscriptionsNotAheadOfDelivery(entry); @@ -602,7 +594,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _lastSeenUpdater.set(subContext, entry); if(releasedEntry == entry) { - _releasedUpdater.compareAndSet(subContext, releasedEntry, null); + _releasedUpdater.compareAndSet(subContext, releasedEntry, null); } } @@ -624,7 +616,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } - public void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException + public void requeue(QueueEntry entry) { SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator(); @@ -662,7 +654,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener deliverAsync(); } - public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException + public void dequeue(QueueEntry entry) { decrementQueueCount(); decrementQueueSize(entry); @@ -671,29 +663,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _deliveredMessages.decrementAndGet(); } - try - { - ServerMessage msg = entry.getMessage(); - if (msg.isPersistent()) - { - _virtualHost.getMessageStore().dequeueMessage(storeContext, this, msg.getMessageNumber()); - } - //entry.dispose(storeContext); - - } - catch (MessageCleanupException e) - { - // Message was dequeued, but could not then be deleted - // though it is no longer referenced. This should be very - // rare and can be detected and cleaned up on recovery or - // done through some form of manual intervention. - _logger.error(e, e); - } - catch (AMQException e) - { - throw new FailedDequeueException(_name.toString(), e); - } - checkCapacity(); } @@ -930,7 +899,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() { private long position = 0; - + public boolean accept(QueueEntry entry) { position++; @@ -942,7 +911,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener return position >= toPosition; } }); - + return entries; } @@ -986,7 +955,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener store.enqueueMessage(storeContext, toQueue, message.getMessageNumber()); } // dequeue does not decrement the refence count - entry.dequeue(storeContext); + entry.dequeue(); } // Commit and flush the move transcations. @@ -1014,7 +983,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener try { - StoreContext.setCurrentContext(storeContext); for (QueueEntry entry : entries) { @@ -1030,11 +998,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { throw new RuntimeException(e); } - finally - { - StoreContext.clearCurrentContext(); - - } } @@ -1074,9 +1037,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener if (message.isPersistent() && toQueue.isDurable()) { - StoreContext sc = StoreContext.setCurrentContext(storeContext); store.enqueueMessage(storeContext, toQueue, message.getMessageNumber()); - StoreContext.setCurrentContext(sc); } } @@ -1127,39 +1088,35 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } - public void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext) + public void removeMessagesFromQueue(long fromMessageId, long toMessageId) { - try + QueueEntryIterator queueListIterator = _entries.iterator(); + + while (queueListIterator.advance()) { - QueueEntryIterator queueListIterator = _entries.iterator(); + QueueEntry node = queueListIterator.getNode(); - while (queueListIterator.advance()) + final ServerMessage message = node.getMessage(); + if(message != null) { - QueueEntry node = queueListIterator.getNode(); - - final long messageId = node.getMessage().getMessageNumber(); + final long messageId = message.getMessageNumber(); if ((messageId >= fromMessageId) && (messageId <= toMessageId) && !node.isDeleted() && node.acquire()) { - node.discard(storeContext); + dequeueEntry(node); } - } } - catch (AMQException e) - { - throw new RuntimeException(e); - } } // ------ Management functions - public void deleteMessageFromTop(StoreContext storeContext) throws AMQException + public void deleteMessageFromTop() { QueueEntryIterator queueListIterator = _entries.iterator(); boolean noDeletes = true; @@ -1169,33 +1126,62 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener QueueEntry node = queueListIterator.getNode(); if (!node.isDeleted() && node.acquire()) { - node.discard(storeContext); + dequeueEntry(node); noDeletes = false; } } } - public long clearQueue(StoreContext storeContext) throws AMQException + public long clearQueue() { QueueEntryIterator queueListIterator = _entries.iterator(); long count = 0; + Transaction txn = new LocalTransaction(getVirtualHost().getMessageStore()); + while (queueListIterator.advance()) { QueueEntry node = queueListIterator.getNode(); if (!node.isDeleted() && node.acquire()) { - node.discard(storeContext); + dequeueEntry(node, txn); count++; } } + + txn.commit(); + return count; } + private void dequeueEntry(final QueueEntry node) + { + Transaction txn = new AutoCommitTransaction(getVirtualHost().getMessageStore()); + dequeueEntry(node, txn); + } + + private void dequeueEntry(final QueueEntry node, Transaction txn) + { + txn.dequeue(this, node.getMessage(), + new Transaction.Action() + { + + public void postCommit() + { + node.discard(); + } + + public void onRollback() + { + + } + }); + } + public void addQueueDeleteTask(final Task task) { _deleteTaskList.add(task); @@ -1228,7 +1214,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _deleteTaskList.clear(); stop(); - + //Log Queue Deletion CurrentActor.get().message(_logSubject, QueueMessages.QUE_1002()); @@ -1496,7 +1482,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener //QPID-1187 - Treat the subscription as suspended for this message // and wait for the message to be removed to continue delivery. subActive = false; - node.addStateChangeListener(new QueueEntryListener(sub, node)); + node.addStateChangeListener(new QueueEntryListener(sub)); } } @@ -1536,15 +1522,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen); boolean expired = false; - while (node != null && (node.isAcquired() || node.isDeleted() || (expired = node.expired()))) + while (node != null && (node.isAcquired() || node.isDeleted() || (expired = node.expired()) || !sub.hasInterest(node))) { if (expired) { expired = false; if (node.acquire()) { - final StoreContext reapingStoreContext = new StoreContext(); - node.discard(reapingStoreContext); + dequeueEntry(node); } } @@ -1607,7 +1592,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { if (sub != null) { - done = attemptDelivery(sub); + done = attemptDelivery(sub); } if (done) { @@ -1656,8 +1641,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void checkMessageStatus() throws AMQException { - final StoreContext storeContext = new StoreContext(); - QueueEntryIterator queueListIterator = _entries.iterator(); while (queueListIterator.advance()) @@ -1665,7 +1648,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener QueueEntry node = queueListIterator.getNode(); if (!node.isDeleted() && node.expired() && node.acquire()) { - node.discard(storeContext); + dequeueEntry(node); } else { @@ -1793,23 +1776,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private final class QueueEntryListener implements QueueEntry.StateChangeListener { - private final QueueEntry _entry; + private final Subscription _sub; - public QueueEntryListener(final Subscription sub, final QueueEntry entry) + public QueueEntryListener(final Subscription sub) { - _entry = entry; _sub = sub; } public boolean equals(Object o) { - return _entry == ((QueueEntryListener) o)._entry && _sub == ((QueueEntryListener) o)._sub; + return _sub == ((QueueEntryListener) o)._sub; } public int hashCode() { - return System.identityHashCode(_entry) ^ System.identityHashCode(_sub); + return System.identityHashCode(_sub); } public void stateChanged(QueueEntry entry, QueueEntry.State oldSate, QueueEntry.State newState) @@ -1841,6 +1823,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener return ids; } + public Object getExclusiveOwner() + { + return _exclusiveOwner; + } + + public void setExclusiveOwner(Object exclusiveOwner) + { + _exclusiveOwner = exclusiveOwner; + } + + public void configure(QueueConfiguration config) { if (config != null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java index 3ed8b0e55c..99387b210a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java @@ -30,7 +30,6 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; /** * @author Robert Greig (robert.j.greig@jpmorgan.com) @@ -43,8 +42,6 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle private List<WeakReference<ContentChunk>> _contentBodies; - private boolean _redelivered; - private final MessageStore _messageStore; private final Long _messageId; @@ -56,12 +53,12 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle _messageStore = messageStore; } - public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException + public ContentHeaderBody getContentHeaderBody() throws AMQException { ContentHeaderBody chb = (_contentHeaderBody != null ? _contentHeaderBody.get() : null); if (chb == null) { - MessageMetaData mmd = loadMessageMetaData(context); + MessageMetaData mmd = loadMessageMetaData(); chb = mmd.getContentHeaderBody(); } return chb; @@ -72,10 +69,10 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle return _messageId; } - private MessageMetaData loadMessageMetaData(StoreContext context) + private MessageMetaData loadMessageMetaData() throws AMQException { - MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId); + MessageMetaData mmd = _messageStore.getMessageMetaData(_messageId); populateFromMessageMetaData(mmd); return mmd; } @@ -87,11 +84,11 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle _messagePublishInfo = new WeakReference<MessagePublishInfo>(mmd.getMessagePublishInfo()); } - public int getBodyCount(StoreContext context) throws AMQException + public int getBodyCount() throws AMQException { if (_contentBodies == null) { - MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId); + MessageMetaData mmd = _messageStore.getMessageMetaData(_messageId); int chunkCount = mmd.getContentChunkCount(); _contentBodies = new ArrayList<WeakReference<ContentChunk>>(chunkCount); for (int i = 0; i < chunkCount; i++) @@ -102,12 +99,12 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle return _contentBodies.size(); } - public long getBodySize(StoreContext context) throws AMQException + public long getBodySize() throws AMQException { - return getContentHeaderBody(context).bodySize; + return getContentHeaderBody().bodySize; } - public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException + public ContentChunk getContentChunk(int index) throws AMQException, IllegalArgumentException { if (index > _contentBodies.size() - 1) { @@ -118,7 +115,7 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle ContentChunk cb = wr.get(); if (cb == null) { - cb = _messageStore.getContentBodyChunk(context, _messageId, index); + cb = _messageStore.getContentBodyChunk(_messageId, index); _contentBodies.set(index, new WeakReference<ContentChunk>(cb)); } return cb; @@ -127,12 +124,11 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle /** * Content bodies are set <i>before</i> the publish and header frames * - * @param storeContext * @param contentChunk * @param isLastContentBody * @throws AMQException */ - public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentChunk, boolean isLastContentBody) throws AMQException + public void addContentBodyFrame(ContentChunk contentChunk, boolean isLastContentBody) throws AMQException { if (_contentBodies == null && isLastContentBody) { @@ -146,32 +142,21 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle } } _contentBodies.add(new WeakReference<ContentChunk>(contentChunk)); - _messageStore.storeContentBodyChunk(storeContext, _messageId, _contentBodies.size() - 1, - contentChunk, isLastContentBody); + } - public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException + public MessagePublishInfo getMessagePublishInfo() throws AMQException { MessagePublishInfo bpb = (_messagePublishInfo != null ? _messagePublishInfo.get() : null); if (bpb == null) { - MessageMetaData mmd = loadMessageMetaData(context); + MessageMetaData mmd = loadMessageMetaData(); bpb = mmd.getMessagePublishInfo(); } return bpb; } - public boolean isRedelivered() - { - return _redelivered; - } - - public void setRedelivered(boolean redelivered) - { - _redelivered = redelivered; - } - public boolean isPersistent() { return true; @@ -184,9 +169,8 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle * @param contentHeaderBody * @throws AMQException */ - public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo publishBody, - ContentHeaderBody contentHeaderBody) - throws AMQException + public MessageMetaData setPublishAndContentHeaderBody(MessagePublishInfo publishBody, + ContentHeaderBody contentHeaderBody) { // if there are no content bodies the list will be null so we must // create en empty list here @@ -198,17 +182,15 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle final long arrivalTime = System.currentTimeMillis(); - MessageMetaData mmd = new MessageMetaData(publishBody, contentHeaderBody, _contentBodies.size(), arrivalTime); - - _messageStore.storeMessageMetaData(storeContext, _messageId, mmd); - + MessageMetaData mmd = new MessageMetaData(publishBody, contentHeaderBody, _contentBodies == null ? 0 : _contentBodies.size(), arrivalTime); populateFromMessageMetaData(mmd); + return mmd; } - public void removeMessage(StoreContext storeContext) throws AMQException + public void removeMessage() throws AMQException { - _messageStore.removeMessage(storeContext, _messageId); + _messageStore.removeMessage(_messageId); } public long getArrivalTime() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java index 2b2c8fb804..6e86f4b70d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java @@ -30,20 +30,18 @@ import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.MessageStoreMessages; -import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.MessageHandleFactory; import org.apache.qpid.server.queue.MessageMetaData; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; + import org.apache.qpid.server.virtualhost.VirtualHost; + import java.io.ByteArrayInputStream; import java.io.File; import java.sql.Blob; @@ -379,9 +377,9 @@ public class DerbyMessageStore extends AbstractMessageStore null); _virtualHost.getQueueRegistry().registerQueue(q); } - + queueMap.put(queueNameShortString,q); - + CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1004(String.valueOf(q.getName()), true)); //Record that we have a queue for recovery @@ -504,12 +502,13 @@ public class DerbyMessageStore extends AbstractMessageStore public void close() throws Exception { _closed.getAndSet(true); - - super.close(); + + super.close(); } - public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException + public void removeMessage(Long messageId) throws AMQException { + StoreContext storeContext = new StoreContext(); boolean localTx = getOrCreateTransaction(storeContext); @@ -523,7 +522,7 @@ public class DerbyMessageStore extends AbstractMessageStore } // first we need to look up the header to get the chunk count - MessageMetaData mmd = getMessageMetaData(storeContext, messageId); + MessageMetaData mmd = getMessageMetaData(messageId); try { PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_MESSAGE_META_DATA); @@ -802,7 +801,7 @@ public class DerbyMessageStore extends AbstractMessageStore { stmt = conn.prepareStatement(INSERT_INTO_QUEUE); - String owner = queue.getPrincipalHolder() == null + String owner = queue.getPrincipalHolder() == null ? null : queue.getPrincipalHolder().getPrincipal() == null ? null @@ -995,6 +994,7 @@ public class DerbyMessageStore extends AbstractMessageStore public void beginTran(StoreContext context) throws AMQException { + if (context.getPayload() != null) { throw new AMQException("Fatal internal error: transactional context is not empty at beginTran: " @@ -1050,6 +1050,24 @@ public class DerbyMessageStore extends AbstractMessageStore } } + public StoreFuture commitTranAsync(StoreContext context) throws AMQException + { + commitTran(context); + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + + } + public void abortTran(StoreContext context) throws AMQException { ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); @@ -1094,12 +1112,13 @@ public class DerbyMessageStore extends AbstractMessageStore return _messageId.getAndIncrement(); } - public void storeContentBodyChunk(StoreContext context, - Long messageId, - int index, - ContentChunk contentBody, - boolean lastContentBody) throws AMQException + public void storeContentBodyChunk( + Long messageId, + int index, + ContentChunk contentBody, + boolean lastContentBody) throws AMQException { + StoreContext context = new StoreContext(); boolean localTx = getOrCreateTransaction(context); Connection conn = getConnection(context); ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); @@ -1138,10 +1157,10 @@ public class DerbyMessageStore extends AbstractMessageStore } - public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData mmd) + public void storeMessageMetaData(Long messageId, MessageMetaData mmd) throws AMQException { - + StoreContext context = new StoreContext(); boolean localTx = getOrCreateTransaction(context); Connection conn = getConnection(context); ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); @@ -1192,8 +1211,9 @@ public class DerbyMessageStore extends AbstractMessageStore } - public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException + public MessageMetaData getMessageMetaData(Long messageId) throws AMQException { + StoreContext context = new StoreContext(); boolean localTx = getOrCreateTransaction(context); Connection conn = getConnection(context); @@ -1277,8 +1297,9 @@ public class DerbyMessageStore extends AbstractMessageStore } - public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException + public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException { + StoreContext context = new StoreContext(); boolean localTx = getOrCreateTransaction(context); Connection conn = getConnection(context); @@ -1378,10 +1399,7 @@ public class DerbyMessageStore extends AbstractMessageStore public void process() throws AMQException { - StoreContext.setCurrentContext(_context); _queue.enqueue(_message); - StoreContext.clearCurrentContext(); - } } @@ -1410,8 +1428,6 @@ public class DerbyMessageStore extends AbstractMessageStore MessageHandleFactory messageHandleFactory = new MessageHandleFactory(); long maxId = 1; - TransactionalContext txnContext = new NonTransactionalContext(this, new StoreContext(), null, null); - Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY); @@ -1441,7 +1457,7 @@ public class DerbyMessageStore extends AbstractMessageStore } else { - message = new AMQMessage(messageId, this, messageHandleFactory, txnContext); + message = new AMQMessage(messageId, this, messageHandleFactory); msgMap.put(messageId,message); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java new file mode 100755 index 0000000000..d791905ad9 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -0,0 +1,99 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; + +public interface DurableConfigurationStore +{ + /** + * Makes the specified exchange persistent. + * + * @param exchange The exchange to persist. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void createExchange(Exchange exchange) throws AMQException; + + /** + * Removes the specified persistent exchange. + * + * @param exchange The exchange to remove. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void removeExchange(Exchange exchange) throws AMQException; + + /** + * Binds the specified queue to an exchange with a routing key. + * + * @param exchange The exchange to bind to. + * @param routingKey The routing key to bind by. + * @param queue The queue to bind. + * @param args Additional parameters. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; + + /** + * Unbinds the specified from an exchange under a particular routing key. + * + * @param exchange The exchange to unbind from. + * @param routingKey The routing key to unbind. + * @param queue The queue to unbind. + * @param args Additonal parameters. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; + + /** + * Makes the specified queue persistent. + * + * @param queue The queue to store. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void createQueue(AMQQueue queue) throws AMQException; + + /** + * Makes the specified queue persistent. + * + * @param queue The queue to store. + * + * @param arguments The additional arguments to the binding + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException; + + /** + * Removes the specified queue from the persistent store. + * + * @param queue The queue to remove. + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void removeQueue(AMQQueue queue) throws AMQException; +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java index 87ec66030d..8a9c1571ca 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.store; -import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; @@ -31,10 +30,7 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.messages.MessageStoreMessages; -import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import java.util.ArrayList; import java.util.Collections; @@ -88,7 +84,7 @@ public class MemoryMessageStore extends AbstractMessageStore super.close(); } - public void removeMessage(StoreContext context, Long messageId) throws AMQException + public void removeMessage(Long messageId) throws AMQException { checkNotClosed(); if (_log.isDebugEnabled()) @@ -155,6 +151,24 @@ public class MemoryMessageStore extends AbstractMessageStore // Not required to do anything } + public StoreFuture commitTranAsync(StoreContext context) throws AMQException + { + commitTran(context); + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + + } + public void abortTran(StoreContext context) throws AMQException { // Not required to do anything @@ -175,7 +189,11 @@ public class MemoryMessageStore extends AbstractMessageStore return _messageId.getAndIncrement(); } - public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) + public void storeContentBodyChunk( + Long messageId, + int index, + ContentChunk contentBody, + boolean lastContentBody) throws AMQException { checkNotClosed(); @@ -197,20 +215,20 @@ public class MemoryMessageStore extends AbstractMessageStore } } - public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) + public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException { checkNotClosed(); _metaDataMap.put(messageId, messageMetaData); } - public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException + public MessageMetaData getMessageMetaData(Long messageId) throws AMQException { checkNotClosed(); return _metaDataMap.get(messageId); } - public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException + public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException { checkNotClosed(); List<ContentChunk> bodyList = _contentBodyMap.get(messageId); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java index 5a1b54b298..802c0bc709 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -20,16 +20,10 @@ */ package org.apache.qpid.server.store; -import org.apache.commons.configuration.Configuration; - import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.MessageMetaData; -import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -53,7 +47,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; * <tr><td> Generate message identifiers. * </table> */ -public interface MessageStore +public interface MessageStore extends DurableConfigurationStore, TransactionLog { /** * Called after instantiation in order to configure the message store. A particular implementation can define @@ -78,137 +72,12 @@ public interface MessageStore /** * Removes the specified message from the store in the given transactional store context. * - * @param storeContext The transactional context to remove the message in. * @param messageId Identifies the message to remove. * * @throws AMQException If the operation fails for any reason. */ - void removeMessage(StoreContext storeContext, Long messageId) throws AMQException; - - /** - * Makes the specified exchange persistent. - * - * @param exchange The exchange to persist. - * - * @throws AMQException If the operation fails for any reason. - */ - void createExchange(Exchange exchange) throws AMQException; - - /** - * Removes the specified persistent exchange. - * - * @param exchange The exchange to remove. - * - * @throws AMQException If the operation fails for any reason. - */ - void removeExchange(Exchange exchange) throws AMQException; - - /** - * Binds the specified queue to an exchange with a routing key. - * - * @param exchange The exchange to bind to. - * @param routingKey The routing key to bind by. - * @param queue The queue to bind. - * @param args Additional parameters. - * - * @throws AMQException If the operation fails for any reason. - */ - void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; - - /** - * Unbinds the specified from an exchange under a particular routing key. - * - * @param exchange The exchange to unbind from. - * @param routingKey The routing key to unbind. - * @param queue The queue to unbind. - * @param args Additonal parameters. - * - * @throws AMQException If the operation fails for any reason. - */ - void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; - - /** - * Makes the specified queue persistent. - * - * @param queue The queue to store. - * - * @throws AMQException If the operation fails for any reason. - */ - void createQueue(AMQQueue queue) throws AMQException; - - /** - * Makes the specified queue persistent. - * - * @param queue The queue to store. - * - * @param arguments The additional arguments to the binding - * @throws AMQException If the operation fails for any reason. - */ - void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException; + void removeMessage(Long messageId) throws AMQException; - /** - * Removes the specified queue from the persistent store. - * - * @param queue The queue to remove. - * @throws AMQException If the operation fails for any reason. - */ - void removeQueue(final AMQQueue queue) throws AMQException; - - /** - * Places a message onto a specified queue, in a given transactional context. - * - * @param context The transactional context for the operation. - * @param queue The queue to place the message on. - * @param messageId The message to enqueue. - * @throws AMQException If the operation fails for any reason. - */ - void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException; - - /** - * Extracts a message from a specified queue, in a given transactional context. - * - * @param context The transactional context for the operation. - * @param queue The queue to place the message on. - * @param messageId The message to dequeue. - * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. - */ - void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException; - - /** - * Begins a transactional context. - * - * @param context The transactional context to begin. - * - * @throws AMQException If the operation fails for any reason. - */ - void beginTran(StoreContext context) throws AMQException; - - /** - * Commits all operations performed within a given transactional context. - * - * @param context The transactional context to commit all operations for. - * - * @throws AMQException If the operation fails for any reason. - */ - void commitTran(StoreContext context) throws AMQException; - - /** - * Abandons all operations performed within a given transactional context. - * - * @param context The transactional context to abandon. - * - * @throws AMQException If the operation fails for any reason. - */ - void abortTran(StoreContext context) throws AMQException; - - /** - * Tests a transactional context to see if it has been begun but not yet committed or aborted. - * - * @param context The transactional context to test. - * - * @return <tt>true</tt> if the transactional context is live, <tt>false</tt> otherwise. - */ - boolean inTran(StoreContext context); /** * Return a valid, currently unused message id. @@ -220,7 +89,6 @@ public interface MessageStore /** * Stores a chunk of message data. * - * @param context The transactional context for the operation. * @param messageId The message to store the data for. * @param index The index of the data chunk. * @param contentBody The content of the data chunk. @@ -228,36 +96,33 @@ public interface MessageStore * * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. */ - void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, - boolean lastContentBody) throws AMQException; + void storeContentBodyChunk(Long messageId, int index, ContentChunk contentBody, + boolean lastContentBody) throws AMQException; /** * Stores message meta-data. * - * @param context The transactional context for the operation. * @param messageId The message to store the data for. * @param messageMetaData The message meta data to store. * * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. */ - void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException; + void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException; /** * Retrieves message meta-data. * - * @param context The transactional context for the operation. * @param messageId The message to get the meta-data for. * * @return The message meta data. * * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. */ - MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException; + MessageMetaData getMessageMetaData(Long messageId) throws AMQException; /** * Retrieves a chunk of message data. * - * @param context The transactional context for the operation. * @param messageId The message to get the data chunk for. * @param index The offset index of the data chunk within the message. * @@ -265,7 +130,7 @@ public interface MessageStore * * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. */ - ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException; + ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException; /** * Is this store capable of persisting the data diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java index 1e75ca04f9..88cc68bc71 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java @@ -32,8 +32,6 @@ public class StoreContext { private static final Logger _logger = Logger.getLogger(StoreContext.class); - private static final ThreadLocal<StoreContext> _threadLocalContext = new ThreadLocal<StoreContext>(); - private String _name; private Object _payload; @@ -72,23 +70,4 @@ public class StoreContext return "<_name = " + _name + ", _payload = " + _payload + ">"; } - - public static StoreContext setCurrentContext(StoreContext context) - { - StoreContext sc = getCurrentContext(); - _threadLocalContext.set(context); - return sc; - } - - public static StoreContext getCurrentContext() - { - return _threadLocalContext.get(); - } - - public static void clearCurrentContext() - { - _threadLocalContext.set(null); - } - - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java new file mode 100755 index 0000000000..acbf95a9d6 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java @@ -0,0 +1,99 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.AMQException; + +public interface TransactionLog +{ + /** + * Places a message onto a specified queue, in a given transactional context. + * + * @param context The transactional context for the operation. + * @param queue The queue to place the message on. + * @param messageId The message to enqueue. + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void enqueueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException; + + /** + * Extracts a message from a specified queue, in a given transactional context. + * + * @param context The transactional context for the operation. + * @param queue The queue to place the message on. + * @param messageId The message to dequeue. + * @throws org.apache.qpid.AMQException If the operation fails for any reason, or if the specified message does not exist. + */ + void dequeueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException; + + /** + * Begins a transactional context. + * + * @param context The transactional context to begin. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void beginTran(StoreContext context) throws AMQException; + + /** + * Commits all operations performed within a given transactional context. + * + * @param context The transactional context to commit all operations for. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void commitTran(StoreContext context) throws AMQException; + + /** + * Commits all operations performed within a given transactional context. + * + * @param context The transactional context to commit all operations for. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + StoreFuture commitTranAsync(StoreContext context) throws AMQException; + + /** + * Abandons all operations performed within a given transactional context. + * + * @param context The transactional context to abandon. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void abortTran(StoreContext context) throws AMQException; + + /** + * Tests a transactional context to see if it has been begun but not yet committed or aborted. + * + * @param context The transactional context to test. + * + * @return <tt>true</tt> if the transactional context is live, <tt>false</tt> otherwise. + */ + boolean inTran(StoreContext context); + + public static interface StoreFuture + { + boolean isComplete(); + + void waitForCompletion(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java index f0d33d1a69..0d317c449d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java @@ -46,6 +46,8 @@ public interface Subscription AMQQueue getQueue(); QueueEntry.SubscriptionAcquiredState getOwningState(); + QueueEntry.SubscriptionAssignedState getAssignedState(); + void setQueue(AMQQueue queue, boolean exclusive); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index 64f5d0dfaa..e7ace4eb55 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -43,12 +43,10 @@ import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.store.StoreContext; /** * Encapsulation of a supscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag @@ -73,7 +71,9 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final ClientDeliveryMethod _deliveryMethod; private final RecordDeliveryMethod _recordMethod; - private QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this); + private final Lock _stateChangeLock; private static final AtomicLong idGenerator = new AtomicLong(0); @@ -82,6 +82,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private LogSubject _logSubject; private LogActor _logActor; + static final class BrowserSubscription extends SubscriptionImpl { public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession, @@ -157,38 +158,28 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage @Override public void send(QueueEntry entry) throws AMQException { + // if we do not need to wait for client acknowledgements + // we can decrement the reference count immediately. - StoreContext storeContext = getChannel().getStoreContext(); - try - { // if we do not need to wait for client acknowledgements - // we can decrement the reference count immediately. - - // By doing this _before_ the send we ensure that it - // doesn't get sent if it can't be dequeued, preventing - // duplicate delivery on recovery. + // By doing this _before_ the send we ensure that it + // doesn't get sent if it can't be dequeued, preventing + // duplicate delivery on recovery. - // The send may of course still fail, in which case, as - // the message is unacked, it will be lost. - entry.dequeue(storeContext); + // The send may of course still fail, in which case, as + // the message is unacked, it will be lost. + entry.dequeue(); - synchronized (getChannel()) - { - long deliveryTag = getChannel().getNextDeliveryTag(); + synchronized (getChannel()) + { + long deliveryTag = getChannel().getNextDeliveryTag(); - sendToClient(entry, deliveryTag); + sendToClient(entry, deliveryTag); - } - entry.dispose(storeContext); } - finally - { - //Only set delivered if it actually was writen successfully.. - // using a try->finally would set it even if an error occured. - // Is this what we want? + entry.dispose(); + - entry.setDeliveredToSubscription(); - } } @Override @@ -229,39 +220,30 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public void send(QueueEntry entry) throws AMQException { - try - { // if we do not need to wait for client acknowledgements - // we can decrement the reference count immediately. + // if we do not need to wait for client acknowledgements + // we can decrement the reference count immediately. - // By doing this _before_ the send we ensure that it - // doesn't get sent if it can't be dequeued, preventing - // duplicate delivery on recovery. + // By doing this _before_ the send we ensure that it + // doesn't get sent if it can't be dequeued, preventing + // duplicate delivery on recovery. - // The send may of course still fail, in which case, as - // the message is unacked, it will be lost. + // The send may of course still fail, in which case, as + // the message is unacked, it will be lost. - synchronized (getChannel()) - { - long deliveryTag = getChannel().getNextDeliveryTag(); + synchronized (getChannel()) + { + long deliveryTag = getChannel().getNextDeliveryTag(); - recordMessageDelivery(entry, deliveryTag); - sendToClient(entry, deliveryTag); + recordMessageDelivery(entry, deliveryTag); + sendToClient(entry, deliveryTag); - } - } - finally - { - //Only set delivered if it actually was writen successfully.. - // using a try->finally would set it even if an error occured. - // Is this what we want? - - entry.setDeliveredToSubscription(); } } + } @@ -452,29 +434,14 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage //todo - client id should be recorded so we don't have to handle // the case where this is null. - final Object publisherId = message.getPublisherClientInstance(); + final Object publisher = message.getPublisherIdentifier(); // We don't want local messages so check to see if message is one we sent - Object localInstance; + Object localInstance = getProtocolSession(); - if (publisherId != null && (getProtocolSession().getClientProperties() != null) && - (localInstance = getProtocolSession().getClientProperties().getObject(CLIENT_PROPERTIES_INSTANCE)) != null) - { - if(publisherId.equals(localInstance)) - { - return false; - } - } - else + if(publisher.equals(localInstance)) { - - localInstance = getProtocolSession().getClientIdentifier(); - - //todo - client id should be recorded so we don't have to do the null check - if (localInstance != null && localInstance.equals(message.getPublisherIdentifier())) - { - return false; - } + return false; } @@ -498,7 +465,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private boolean checkFilters(QueueEntry msg) { - return (_filters == null) || _filters.allAllow(msg.getMessage()); + return (_filters == null) || _filters.allAllow(msg); } public boolean isAutoClose() @@ -678,6 +645,12 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return _owningState; } + public QueueEntry.SubscriptionAssignedState getAssignedState() + { + return _assignedState; + } + + public void confirmAutoClose() { ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index 88617d53b8..1b80ede81f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -22,8 +22,6 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.FailedDequeueException; -import org.apache.qpid.server.queue.MessageCleanupException; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.CreditCreditManager; import org.apache.qpid.server.flow.WindowCreditManager; @@ -38,7 +36,6 @@ import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.AMQException; import org.apache.qpid.transport.*; @@ -59,6 +56,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private final long _subscriptionID = idGenerator.getAndIncrement(); private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this); + private final Lock _stateChangeLock = new ReentrantLock(); private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE); @@ -124,6 +123,11 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _owningState; } + public QueueEntry.SubscriptionAssignedState getAssignedState() + { + return _assignedState; + } + public void setQueue(AMQQueue queue, boolean exclusive) { if(getQueue() != null) @@ -176,7 +180,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private boolean checkFilters(QueueEntry entry) { - return (_filters == null) || _filters.allAllow(entry.getMessage()); + return (_filters == null) || _filters.allAllow(entry); } public boolean isAutoClose() @@ -390,6 +394,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr public boolean acquire() { boolean acquired = entry.acquire(Subscription_0_10.this); + //TODO - why acknowledge here??? seems bizarre... _session.acknowledge(Subscription_0_10.this,entry); return acquired; @@ -412,14 +417,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { entry.setRedelivered(true); entry.release(); - try - { - entry.requeue(new StoreContext()); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } } public void queueDeleted(AMQQueue queue) @@ -568,18 +565,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { // TODO Fix Store Context / cleanup - try - { - entry.discard(new StoreContext()); - } - catch (FailedDequeueException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - catch (MessageCleanupException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } + entry.discard(); } public void flush() throws AMQException diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index 5eab6c14c1..c0db61cf3a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -29,8 +29,7 @@ import org.apache.qpid.server.txn.Transaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.PrincipalHolder; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.AMQException; import java.util.*; @@ -47,6 +46,7 @@ public class ServerSession extends Session implements PrincipalHolder { private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); + public static interface MessageDispositionChangeListener { public void onAccept(); @@ -83,7 +83,8 @@ public class ServerSession extends Session implements PrincipalHolder ServerSession(Connection connection, Binary name, long expiry) { super(connection, name, expiry); - _transaction = new AutoCommitTransaction(); + + _transaction = new AutoCommitTransaction(this.getMessageStore()); _principal = new UserPrincipal(connection.getAuthorizationID()); _reference = new WeakReference(this); } @@ -91,29 +92,32 @@ public class ServerSession extends Session implements PrincipalHolder ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) { super(connection, delegate, name, expiry); - _transaction = new AutoCommitTransaction(); + _transaction = new AutoCommitTransaction(this.getMessageStore()); _principal = new UserPrincipal(connection.getAuthorizationID()); _reference = new WeakReference(this); } - public void enqueue(final ServerMessage message, ArrayList<AMQQueue> queues) + public void enqueue(final ServerMessage message, final ArrayList<AMQQueue> queues) { - for(final AMQQueue q : queues) - { - _transaction.enqueue(q,message, new Transaction.Action() + _transaction.enqueue(queues,message, new Transaction.Action() { + AMQQueue[] _queues = queues.toArray(new AMQQueue[queues.size()]); + public void postCommit() { - try + for(int i = 0; i < _queues.length; i++) { - q.enqueue(message); - } - catch (AMQException e) - { - // TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + try + { + _queues[i].enqueue(message); + } + catch (AMQException e) + { + // TODO + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } } } @@ -122,7 +126,7 @@ public class ServerSession extends Session implements PrincipalHolder // NO-OP } }); - } + } @@ -301,18 +305,6 @@ public class ServerSession extends Session implements PrincipalHolder public void onRollback() { entry.release(); - - try - { - entry.requeue(new StoreContext()); - } - catch (AMQException e) - { - //TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - throw new RuntimeException(e); - } - } }); @@ -359,7 +351,7 @@ public class ServerSession extends Session implements PrincipalHolder public void selectTx() { - _transaction = new LocalTransaction(); + _transaction = new LocalTransaction(this.getMessageStore()); } public void commit() @@ -392,5 +384,10 @@ public class ServerSession extends Session implements PrincipalHolder return _reference; } + public MessageStore getMessageStore() + { + return ((ServerConnection)getConnection()).getVirtualHost().getMessageStore(); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index c4a40c4676..7891c5214c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -31,17 +31,11 @@ import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.flow.*; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUnknownExchangeType; -import org.apache.qpid.AMQInvalidRoutingKeyException; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.framing.*; import java.util.ArrayList; -import java.util.Map; import java.util.Collection; public class ServerSessionDelegate extends SessionDelegate @@ -218,26 +212,17 @@ public class ServerSessionDelegate extends SessionDelegate delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); } - try - { - ArrayList<AMQQueue> queues = exchange.route(message); - + ArrayList<AMQQueue> queues = exchange.route(message); - if(queues != null) - { - ((ServerSession) ssn).enqueue(message, queues); - } - ssn.processed(xfr); - } - catch (AMQException e) + if(queues != null) { - // TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - throw new RuntimeException(e); + ((ServerSession) ssn).enqueue(message, queues); } + ssn.processed(xfr); + super.messageTransfer(ssn, xfr); //To change body of overridden methods use File | Settings | File Templates. } @@ -1007,15 +992,7 @@ public class ServerSessionDelegate extends SessionDelegate else { //TODO - try - { - queue.clearQueue(new StoreContext()); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - throw new RuntimeException(e); - } + queue.clearQueue(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java index 78fad3f629..4afaa39a0d 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java @@ -21,26 +21,151 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.StoreContext; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.AMQException; + +import java.util.List; +import java.util.Collection; public class AutoCommitTransaction implements Transaction { + private final TransactionLog _transactionLog; - public void dequeue(AMQQueue queue, ServerMessage message, Action postCommitAction) + public AutoCommitTransaction(TransactionLog transactionLog) { - // store.remove enqueue - // store.commit - postCommitAction.postCommit(); + _transactionLog = transactionLog; } - public void enqueue(AMQQueue queue, ServerMessage message, Action postCommitAction) + + public void addPostCommitAction(Action postCommitAction) { - // store.add enqueue - // store.commit postCommitAction.postCommit(); } + public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + { + + try + { + if(message.isPersistent() && queue.isDurable()) + { + + StoreContext context = new StoreContext(); + + _transactionLog.beginTran(context); + _transactionLog.dequeueMessage(context, queue, message.getMessageNumber()); + // store.remove enqueue + // store.commit + _transactionLog.commitTran(context); + } + postCommitAction.postCommit(); + } + catch (AMQException e) + { + //TODO + postCommitAction.onRollback(); + throw new RuntimeException(e); + } + } + + public void dequeue(Collection<QueueEntry> ackedMessages, Action postCommitAction) + { + try + { + StoreContext context = null; + for(QueueEntry entry : ackedMessages) + { + ServerMessage message = entry.getMessage(); + AMQQueue queue = entry.getQueue(); + + if(message.isPersistent() && queue.isDurable()) + { + if(context == null) + { + context = new StoreContext(); + _transactionLog.beginTran(context); + } + _transactionLog.dequeueMessage(context, queue, message.getMessageNumber()); + } + + } + if(context != null) + { + _transactionLog.commitTran(context); + } + postCommitAction.postCommit(); + } + catch (AMQException e) + { + //TODO + postCommitAction.onRollback(); + throw new RuntimeException(e); + } + } + + + public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + { + try + { + if(message.isPersistent() && queue.isDurable()) + { + StoreContext context = new StoreContext(); + + _transactionLog.beginTran(context); + _transactionLog.enqueueMessage(context, queue, message.getMessageNumber()); + _transactionLog.commitTran(context); + } + postCommitAction.postCommit(); + } + catch (AMQException e) + { + //TODO + e.printStackTrace(); + postCommitAction.onRollback(); + throw new RuntimeException(e); + } + + } + + public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction) + { + try + { + + if(message.isPersistent()) + { + StoreContext context = new StoreContext(); + + _transactionLog.beginTran(context); + + Long id = message.getMessageNumber(); + for(AMQQueue q : queues) + { + if(q.isDurable()) + { + _transactionLog.enqueueMessage(context, q, id); + } + } + _transactionLog.commitTran(context); + + } + postCommitAction.postCommit(); + } + catch (AMQException e) + { + //TODO + postCommitAction.onRollback(); + throw new RuntimeException(e); + } + + } + public void commit() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index 6db98ef101..380486dde7 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -1,53 +1,245 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.StoreContext; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.AMQException; import java.util.List; import java.util.ArrayList; +import java.util.Collection; public class LocalTransaction implements Transaction { private final List<Action> _postCommitActions = new ArrayList<Action>(); - public void dequeue(AMQQueue queue, ServerMessage message, Action postCommitAction) + private volatile StoreContext _storeContext; + private TransactionLog _transactionLog; + + public LocalTransaction(TransactionLog transactionLog) + { + _transactionLog = transactionLog; + } + + public void addPostCommitAction(Action postCommitAction) { _postCommitActions.add(postCommitAction); } - public void enqueue(AMQQueue queue, ServerMessage message, Action postCommitAction) + public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) { + if(message.isPersistent() && queue.isDurable()) + { + try + { + + beginTranIfNecessary(); + _transactionLog.dequeueMessage(_storeContext, queue, message.getMessageNumber()); + + } + catch(AMQException e) + { + tidyUpOnError(e); + } + } _postCommitActions.add(postCommitAction); } - public void commit() + public void dequeue(Collection<QueueEntry> queueEntries, Action postCommitAction) + { + try + { + + for(QueueEntry entry : queueEntries) + { + ServerMessage message = entry.getMessage(); + AMQQueue queue = entry.getQueue(); + if(message.isPersistent() && queue.isDurable()) + { + beginTranIfNecessary(); + _transactionLog.dequeueMessage(_storeContext, queue, message.getMessageNumber()); + } + + } + } + catch(AMQException e) + { + tidyUpOnError(e); + } + _postCommitActions.add(postCommitAction); + + } + + private void tidyUpOnError(AMQException e) { try { for(Action action : _postCommitActions) { - action.postCommit(); + action.onRollback(); } } finally { + try + { + _transactionLog.abortTran(_storeContext); + } + catch (AMQException e1) + { + // TODO could try to chain the information to the original error + } + _storeContext = null; _postCommitActions.clear(); } + + throw new RuntimeException(e); } - public void rollback() + private void beginTranIfNecessary() { + if(_storeContext == null) + { + _storeContext = new StoreContext(); + try + { + _transactionLog.beginTran(_storeContext); + } + catch (AMQException e) + { + tidyUpOnError(e); + } + } + } + public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + { + if(message.isPersistent() && queue.isDurable()) + { + beginTranIfNecessary(); + try + { + _transactionLog.enqueueMessage(_storeContext, queue, message.getMessageNumber()); + } + catch (AMQException e) + { + tidyUpOnError(e); + } + } + _postCommitActions.add(postCommitAction); + + + } + + public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction) + { + + + if(message.isPersistent()) + { + if(_storeContext == null) + { + for(AMQQueue queue : queues) + { + if(queue.isDurable()) + { + beginTranIfNecessary(); + break; + } + } + + + } + + + try + { + for(AMQQueue queue : queues) + { + if(queue.isDurable()) + { + _transactionLog.enqueueMessage(_storeContext, queue, message.getMessageNumber()); + } + } + + } + catch (AMQException e) + { + tidyUpOnError(e); + } + } + _postCommitActions.add(postCommitAction); + + + } + + public void commit() + { try { + if(_storeContext != null) + { + + _transactionLog.commitTran(_storeContext); + } + + for(Action action : _postCommitActions) + { + action.postCommit(); + } + } + catch (AMQException e) + { for(Action action : _postCommitActions) { action.onRollback(); } + //TODO + throw new RuntimeException(e); } finally { + _storeContext = null; _postCommitActions.clear(); } + + } + + public void rollback() + { + + try + { + + if(_storeContext != null) + { + + _transactionLog.abortTran(_storeContext); + } + } + catch (AMQException e) + { + //TODO + e.printStackTrace(); + throw new RuntimeException(e); + } + finally + { + try + { + for(Action action : _postCommitActions) + { + action.onRollback(); + } + } + finally + { + _storeContext = null; + _postCommitActions.clear(); + } + } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java deleted file mode 100644 index 27a6f14b03..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.ack.TxAck; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.*; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; - -import java.util.List; -import java.util.ArrayList; - -/** A transactional context that only supports local transactions. */ -public class LocalTransactionalContext implements TransactionalContext -{ - private static final Logger _log = Logger.getLogger(LocalTransactionalContext.class); - - private final TxnBuffer _txnBuffer = new TxnBuffer(); - - private final List<DeliveryAction> _postCommitDeliveryList = new ArrayList<DeliveryAction>(); - - /** - * We keep hold of the ack operation so that we can consolidate acks, i.e. multiple acks within a txn are - * consolidated into a single operation - */ - private TxAck _ackOp; - - private boolean _inTran = false; - - /** Are there messages to deliver. NOT Has the message been delivered */ - private boolean _messageDelivered = false; - private final AMQChannel _channel; - - - private abstract class DeliveryAction - { - - abstract public void process() throws AMQException; - - } - - private class RequeueAction extends DeliveryAction - { - public QueueEntry entry; - - public RequeueAction(QueueEntry entry) - { - this.entry = entry; - } - - public void process() throws AMQException - { - entry.requeue(getStoreContext()); - } - } - - private class PublishAction extends DeliveryAction - { - private final AMQQueue _queue; - private final AMQMessage _message; - - public PublishAction(final AMQQueue queue, final AMQMessage message) - { - _queue = queue; - _message = message; - } - - public void process() throws AMQException - { - - MessageReference ref = _message.newReference(); - try - { - StoreContext.setCurrentContext(getStoreContext()); - QueueEntry entry = _queue.enqueue(_message); - _queue.checkCapacity(_channel); - - if(entry.immediateAndNotDelivered()) - { - getReturnMessages().add(new NoConsumersException(_message)); - } - } - finally - { - ref.release(); - StoreContext.clearCurrentContext(); - } - } - } - - public LocalTransactionalContext(final AMQChannel channel) - { - _channel = channel; - } - - public StoreContext getStoreContext() - { - return _channel.getStoreContext(); - } - - public List<RequiredDeliveryException> getReturnMessages() - { - return _channel.getReturnMessages(); - } - - public MessageStore getMessageStore() - { - return _channel.getMessageStore(); - } - - - public void rollback() throws AMQException - { - _txnBuffer.rollback(getStoreContext()); - // Hack to deal with uncommitted non-transactional writes - if (getMessageStore().inTran(getStoreContext())) - { - getMessageStore().abortTran(getStoreContext()); - _inTran = false; - } - - _postCommitDeliveryList.clear(); - } - - public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException - { - // A publication will result in the enlisting of several - // TxnOps. The first is an op that will store the message. - // Following that (and ordering is important), an op will - // be added for every queue onto which the message is - // enqueued. - _postCommitDeliveryList.add(new PublishAction(queue, message)); - _messageDelivered = true; - - } - - public void requeue(QueueEntry entry) throws AMQException - { - _postCommitDeliveryList.add(new RequeueAction(entry)); - _messageDelivered = true; - - } - - - private void checkAck(long deliveryTag, UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException - { - if (!unacknowledgedMessageMap.contains(deliveryTag)) - { - throw new AMQException("Ack with delivery tag " + deliveryTag + " not known for channel"); - } - } - - public void acknowledgeMessage(long deliveryTag, long lastDeliveryTag, boolean multiple, - UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException - { - // check that the tag exists to give early failure - if (!multiple || (deliveryTag > 0)) - { - checkAck(deliveryTag, unacknowledgedMessageMap); - } - // we use a single txn op for all acks and update this op - // as new acks come in. If this is the first ack in the txn - // we will need to create and enlist the op. - if (_ackOp == null) - { - _ackOp = new TxAck(unacknowledgedMessageMap); - _txnBuffer.enlist(_ackOp); - } - // update the op to include this ack request - if (multiple && (deliveryTag == 0)) - { - // if have signalled to ack all, that refers only - // to all at this time - _ackOp.update(lastDeliveryTag, multiple); - } - else - { - _ackOp.update(deliveryTag, multiple); - } - if(!_inTran && _ackOp.checkPersistent()) - { - beginTranIfNecessary(); - } - } - - public void messageFullyReceived(boolean persistent) throws AMQException - { - // Not required in this transactional context - } - - public void messageProcessed(AMQProtocolSession protocolSession) throws AMQException - { - // Not required in this transactional context - } - - public void beginTranIfNecessary() throws AMQException - { - if (!_inTran) - { - if (_log.isDebugEnabled()) - { - _log.debug("Starting transaction on message store: " + this); - } - - getMessageStore().beginTran(getStoreContext()); - _inTran = true; - } - } - - public void commit() throws AMQException - { - if (_log.isDebugEnabled()) - { - _log.debug("Committing transactional context: " + this); - } - - if (_ackOp != null) - { - - _messageDelivered = true; - _ackOp.consolidate(); - // already enlisted, after commit will reset regardless of outcome - _ackOp = null; - } - - if (_messageDelivered && _inTran) - { - _txnBuffer.enlist(new StoreMessageOperation(getMessageStore())); - } - // fixme fail commit here ... QPID-440 - try - { - _txnBuffer.commit(getStoreContext()); - } - finally - { - _messageDelivered = false; - _inTran = getMessageStore().inTran(getStoreContext()); - } - - try - { - postCommitDelivery(); - } - catch (AMQException e) - { - // OK so what do we do now...? - _log.error("Failed to deliver messages following txn commit: " + e, e); - } - } - - private void postCommitDelivery() throws AMQException - { - if (_log.isDebugEnabled()) - { - _log.debug("Performing post commit delivery"); - } - - try - { - for (DeliveryAction dd : _postCommitDeliveryList) - { - dd.process(); - } - } - finally - { - _postCommitDeliveryList.clear(); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java deleted file mode 100644 index dd461bad47..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import java.util.LinkedList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.*; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; - -/** @author Apache Software Foundation */ -public class NonTransactionalContext implements TransactionalContext -{ - private static final Logger _log = Logger.getLogger(NonTransactionalContext.class); - - /** Channel is useful for logging */ - private final AMQChannel _channel; - - /** Where to put undeliverable messages */ - private final List<RequiredDeliveryException> _returnMessages; - - - - private final MessageStore _messageStore; - - private final StoreContext _storeContext; - - /** Whether we are in a transaction */ - private boolean _inTran; - - public NonTransactionalContext(MessageStore messageStore, StoreContext storeContext, AMQChannel channel, - List<RequiredDeliveryException> returnMessages) - { - _channel = channel; - _storeContext = storeContext; - _returnMessages = returnMessages; - _messageStore = messageStore; - - } - - - public StoreContext getStoreContext() - { - return _storeContext; - } - - public void beginTranIfNecessary() throws AMQException - { - if (!_inTran) - { - _messageStore.beginTran(_storeContext); - _inTran = true; - } - } - - public void commit() throws AMQException - { - // Does not apply to this context - } - - public void rollback() throws AMQException - { - // Does not apply to this context - } - - public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException - { - StoreContext.setCurrentContext(getStoreContext()); - - QueueEntry entry = queue.enqueue(message); - - StoreContext.clearCurrentContext(); - - queue.checkCapacity(_channel); - - //following check implements the functionality - //required by the 'immediate' flag: - if(entry.immediateAndNotDelivered()) - { - _returnMessages.add(new NoConsumersException(entry.getMessage())); - } - - } - - public void requeue(QueueEntry entry) throws AMQException - { - entry.requeue(_storeContext); - } - - public void acknowledgeMessage(final long deliveryTag, long lastDeliveryTag, - boolean multiple, final UnacknowledgedMessageMap unacknowledgedMessageMap) - throws AMQException - { - - final boolean debug = _log.isDebugEnabled(); - ; - if (multiple) - { - if (deliveryTag == 0) - { - - //Spec 2.1.6.11 ... If the multiple field is 1, and the delivery tag is zero, - // tells the server to acknowledge all outstanding mesages. - _log.info("Multiple ack on delivery tag 0. ACKing all messages. Current count:" + - unacknowledgedMessageMap.size()); - unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor() - { - public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException - { - if (debug) - { - _log.debug("Discarding message: " + message.getMessage().getMessageNumber()); - } - if(message.getMessage().isPersistent()) - { - beginTranIfNecessary(); - } - //Message has been ack so discard it. This will dequeue and decrement the reference. - message.discard(_storeContext); - - return false; - } - - public void visitComplete() - { - unacknowledgedMessageMap.clear(); - } - }); - } - else - { - if (!unacknowledgedMessageMap.contains(deliveryTag)) - { - throw new AMQException("Multiple ack on delivery tag " + deliveryTag + " not known for channel"); - } - - unacknowledgedMessageMap.drainTo(deliveryTag, _storeContext); - } - } - else - { - QueueEntry msg; - msg = unacknowledgedMessageMap.get(deliveryTag); - - if (msg == null) - { - _log.info("Single ack on delivery tag " + deliveryTag + " not known for channel:" + - _channel.getChannelId()); - throw new AMQException("Single ack on delivery tag " + deliveryTag + " not known for channel:" + - _channel.getChannelId()); - } - - if (debug) - { - _log.debug("Discarding message: " + msg.getMessage().getMessageNumber()); - } - if(msg.getMessage().isPersistent()) - { - beginTranIfNecessary(); - } - - //Message has been ack so discard it. This will dequeue and decrement the reference. - msg.discard(_storeContext); - - unacknowledgedMessageMap.remove(deliveryTag); - - - if (debug) - { - _log.debug("Received non-multiple ack for messaging with delivery tag " + deliveryTag + " msg id " + - msg.getMessage().getMessageNumber()); - } - } - if(_inTran) - { - _messageStore.commitTran(_storeContext); - _inTran = false; - } - } - - public void messageFullyReceived(boolean persistent) throws AMQException - { - if (persistent) - { - _messageStore.commitTran(_storeContext); - _inTran = false; - } - } - - public void messageProcessed(AMQProtocolSession protocolSession) throws AMQException - { - _channel.processReturns(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java deleted file mode 100644 index 0e4d6c2030..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; - -/** - * A transactional operation to store messages in an underlying persistent store. When this operation - * commits it will do everything to ensure that all messages are safely committed to persistent - * storage. - */ -public class StoreMessageOperation implements TxnOp -{ - private final MessageStore _messsageStore; - - public StoreMessageOperation(MessageStore messageStore) - { - _messsageStore = messageStore; - } - - public void prepare(StoreContext context) throws AMQException - { - } - - public void undoPrepare() - { - } - - public void commit(StoreContext context) throws AMQException - { - _messsageStore.commitTran(context); - } - - public void rollback(StoreContext context) throws AMQException - { - _messsageStore.abortTran(context); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/Transaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/Transaction.java index 85719737f1..dc91f31130 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/Transaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/Transaction.java @@ -21,11 +21,22 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.AMQChannel; + +import java.util.List; +import java.util.SortedSet; +import java.util.Collection; public interface Transaction { + void addPostCommitAction(Action postCommitAction); + + + public static interface Action { @@ -34,9 +45,14 @@ public interface Transaction public void onRollback(); } - void dequeue(AMQQueue queue, ServerMessage message, Action postCommitAction); + void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction); + + void dequeue(Collection<QueueEntry> ackedMessages, Action postCommitAction); + + void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction); + + void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction); - void enqueue(AMQQueue queue, ServerMessage message, Action postCommitAction); void commit(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java deleted file mode 100644 index 647ba66fb4..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.StoreContext; - -/** - * TransactionalContext provides a context in which transactional operations on {@link AMQMessage}s are performed. - * Different levels of transactional support for the delivery of messages may be provided by different implementations - * of this interface. - * - * <p/>The fundamental transactional operations that can be performed on a message queue are 'enqueue' and 'dequeue'. - * In this interface, these have been recast as the {@link #messageFullyReceived} and {@link #acknowledgeMessage} - * operations. This interface essentially provides a way to make enqueueing and dequeuing transactional. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities - * <tr><td> Explicitly accept a transaction start notification. - * <tr><td> Commit all pending operations in a transaction. - * <tr><td> Rollback all pending operations in a transaction. - * <tr><td> Deliver a message to a queue as part of a transaction. - * <tr><td> Redeliver a message to a queue as part of a transaction. - * <tr><td> Mark a message as acknowledged as part of a transaction. - * <tr><td> Accept notification that a message has been completely received as part of a transaction. - * <tr><td> Accept notification that a message has been fully processed as part of a transaction. - * <tr><td> Associate a message store context with this transaction context. - * </table> - * - * @todo The 'fullyReceived' and 'messageProcessed' events sit uncomfortably in the responsibilities of a transactional - * context. They are non-transactional operations, used to trigger other side-effects. Consider moving them - * somewhere else, a seperate interface for example. - * - * @todo This transactional context could be written as a wrapper extension to a Queue implementation, that provides - * transactional management of the enqueue and dequeue operations, with added commit/rollback methods. Any - * queue implementation could be made transactional by wrapping it as a transactional queue. This would mean - * that the enqueue/dequeue operations do not need to be recast as deliver/acknowledge operations, which may be - * conceptually neater. - * - * For example: - * <pre> - * public interface Transactional - * { - * public void commit(); - * public void rollback(); - * } - * - * public interface TransactionalQueue<E> extends Transactional, SizeableQueue<E> - * {} - * - * public class Queues - * { - * ... - * // For transactional messaging, take a transactional view onto the queue. - * public static <E> TransactionalQueue<E> getTransactionalQueue(SizeableQueue<E> queue) { ... } - * - * // For non-transactional messaging, take a non-transactional view onto the queue. - * public static <E> TransactionalQueue<E> getNonTransactionalQueue(SizeableQueue<E> queue) { ... } - * } - * </pre> - */ -public interface TransactionalContext -{ - /** - * Explicitly begins the transaction, if it has not already been started. {@link #commit} or {@link #rollback} - * should automatically begin the next transaction in the chain. - * - * @throws AMQException If the transaction cannot be started for any reason. - */ - void beginTranIfNecessary() throws AMQException; - - /** - * Makes all pending operations on the transaction permanent and visible. - * - * @throws AMQException If the transaction cannot be committed for any reason. - */ - void commit() throws AMQException; - - /** - * Erases all pending operations on the transaction. - * - * @throws AMQException If the transaction cannot be committed for any reason. - */ - void rollback() throws AMQException; - - /** - * Delivers the specified message to the specified queue. - * - * <p/>This is an 'enqueue' operation. - * - * @param queue - * @param message The message to deliver - * @throws AMQException If the message cannot be delivered for any reason. - */ - void deliver(final AMQQueue queue, AMQMessage message) throws AMQException; - - /** - * Requeues the specified message entry (message queue pair) - * - * - * @param queueEntry The message,queue pair - * - * @throws AMQException If the message cannot be delivered for any reason. - */ - void requeue(QueueEntry queueEntry) throws AMQException; - - - /** - * Acknowledges a message or many messages as delivered. All messages up to a specified one, may be acknowledged by - * setting the 'multiple' flag. It is also possible for the acknowledged message id to be zero, when the 'multiple' - * flag is set, in which case an acknowledgement up to the latest delivered message should be done. - * - * <p/>This is a 'dequeue' operation. - * - * @param deliveryTag The id of the message to acknowledge, or zero, if using multiple acknowledgement - * up to the latest message. - * @param lastDeliveryTag The latest message delivered. - * @param multiple <tt>true</tt> if all message ids up the acknowledged one or latest delivered, are - * to be acknowledged, <tt>false</tt> otherwise. - * @param unacknowledgedMessageMap The unacknowledged messages in the transaction, to remove the acknowledged message - * from. - * - * @throws AMQException If the message cannot be acknowledged for any reason. - */ - void acknowledgeMessage(long deliveryTag, long lastDeliveryTag, boolean multiple, - UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException; - - /** - * Notifies the transactional context that a message has been fully received. The actual message that was received - * is not specified. This event may be used to trigger a process related to the receipt of the message, for example, - * flushing its data to disk. - * - * @param persistent <tt>true</tt> if the received message is persistent, <tt>false</tt> otherwise. - * - * @throws AMQException If the fully received event cannot be processed for any reason. - */ - void messageFullyReceived(boolean persistent) throws AMQException; - - /** - * Notifies the transactional context that a message has been delivered, succesfully or otherwise. The actual - * message that was delivered is not specified. This event may be used to trigger a process related to the - * outcome of the delivery of the message, for example, cleaning up failed deliveries. - * - * @param protocolSession The protocol session of the deliverable message. - * - * @throws AMQException If the message processed event cannot be handled for any reason. - */ - void messageProcessed(AMQProtocolSession protocolSession) throws AMQException; - - /** - * Gets the message store context associated with this transactional context. - * - * @return The message store context associated with this transactional context. - */ - StoreContext getStoreContext(); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java deleted file mode 100644 index 46a68b6a23..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; - -/** Holds a list of TxnOp instance representing transactional operations. */ -public class TxnBuffer -{ - private final List<TxnOp> _ops = new ArrayList<TxnOp>(); - private static final Logger _log = Logger.getLogger(TxnBuffer.class); - - public TxnBuffer() - { - } - - public void commit(StoreContext context) throws AMQException - { - if (_log.isDebugEnabled()) - { - _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops); - } - - if (prepare(context)) - { - for (TxnOp op : _ops) - { - op.commit(context); - } - } - _ops.clear(); - } - - private boolean prepare(StoreContext context) throws AMQException - { - for (int i = 0; i < _ops.size(); i++) - { - TxnOp op = _ops.get(i); - try - { - op.prepare(context); - } - catch (AMQException e) - { - undoPrepare(i); - throw e; - } - catch (RuntimeException e) - { - undoPrepare(i); - throw e; - } - } - return true; - } - - private void undoPrepare(int lastPrepared) - { - //compensate previously prepared ops - for (int j = 0; j < lastPrepared; j++) - { - _ops.get(j).undoPrepare(); - } - } - - - - public void rollback(StoreContext context) throws AMQException - { - for (TxnOp op : _ops) - { - op.rollback(context); - } - _ops.clear(); - } - - public void enlist(TxnOp op) - { - _ops.add(op); - } - - public void cancel(TxnOp op) - { - _ops.remove(op); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java deleted file mode 100644 index 919c078cf0..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; - -/** - * This provides the abstraction of an individual operation within a - * transaction. It is used by the TxnBuffer class. - */ -public interface TxnOp -{ - /** - * Do the part of the operation that updates persistent state - */ - public void prepare(StoreContext context) throws AMQException; - /** - * Complete the operation started by prepare. Can now update in - * memory state or make netork transfers. - */ - public void commit(StoreContext context) throws AMQException; - /** - * This is not the same as rollback. Unfortunately the use of an - * in memory reference count as a locking mechanism and a test for - * whether a message should be deleted means that as things are, - * handling an acknowledgement unavoidably alters both memory and - * persistent state on prepare. This is needed to 'compensate' or - * undo the in-memory change if the peristent update of later ops - * fails. - */ - public void undoPrepare(); - /** - * Rolls back the operation. - */ - public void rollback(StoreContext context) throws AMQException; -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index 3b776a62b4..8ce9cbc480 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -20,9 +20,7 @@ */ package org.apache.qpid.server.virtualhost; -import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; @@ -30,7 +28,6 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.server.AMQBrokerManagerMBean; import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.messages.VirtualHostMessages; import org.apache.qpid.server.configuration.ExchangeConfiguration; import org.apache.qpid.server.configuration.QueueConfiguration; @@ -52,11 +49,11 @@ import org.apache.qpid.server.queue.MessageMetaData; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.access.Accessable; -import org.apache.qpid.server.security.access.plugins.SimpleXML; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreContext; +import org.apache.qpid.server.store.DurableConfigurationStore; import javax.management.NotCompliantMBeanException; import java.util.Collections; @@ -228,17 +225,17 @@ public class VirtualHost implements Accessable // file and write them in to the new routing Table. for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue) { - _messageStore.createQueue(cqt.queue, cqt.arguments); + getDurableConfigurationStore().createQueue(cqt.queue, cqt.arguments); } for (Exchange exchange : configFileRT.exchange) { - _messageStore.createExchange(exchange); + getDurableConfigurationStore().createExchange(exchange); } for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings) { - _messageStore.bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments); + getDurableConfigurationStore().bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments); } _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig); @@ -352,7 +349,7 @@ public class VirtualHost implements Accessable if (queue.isDurable()) { - _messageStore.createQueue(queue); + getDurableConfigurationStore().createQueue(queue); } String exchangeName = queueConfiguration.getExchange(); @@ -416,6 +413,11 @@ public class VirtualHost implements Accessable return _messageStore; } + public DurableConfigurationStore getDurableConfigurationStore() + { + return _messageStore; + } + public AuthenticationManager getAuthenticationManager() { return _authenticationManager; @@ -487,7 +489,7 @@ public class VirtualHost implements Accessable { } - public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException + public void removeMessage(Long messageId) throws AMQException { //To change body of implemented methods use File | Settings | File Templates. } @@ -553,6 +555,24 @@ public class VirtualHost implements Accessable //To change body of implemented methods use File | Settings | File Templates. } + public StoreFuture commitTranAsync(StoreContext context) throws AMQException + { + commitTran(context); + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + + } + public void abortTran(StoreContext context) throws AMQException { //To change body of implemented methods use File | Settings | File Templates. @@ -568,22 +588,26 @@ public class VirtualHost implements Accessable return null; //To change body of implemented methods use File | Settings | File Templates. } - public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException + public void storeContentBodyChunk( + Long messageId, + int index, + ContentChunk contentBody, + boolean lastContentBody) throws AMQException { //To change body of implemented methods use File | Settings | File Templates. } - public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException + public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException { //To change body of implemented methods use File | Settings | File Templates. } - public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException + public MessageMetaData getMessageMetaData(Long messageId) throws AMQException { return null; //To change body of implemented methods use File | Settings | File Templates. } - public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException + public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException { return null; //To change body of implemented methods use File | Settings | File Templates. } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java index 5e99997863..8df4afa2db 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java @@ -62,6 +62,6 @@ public class Purge extends Move protected void doCommand(AMQQueue fromQueue, long start, long end, AMQQueue toQueue) { - fromQueue.removeMessagesFromQueue(start, end, _storeContext); + fromQueue.removeMessagesFromQueue(start, end); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java index d846d9976b..6acea07719 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java @@ -171,7 +171,7 @@ public class Show extends AbstractCommand // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getEncoding(); // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getExpiration(); // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getHeaders(); -// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getMessageId(); +// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getMessageNumber(); // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getPriority(); // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getPropertyFlags(); // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getReplyTo(); @@ -182,14 +182,14 @@ public class Show extends AbstractCommand // //Print out all the property names // ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getHeaders().getPropertyNames(); // -// msg.getMessageId(); +// msg.getMessageNumber(); // msg.getSize(); // msg.getArrivalTime(); // msg.getDeliveredSubscription(); // msg.getDeliveredToConsumer(); // msg.getMessageHandle(); -// msg.getMessageId(); +// msg.getMessageNumber(); // msg.getMessagePublishInfo(); // msg.getPublisher(); @@ -352,7 +352,7 @@ public class Show extends AbstractCommand ispersitent.add(msg.isPersistent() ? "true" : "false"); - isredelivered.add(msg.isRedelivered() ? "true" : "false"); + isredelivered.add(entry.isRedelivered() ? "true" : "false"); isdelivered.add(entry.getDeliveredToConsumer() ? "true" : "false"); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java index 06aef13dde..f39f94a1b6 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.server; import junit.framework.TestCase; import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; -import org.apache.qpid.server.queue.MockQueueEntry; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.SimpleQueueEntryList; import org.apache.qpid.server.queue.MockAMQMessage; @@ -30,15 +29,15 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.QueueEntryIterator; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.MockSubscription; +import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.AMQException; import java.util.Map; import java.util.LinkedHashMap; import java.util.LinkedList; -import java.util.Iterator; /** * QPID-1385 : Race condition between added to unacked map and resending due to a rollback. @@ -63,6 +62,7 @@ public class ExtractResendAndRequeueTest extends TestCase UnacknowledgedMessageMapImpl _unacknowledgedMessageMap; private static final int INITIAL_MSG_COUNT = 10; private AMQQueue _queue = new MockAMQQueue(getName()); + private MessageStore _messageStore = new MemoryMessageStore(); private LinkedList<QueueEntry> _referenceList = new LinkedList<QueueEntry>(); @Override @@ -137,7 +137,7 @@ public class ExtractResendAndRequeueTest extends TestCase // requeueIfUnabletoResend doesn't matter here. _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, new StoreContext())); + msgToResend, true, _messageStore)); assertEquals("Message count for resend not correct.", INITIAL_MSG_COUNT, msgToResend.size()); assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); @@ -166,7 +166,7 @@ public class ExtractResendAndRequeueTest extends TestCase // requeueIfUnabletoResend doesn't matter here. _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, new StoreContext())); + msgToResend, true, _messageStore)); assertEquals("Message count for resend not correct.", 0, msgToResend.size()); assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); @@ -187,7 +187,7 @@ public class ExtractResendAndRequeueTest extends TestCase // requeueIfUnabletoResend = true so all messages should go to msgToRequeue _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, new StoreContext())); + msgToResend, true, _messageStore)); assertEquals("Message count for resend not correct.", 0, msgToResend.size()); assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); @@ -208,7 +208,7 @@ public class ExtractResendAndRequeueTest extends TestCase // requeueIfUnabletoResend = false so all messages should be dropped all maps should be empty _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, false, new StoreContext())); + msgToResend, false, _messageStore)); assertEquals("Message count for resend not correct.", 0, msgToResend.size()); assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); @@ -240,7 +240,7 @@ public class ExtractResendAndRequeueTest extends TestCase // requeueIfUnabletoResend : value doesn't matter here as queue has been deleted _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, false, new StoreContext())); + msgToResend, false, _messageStore)); assertEquals("Message count for resend not correct.", 0, msgToResend.size()); assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java deleted file mode 100644 index eac887bd60..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.ack; - -import junit.framework.TestCase; - -import org.apache.commons.configuration.PropertiesConfiguration; -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.queue.MessageHandleFactory; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.AMQMessageHandle; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.TestMemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; - -import java.util.*; - -public class TxAckTest extends TestCase -{ - private Scenario individual; - private Scenario multiple; - private Scenario combined; - - protected void setUp() throws Exception - { - super.setUp(); - - - // Highlight that this test will cause the creation of an AR - ApplicationRegistry.getInstance(); - - //ack only 5th msg - individual = new Scenario(10, Arrays.asList(5l), Arrays.asList(1l, 2l, 3l, 4l, 6l, 7l, 8l, 9l, 10l)); - individual.update(5, false); - - //ack all up to and including 5th msg - multiple = new Scenario(10, Arrays.asList(1l, 2l, 3l, 4l, 5l), Arrays.asList(6l, 7l, 8l, 9l, 10l)); - multiple.update(5, true); - - //leave only 8th and 9th unacked - combined = new Scenario(10, Arrays.asList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 10l), Arrays.asList(8l, 9l)); - combined.update(3, false); - combined.update(5, true); - combined.update(7, true); - combined.update(2, true);//should be ignored - combined.update(1, false);//should be ignored - combined.update(10, false); - } - - @Override - protected void tearDown() throws Exception - { - individual.stop(); - multiple.stop(); - combined.stop(); - - // Ensure we close the AR we created - ApplicationRegistry.remove(); - super.tearDown(); - } - - public void testPrepare() throws AMQException - { - individual.prepare(); - multiple.prepare(); - combined.prepare(); - } - - public void testUndoPrepare() throws AMQException - { - individual.undoPrepare(); - multiple.undoPrepare(); - combined.undoPrepare(); - } - - public void testCommit() throws AMQException - { - individual.commit(); - multiple.commit(); - combined.commit(); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(TxAckTest.class); - } - - private class Scenario - { - private final UnacknowledgedMessageMap _map = new UnacknowledgedMessageMapImpl(5000); - private final TxAck _op = new TxAck(_map); - private final List<Long> _acked; - private final List<Long> _unacked; - private StoreContext _storeContext = new StoreContext(); - private AMQQueue _queue; - - Scenario(int messageCount, List<Long> acked, List<Long> unacked) throws Exception - { - TransactionalContext txnContext = new NonTransactionalContext(new TestMemoryMessageStore(), - _storeContext, null, - new LinkedList<RequiredDeliveryException>() - ); - - VirtualHost virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); - - _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("test"), false, null, false, - virtualHost, null); - - for (int i = 0; i < messageCount; i++) - { - long deliveryTag = i + 1; - - MessagePublishInfo info = new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return null; - } - - public void setExchange(AMQShortString exchange) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isImmediate() - { - return false; - } - - public boolean isMandatory() - { - return false; - } - - public AMQShortString getRoutingKey() - { - return null; - } - }; - - TestMessage message = new TestMessage(deliveryTag, i, info, txnContext.getStoreContext()); - StoreContext sc = StoreContext.setCurrentContext(new StoreContext()); - _map.add(deliveryTag, _queue.enqueue(message)); - StoreContext.setCurrentContext(sc); - } - _acked = acked; - _unacked = unacked; - } - - void update(long deliverytag, boolean multiple) - { - _op.update(deliverytag, multiple); - } - - private void assertCount(List<Long> tags, int expected) - { - for (long tag : tags) - { - QueueEntry u = _map.get(tag); - assertTrue("Message not found for tag " + tag, u != null); - ((TestMessage) u.getMessage()).assertCountEquals(expected); - } - } - - void prepare() throws AMQException - { - _op.consolidate(); - _op.prepare(_storeContext); - - assertCount(_acked, -1); - assertCount(_unacked, 0); - - } - - void undoPrepare() - { - _op.consolidate(); - _op.undoPrepare(); - - assertCount(_acked, 1); - assertCount(_unacked, 0); - } - - void commit() - { - _op.consolidate(); - _op.commit(_storeContext); - - //check acked messages are removed from map - Set<Long> keys = new HashSet<Long>(_map.getDeliveryTags()); - keys.retainAll(_acked); - assertTrue("Expected messages with following tags to have been removed from map: " + keys, keys.isEmpty()); - //check unacked messages are still in map - keys = new HashSet<Long>(_unacked); - keys.removeAll(_map.getDeliveryTags()); - assertTrue("Expected messages with following tags to still be in map: " + keys, keys.isEmpty()); - } - - public void stop() - { - _queue.stop(); - } - } - - private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody) - { - final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, - null, - false); - try - { - amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(), - publishBody, - new ContentHeaderBody() - { - public int getSize() - { - return 1; - } - }); - } - catch (AMQException e) - { - // won't happen - } - - - return amqMessageHandle; - } - - - private class TestMessage extends AMQMessage - { - private final long _tag; - private int _count; - - TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext) - throws AMQException - { - super(createMessageHandle(messageId, publishBody), storeContext, publishBody); - _tag = tag; - } - - - public boolean incrementReference() - { - _count++; - return true; - } - - public void decrementReference(StoreContext context) - { - _count--; - } - - void assertCountEquals(int expected) - { - assertEquals("Wrong count for message with tag " + _tag, expected, _count); - } - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 93e7e756e6..6dce7aacb7 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -421,7 +421,7 @@ public class ServerConfigurationTest extends TestCase { // Check default ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(0, serverConfig.getMaximumMessageCount()); + assertEquals(0, serverConfig.getMaximumMessageCount()); // Check value we set _config.setProperty("maximumMessageCount", 10L); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java index 28f5d417ff..2747094caf 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java @@ -29,13 +29,8 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.SkeletonMessageStore; import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.log4j.Logger; @@ -54,8 +49,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase */ private MessageStore _store = new MemoryMessageStore(); - private StoreContext _storeContext = new StoreContext(); - private MessageHandleFactory _handleFactory = new MessageHandleFactory(); private int count; @@ -93,14 +86,18 @@ public class AbstractHeadersExchangeTestBase extends TestCase } - protected void route(Message m) throws AMQException + protected int route(Message m) throws AMQException { m.route(exchange); m.getIncomingMessage().routingComplete(_store, _handleFactory); if(m.getIncomingMessage().allContentReceived()) { - m.getIncomingMessage().deliverToQueues(); + for(AMQQueue q : m.getIncomingMessage().getDestinationQueues()) + { + q.enqueue(m); + } } + return m.getIncomingMessage().getDestinationQueues().size(); } protected void routeAndTest(Message m, TestQueue... expected) throws AMQException @@ -120,10 +117,8 @@ public class AbstractHeadersExchangeTestBase extends TestCase protected void routeAndTest(Message m, boolean expectReturn, List<TestQueue> expected) throws AMQException { - try - { - route(m); - assertFalse("Expected "+m+" to be returned due to manadatory flag, and lack of routing",expectReturn); + int queueCount = route(m); + for (TestQueue q : queues) { if (expected.contains(q)) @@ -137,12 +132,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase //assert !m.isInQueue(q) : "Did not expect " + m + " to be delivered to " + q; } } - } - catch (NoRouteException ex) - { - assertTrue("Expected "+m+" not to be returned",expectReturn); - } + if(expectReturn) + { + assertEquals("Expected "+m+" to be returned due to manadatory flag, and lack of routing",0, queueCount); + } } @@ -244,6 +238,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase { final List<HeadersExchangeTest.Message> messages = new ArrayList<HeadersExchangeTest.Message>(); + public String toString() + { + return getName().toString(); + } + public TestQueue(AMQShortString name) throws AMQException { super(name, false, new AMQShortString("test"), true, ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test")); @@ -334,6 +333,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase //To change body of implemented methods use File | Settings | File Templates. } + public boolean releaseButRetain() + { + return false; + } + public boolean immediateAndNotDelivered() { return false; //To change body of implemented methods use File | Settings | File Templates. @@ -344,6 +348,16 @@ public class AbstractHeadersExchangeTestBase extends TestCase //To change body of implemented methods use File | Settings | File Templates. } + public AMQMessageHeader getMessageHeader() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isPersistent() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + public boolean isRedelivered() { return false; //To change body of implemented methods use File | Settings | File Templates. @@ -369,7 +383,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase return false; //To change body of implemented methods use File | Settings | File Templates. } - public void requeue(StoreContext storeContext) throws AMQException + public void requeue() { //To change body of implemented methods use File | Settings | File Templates. } @@ -379,12 +393,12 @@ public class AbstractHeadersExchangeTestBase extends TestCase //To change body of implemented methods use File | Settings | File Templates. } - public void dequeue(final StoreContext storeContext) throws FailedDequeueException + public void dequeue() { //To change body of implemented methods use File | Settings | File Templates. } - public void dispose(final StoreContext storeContext) throws MessageCleanupException + public void dispose() { //To change body of implemented methods use File | Settings | File Templates. } @@ -394,7 +408,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase //To change body of implemented methods use File | Settings | File Templates. } - public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException + public void discard() { //To change body of implemented methods use File | Settings | File Templates. } @@ -438,10 +452,9 @@ public class AbstractHeadersExchangeTestBase extends TestCase public TestIncomingMessage(final long messageId, final MessagePublishInfo info, - final TransactionalContext txnContext, final AMQProtocolSession publisher) { - super(messageId, info, txnContext, publisher); + super(messageId, info, publisher); } @@ -468,14 +481,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase private static MessageStore _messageStore = new SkeletonMessageStore(); - private static StoreContext _storeContext = new StoreContext(); - - - private static TransactionalContext _txnContext = new NonTransactionalContext(_messageStore, _storeContext, - null, - new LinkedList<RequiredDeliveryException>() - ); - Message(AMQProtocolSession protocolSession, String id, String... headers) throws AMQException { this(protocolSession, id, getHeaders(headers)); @@ -496,11 +501,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase ContentHeaderBody header, List<ContentBody> bodies) throws AMQException { - super(createMessageHandle(messageId, publish, header), _txnContext.getStoreContext(), publish); + super(createMessageHandle(messageId, publish, header), header, header.bodySize, publish); - _incoming = new TestIncomingMessage(getMessageId(),publish, _txnContext, protocolsession); + _incoming = new TestIncomingMessage(getMessageId(),publish, protocolsession); _incoming.setContentHeaderBody(header); @@ -515,14 +520,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase _messageStore, true); - try - { - amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),publish,header); - } - catch (AMQException e) - { - - } + amqMessageHandle.setPublishAndContentHeaderBody(publish,header); return amqMessageHandle; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java index 507096bd42..bd0f273742 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java @@ -25,20 +25,14 @@ import junit.framework.Assert; import org.apache.qpid.server.queue.*; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.RequiredDeliveryException; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import java.util.LinkedList; - public class DestWildExchangeTest extends TestCase { @@ -46,7 +40,6 @@ public class DestWildExchangeTest extends TestCase VirtualHost _vhost; MessageStore _store; - StoreContext _context; InternalTestProtocolSession _protocolSession; @@ -56,7 +49,6 @@ public class DestWildExchangeTest extends TestCase _exchange = new TopicExchange(); _vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); _store = new MemoryMessageStore(); - _context = new StoreContext(); _protocolSession = new InternalTestProtocolSession(_vhost); } @@ -74,7 +66,7 @@ public class DestWildExchangeTest extends TestCase MessagePublishInfo info = new PublishInfo(new AMQShortString("a.b")); - IncomingMessage message = new IncomingMessage(0L, info, null, _protocolSession); + IncomingMessage message = new IncomingMessage(0L, info, _protocolSession); message.enqueue(_exchange.route(message)); @@ -89,33 +81,20 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.b"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.c"); - try - { - routeMessage(message); - fail("Message has no route and should fail to be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } @@ -129,52 +108,33 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.b"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.c"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + int queueCount = routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a"); - try - { - routeMessage(message); - fail("Message has no route and should fail to be routed"); - } - catch (AMQException nre) - { - } + + queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } @@ -187,89 +147,56 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.b.c"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + int queueCount = routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.b"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + queueCount = routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.c"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + queueCount = routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has route and should be routed"); - } + queueCount = routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("b"); - try - { - routeMessage(message); - fail("Message has no route and should fail to be routed"); - } - catch (AMQException nre) - { - } + + queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } @@ -283,38 +210,24 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.c.d.b"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.c.b"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); } @@ -327,66 +240,39 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.c.b.b"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.a.b.c"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.b.c.b"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.b.c.b.c"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); } @@ -400,34 +286,21 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.c.b.b.c"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.a.b.c.d"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); } @@ -440,33 +313,20 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.c.b.b.c"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); message = createMessage("a.a.b.c.d"); - try - { - routeMessage(message); - } - catch (AMQException nre) - { - fail("Message has no route and should be routed"); - } + routeMessage(message); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); - queue.deleteMessageFromTop(_context); + queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); } @@ -479,25 +339,24 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.b.c"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } - private void routeMessage(final IncomingMessage message) + private int routeMessage(final IncomingMessage message) throws AMQException { message.enqueue(_exchange.route(message)); message.routingComplete(_store, new MessageHandleFactory()); - message.deliverToQueues(); + AMQMessage msg = new AMQMessage(message.getMessageHandle(), message.getContentHeader(), message.getSize(), message.getMessagePublishInfo()); + for(AMQQueue q : message.getDestinationQueues()) + { + q.enqueue(msg); + } + return message.getDestinationQueues().size(); } public void testMoreRouting() throws AMQException @@ -508,14 +367,8 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a.b.c"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -529,14 +382,8 @@ public class DestWildExchangeTest extends TestCase IncomingMessage message = createMessage("a"); - try - { - routeMessage(message); - fail("Message has route and should not be routed"); - } - catch (AMQException nre) - { - } + int queueCount = routeMessage(message); + Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -546,11 +393,7 @@ public class DestWildExchangeTest extends TestCase { MessagePublishInfo info = new PublishInfo(new AMQShortString(s)); - TransactionalContext trancontext = new NonTransactionalContext(_store, _context, null, - new LinkedList<RequiredDeliveryException>() - ); - - IncomingMessage message = new IncomingMessage(0L, info, trancontext,_protocolSession); + IncomingMessage message = new IncomingMessage(0L, info, _protocolSession); message.setContentHeaderBody( new ContentHeaderBody()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java index ec7bf1cb72..f6bd946bff 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java @@ -21,17 +21,17 @@ package org.apache.qpid.server.protocol; import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.queue.AMQMessage; +import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.TestNetworkDriver; @@ -68,7 +68,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr public byte getProtocolMajorVersion() { return (byte) 8; - } + } public byte getProtocolMinorVersion() { @@ -99,6 +99,15 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr } } + public void writeReturn(MessagePublishInfo messagePublishInfo, + ContentHeaderBody header, + Iterator<AMQDataBlock> bodyFrameIterator, + int channelId, + int replyCode, + AMQShortString replyText) throws AMQException + { + + } // *** ProtocolOutputConverter Implementation public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException { @@ -108,7 +117,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr { } - public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException { _deliveryCount.incrementAndGet(); @@ -130,11 +139,11 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr consumers.put(consumerTag, consumerDelivers); } - consumerDelivers.add(new DeliveryPair(deliveryTag, message)); + consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage())); } } - public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException + public void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException { } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java index 19470e6226..8e5d833a93 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java @@ -20,13 +20,7 @@ */ package org.apache.qpid.server.queue; -import java.util.ArrayList; -import java.util.LinkedList; - -import javax.management.Notification; - import junit.framework.TestCase; - import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; @@ -34,7 +28,6 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.RequiredDeliveryException; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.protocol.AMQProtocolEngine; import org.apache.qpid.server.protocol.InternalTestProtocolSession; @@ -42,13 +35,13 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.virtualhost.VirtualHost; +import javax.management.Notification; +import java.util.ArrayList; + /** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */ public class AMQQueueAlertTest extends TestCase { @@ -61,11 +54,6 @@ public class AMQQueueAlertTest extends TestCase private VirtualHost _virtualHost; private AMQProtocolEngine _protocolSession; private MessageStore _messageStore = new MemoryMessageStore(); - private StoreContext _storeContext = new StoreContext(); - private TransactionalContext _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext, - null, - new LinkedList<RequiredDeliveryException>() - ); private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE; /** @@ -75,6 +63,10 @@ public class AMQQueueAlertTest extends TestCase */ public void testMessageCountAlert() throws Exception { + _protocolSession = new InternalTestProtocolSession(_virtualHost); + AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore); + _protocolSession.addChannel(channel); + _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"), false, _virtualHost, null); @@ -82,7 +74,7 @@ public class AMQQueueAlertTest extends TestCase _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); - sendMessages(MAX_MESSAGE_COUNT, 256l); + sendMessages(channel, MAX_MESSAGE_COUNT, 256l); assertTrue(_queueMBean.getMessageCount() == MAX_MESSAGE_COUNT); Notification lastNotification = _queueMBean.getLastNotification(); @@ -99,6 +91,10 @@ public class AMQQueueAlertTest extends TestCase */ public void testMessageSizeAlert() throws Exception { + _protocolSession = new InternalTestProtocolSession(_virtualHost); + AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore); + _protocolSession.addChannel(channel); + _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"), false, _virtualHost, null); @@ -106,7 +102,7 @@ public class AMQQueueAlertTest extends TestCase _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); _queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE); - sendMessages(1, MAX_MESSAGE_SIZE * 2); + sendMessages(channel, 1, MAX_MESSAGE_SIZE * 2); assertTrue(_queueMBean.getMessageCount() == 1); Notification lastNotification = _queueMBean.getLastNotification(); @@ -125,6 +121,10 @@ public class AMQQueueAlertTest extends TestCase */ public void testQueueDepthAlertNoSubscriber() throws Exception { + _protocolSession = new InternalTestProtocolSession(_virtualHost); + AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore); + _protocolSession.addChannel(channel); + _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"), false, _virtualHost, null); @@ -134,7 +134,7 @@ public class AMQQueueAlertTest extends TestCase while (_queue.getQueueDepth() < MAX_QUEUE_DEPTH) { - sendMessages(1, MAX_MESSAGE_SIZE); + sendMessages(channel, 1, MAX_MESSAGE_SIZE); } Notification lastNotification = _queueMBean.getLastNotification(); @@ -154,6 +154,10 @@ public class AMQQueueAlertTest extends TestCase */ public void testMessageAgeAlert() throws Exception { + _protocolSession = new InternalTestProtocolSession(_virtualHost); + AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore); + _protocolSession.addChannel(channel); + _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"), false, _virtualHost, null); @@ -161,7 +165,7 @@ public class AMQQueueAlertTest extends TestCase _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); _queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE); - sendMessages(1, MAX_MESSAGE_SIZE); + sendMessages(channel, 1, MAX_MESSAGE_SIZE); // Ensure message sits on queue long enough to age. Thread.sleep(MAX_MESSAGE_AGE * 2); @@ -201,7 +205,7 @@ public class AMQQueueAlertTest extends TestCase // Send messages(no of message to be little more than what can cause a Queue_Depth alert) int messageCount = Math.round(MAX_QUEUE_DEPTH / MAX_MESSAGE_SIZE) + 10; long totalSize = (messageCount * MAX_MESSAGE_SIZE); - sendMessages(messageCount, MAX_MESSAGE_SIZE); + sendMessages(channel, messageCount, MAX_MESSAGE_SIZE); // Check queueDepth. There should be no messages on the queue and as the subscriber is listening // so there should be no Queue_Deoth alert raised @@ -281,7 +285,7 @@ public class AMQQueueAlertTest extends TestCase ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); contentHeaderBody.bodySize = size; // in bytes - IncomingMessage message = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession); + IncomingMessage message = new IncomingMessage(_messageStore.getNewMessageId(), publish, _protocolSession); message.setContentHeaderBody(contentHeaderBody); return message; @@ -305,7 +309,7 @@ public class AMQQueueAlertTest extends TestCase } - private void sendMessages(long messageCount, final long size) throws AMQException + private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException { IncomingMessage[] messages = new IncomingMessage[(int) messageCount]; for (int i = 0; i < messages.length; i++) @@ -339,7 +343,11 @@ public class AMQQueueAlertTest extends TestCase } }); - messages[i].deliverToQueues(); + _queue.enqueue(new AMQMessage(messages[i].getMessageHandle(), + messages[i].getContentHeader(), + messages[i].getSize(), + messages[i].getMessagePublishInfo())); + } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java index 03eb7021ad..b135567029 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java @@ -29,7 +29,6 @@ import org.apache.qpid.framing.ContentBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.RequiredDeliveryException; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactory; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; @@ -38,10 +37,7 @@ import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.txn.TransactionalContext; -import org.apache.qpid.server.txn.NonTransactionalContext; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.mina.common.ByteBuffer; @@ -49,8 +45,6 @@ import org.apache.mina.common.ByteBuffer; import javax.management.JMException; import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Collections; /** * Test class to test AMQQueueMBean attribtues and operations @@ -61,8 +55,6 @@ public class AMQQueueMBeanTest extends TestCase private AMQQueue _queue; private AMQQueueMBean _queueMBean; private MessageStore _messageStore; - private StoreContext _storeContext = new StoreContext(); - private TransactionalContext _transactionalContext; private VirtualHost _virtualHost; private AMQProtocolSession _protocolSession; private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE; @@ -108,7 +100,7 @@ public class AMQQueueMBeanTest extends TestCase //Ensure that the data has been removed from the Store verifyBrokerState(); } - + public void testDeleteMessages() throws Exception { int messageCount = 10; @@ -129,9 +121,9 @@ public class AMQQueueMBeanTest extends TestCase } catch(Exception e) { - + } - + //delete last message, leaving 2nd to 9th _queueMBean.deleteMessages(10L,10L); assertTrue(_queueMBean.getMessageCount() == (messageCount - 2)); @@ -143,7 +135,7 @@ public class AMQQueueMBeanTest extends TestCase } catch(Exception e) { - + } //delete remaining messages, leaving none @@ -162,7 +154,7 @@ public class AMQQueueMBeanTest extends TestCase TestableMemoryMessageStore store = new TestableMemoryMessageStore((MemoryMessageStore) _virtualHost.getMessageStore()); // Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up. - assertNotNull("ContentBodyMap should not be null", store.getContentBodyMap()); + assertNotNull("ContentBodyMap should not be null", store.getContentBodyMap()); assertEquals("Expected the store to have no content:" + store.getContentBodyMap(), 0, store.getContentBodyMap().size()); assertNotNull("MessageMetaDataMap should not be null", store.getMessageMetaDataMap()); assertEquals("Expected the store to have no metadata:" + store.getMessageMetaDataMap(), 0, store.getMessageMetaDataMap().size()); @@ -170,7 +162,7 @@ public class AMQQueueMBeanTest extends TestCase public void testConsumerCount() throws AMQException { - + assertTrue(_queue.getActiveConsumerCount() == 0); assertTrue(_queueMBean.getActiveConsumerCount() == 0); @@ -182,7 +174,7 @@ public class AMQQueueMBeanTest extends TestCase Subscription subscription = SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager()); - + _queue.registerSubscription(subscription, false); assertEquals(1,(int)_queueMBean.getActiveConsumerCount()); @@ -225,7 +217,6 @@ public class AMQQueueMBeanTest extends TestCase assertTrue(_queueMBean.getMaximumQueueDepth() == (maxQueueDepth)); assertTrue(_queueMBean.getName().equals("testQueue")); - assertTrue(_queueMBean.getOwner().equals("AMQueueMBeanTest")); assertFalse(_queueMBean.isAutoDelete()); assertFalse(_queueMBean.isDurable()); } @@ -261,7 +252,7 @@ public class AMQQueueMBeanTest extends TestCase { } - + try { long end = Integer.MAX_VALUE; @@ -275,13 +266,12 @@ public class AMQQueueMBeanTest extends TestCase } IncomingMessage msg = message(false, false); - long id = msg.getMessageId(); - _queue.clearQueue(_storeContext); + long id = msg.getMessageNumber(); + _queue.clearQueue(); ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); qs.add(_queue); msg.enqueue(qs); msg.routingComplete(_messageStore, new MessageHandleFactory()); - msg.addContentBodyFrame(new ContentChunk() { ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE); @@ -301,7 +291,12 @@ public class AMQQueueMBeanTest extends TestCase } }); - msg.deliverToQueues(); + + AMQMessage m = new AMQMessage(msg.getMessageHandle(), msg.getContentHeader(), msg.getSize(), msg.getMessagePublishInfo()); + for(AMQQueue q : msg.getDestinationQueues()) + { + q.enqueue(m); + } // _queue.process(_storeContext, new QueueEntry(_queue, msg), false); _queueMBean.viewMessageContent(id); try @@ -350,7 +345,7 @@ public class AMQQueueMBeanTest extends TestCase contentHeaderBody.bodySize = MESSAGE_SIZE; // in bytes contentHeaderBody.properties = new BasicContentHeaderProperties(); ((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) (persistent ? 2 : 1)); - IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession); + IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publish, _protocolSession); msg.setContentHeaderBody(contentHeaderBody); return msg; @@ -364,11 +359,6 @@ public class AMQQueueMBeanTest extends TestCase _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test"); _messageStore = _virtualHost.getMessageStore(); - _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext, - null, - new LinkedList<RequiredDeliveryException>() - ); - _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("AMQueueMBeanTest"), false, _virtualHost, null); _queueMBean = new AMQQueueMBean(_queue); @@ -400,7 +390,12 @@ public class AMQQueueMBeanTest extends TestCase .convertToContentChunk( new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE), MESSAGE_SIZE))); - currentMessage.deliverToQueues(); + + AMQMessage m = new AMQMessage(currentMessage.getMessageHandle(), currentMessage.getContentHeader(), currentMessage.getSize(), currentMessage.getMessagePublishInfo()); + for(AMQQueue q : currentMessage.getDestinationQueues()) + { + q.enqueue(m); + } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java index 79f7d75aa9..0edcc182b0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java @@ -28,7 +28,8 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.RequiredDeliveryException; +import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.protocol.AMQProtocolSession; @@ -39,15 +40,9 @@ import org.apache.qpid.server.flow.Pre0_10CreditManager; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.TestMemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.txn.TransactionalContext; -import org.apache.qpid.server.util.NullApplicationRegistry; import java.util.ArrayList; -import java.util.LinkedList; import java.util.Set; -import java.util.Collections; /** * Tests that acknowledgements are handled correctly. @@ -62,8 +57,6 @@ public class AckTest extends TestCase private TestMemoryMessageStore _messageStore; - private StoreContext _storeContext = new StoreContext(); - private AMQChannel _channel; private AMQQueue _queue; @@ -99,9 +92,6 @@ public class AckTest extends TestCase private void publishMessages(int count, boolean persistent) throws AMQException { - TransactionalContext txnContext = new NonTransactionalContext(_messageStore, _storeContext, null, - new LinkedList<RequiredDeliveryException>() - ); _queue.registerSubscription(_subscription,false); MessageHandleFactory factory = new MessageHandleFactory(); for (int i = 1; i <= count; i++) @@ -136,7 +126,7 @@ public class AckTest extends TestCase return new AMQShortString("rk"); } }; - IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publishBody, txnContext,_protocolSession); + final IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publishBody, _protocolSession); //IncomingMessage msg2 = null; if (persistent) { @@ -160,7 +150,26 @@ public class AckTest extends TestCase msg.routingComplete(_messageStore, factory); if(msg.allContentReceived()) { - msg.deliverToQueues(); + Transaction txn = new AutoCommitTransaction(_messageStore); + txn.enqueue(_queue, msg, new Transaction.Action() { + public void postCommit() + { + try + { + _queue.enqueue(new AMQMessage(msg.getMessageHandle(), msg.getContentHeader(), msg.getSize(), msg.getMessagePublishInfo())); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + + public void onRollback() + { + //To change body of implemented methods use File | Settings | File Templates. + } + }); + } // we manually send the message to the subscription //_subscription.send(new QueueEntry(_queue,msg), _queue); @@ -178,8 +187,7 @@ public class AckTest extends TestCase publishMessages(msgCount, true); UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == msgCount); - assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount); + assertEquals("",msgCount,map.size()); Set<Long> deliveryTagSet = map.getDeliveryTags(); int i = 1; @@ -191,8 +199,6 @@ public class AckTest extends TestCase assertTrue(unackedMsg.getQueue() == _queue); } - assertTrue(map.size() == msgCount); - assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount); } /** diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java index 355ba6a362..85e8464bff 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.AMQException; import org.apache.qpid.framing.abstraction.MessagePublishInfo; @@ -30,8 +29,7 @@ public class MockAMQMessage extends AMQMessage throws AMQException { super(new MockAMQMessageHandle(messageId) , - (StoreContext)null, - (MessagePublishInfo)new MockMessagePublishInfo()); + (MessagePublishInfo)new MockMessagePublishInfo()); } protected MockAMQMessage(AMQMessage msg) diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java index bdb0707c27..434c2bde71 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.server.store.StoreContext; - public class MockAMQMessageHandle extends InMemoryMessageHandle { public MockAMQMessageHandle(final Long messageId) @@ -30,7 +28,7 @@ public class MockAMQMessageHandle extends InMemoryMessageHandle } @Override - public long getBodySize(StoreContext store) + public long getBodySize() { return 0l; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index 1d8400f736..77a1412f5f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -23,25 +23,19 @@ package org.apache.qpid.server.queue; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.PrincipalHolder; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.AMQException; -import org.apache.commons.configuration.Configuration; import java.util.List; import java.util.Set; import java.util.Map; -import java.util.HashMap; -import java.util.LinkedList; public class MockAMQQueue implements AMQQueue { @@ -51,6 +45,8 @@ public class MockAMQQueue implements AMQQueue private PrincipalHolder _principalHolder; + private Object _exclusiveOwner; + public MockAMQQueue(String name) { _name = new AMQShortString(name); @@ -171,7 +167,7 @@ public class MockAMQQueue implements AMQQueue return null; //To change body of implemented methods use File | Settings | File Templates. } - public void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException + public void requeue(QueueEntry entry) { //To change body of implemented methods use File | Settings | File Templates. } @@ -181,7 +177,7 @@ public class MockAMQQueue implements AMQQueue //To change body of implemented methods use File | Settings | File Templates. } - public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException + public void dequeue(QueueEntry entry) { //To change body of implemented methods use File | Settings | File Templates. } @@ -236,7 +232,7 @@ public class MockAMQQueue implements AMQQueue //To change body of implemented methods use File | Settings | File Templates. } - public void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext) + public void removeMessagesFromQueue(long fromMessageId, long toMessageId) { //To change body of implemented methods use File | Settings | File Templates. } @@ -295,12 +291,12 @@ public class MockAMQQueue implements AMQQueue return 0; //To change body of implemented methods use File | Settings | File Templates. } - public void deleteMessageFromTop(StoreContext storeContext) throws AMQException + public void deleteMessageFromTop() { //To change body of implemented methods use File | Settings | File Templates. } - public long clearQueue(StoreContext storeContext) throws AMQException + public long clearQueue() { return 0; //To change body of implemented methods use File | Settings | File Templates. } @@ -399,4 +395,15 @@ public class MockAMQQueue implements AMQQueue _principalHolder = principalHolder; } + public Object getExclusiveOwner() + { + return _exclusiveOwner; + } + + public void setExclusiveOwner(Object exclusiveOwner) + { + _exclusiveOwner = exclusiveOwner; + } + + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java index 84b3b09c8e..cff6d4d22a 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java @@ -21,8 +21,8 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.message.AMQMessageHeader; public class MockQueueEntry implements QueueEntry { @@ -59,17 +59,17 @@ public class MockQueueEntry implements QueueEntry return false; } - public void dequeue(StoreContext storeContext) throws FailedDequeueException + public void dequeue() { } - public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException + public void discard() { } - public void dispose(StoreContext storeContext) throws MessageCleanupException + public void dispose() { } @@ -154,7 +154,12 @@ public class MockQueueEntry implements QueueEntry } - + public boolean releaseButRetain() + { + return false; + } + + public boolean removeStateChangeListener(StateChangeListener listener) { @@ -162,7 +167,7 @@ public class MockQueueEntry implements QueueEntry } - public void requeue(StoreContext storeContext) throws AMQException + public void requeue() { @@ -187,6 +192,16 @@ public class MockQueueEntry implements QueueEntry } + public AMQMessageHeader getMessageHeader() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isPersistent() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + public boolean isRedelivered() { return false; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index 852134d9fe..6fa0fdef8a 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -1,6 +1,6 @@ package org.apache.qpid.server.queue; /* - * + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -8,16 +8,16 @@ package org.apache.qpid.server.queue; * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * + * */ @@ -31,21 +31,18 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.ContentHeaderProperties; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; -import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionImpl; -import org.apache.qpid.server.txn.NonTransactionalContext; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.Transaction; public class SimpleAMQQueueTest extends TestCase { @@ -59,7 +56,7 @@ public class SimpleAMQQueueTest extends TestCase protected DirectExchange _exchange = new DirectExchange(); protected MockSubscription _subscription = new MockSubscription(); protected FieldTable _arguments = null; - + MessagePublishInfo info = new MessagePublishInfo() { @@ -88,7 +85,7 @@ public class SimpleAMQQueueTest extends TestCase return null; } }; - + @Override protected void setUp() throws Exception { @@ -119,51 +116,51 @@ public class SimpleAMQQueueTest extends TestCase } catch (IllegalArgumentException e) { - assertTrue("Exception was not about missing name", + assertTrue("Exception was not about missing name", e.getMessage().contains("name")); } - + try { _queue = new SimpleAMQQueue(_qname, false, _owner, false, null); assertNull("Queue was created", _queue); } catch (IllegalArgumentException e) { - assertTrue("Exception was not about missing vhost", + assertTrue("Exception was not about missing vhost", e.getMessage().contains("Host")); } - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, + _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, _virtualHost, _arguments); assertNotNull("Queue was not created", _queue); } - + public void testGetVirtualHost() { assertEquals("Virtual host was wrong", _virtualHost, _queue.getVirtualHost()); } - + public void testBinding() { try { _queue.bind(_exchange, _routingKey, null); - assertTrue("Routing key was not bound", + assertTrue("Routing key was not bound", _exchange.getBindings().containsKey(_routingKey)); - assertEquals("Queue was not bound to key", + assertEquals("Queue was not bound to key", _exchange.getBindings().get(_routingKey).get(0), _queue); - assertEquals("Exchange binding count", 1, + assertEquals("Exchange binding count", 1, _queue.getExchangeBindings().size()); - assertEquals("Wrong exchange bound", _routingKey, + assertEquals("Wrong exchange bound", _routingKey, _queue.getExchangeBindings().get(0).getRoutingKey()); - assertEquals("Wrong exchange bound", _exchange, + assertEquals("Wrong exchange bound", _exchange, _queue.getExchangeBindings().get(0).getExchange()); - + _queue.unBind(_exchange, _routingKey, null); - assertFalse("Routing key was still bound", + assertFalse("Routing key was still bound", _exchange.getBindings().containsKey(_routingKey)); - assertNull("Routing key was not empty", + assertNull("Routing key was not empty", _exchange.getBindings().get(_routingKey)); } catch (AMQException e) @@ -171,36 +168,36 @@ public class SimpleAMQQueueTest extends TestCase assertNull("Unexpected exception", e); } } - + public void testSubscription() throws AMQException { // Check adding a subscription adds it to the queue _queue.registerSubscription(_subscription, false); - assertEquals("Subscription did not get queue", _queue, + assertEquals("Subscription did not get queue", _queue, _subscription.getQueue()); - assertEquals("Queue does not have consumer", 1, + assertEquals("Queue does not have consumer", 1, _queue.getConsumerCount()); - assertEquals("Queue does not have active consumer", 1, + assertEquals("Queue does not have active consumer", 1, _queue.getActiveConsumerCount()); - + // Check sending a message ends up with the subscriber AMQMessage messageA = createMessage(new Long(24)); _queue.enqueue(messageA); assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage()); - + // Check removing the subscription removes it's information from the queue _queue.unregisterSubscription(_subscription); assertTrue("Subscription still had queue", _subscription.isClosed()); assertFalse("Queue still has consumer", 1 == _queue.getConsumerCount()); - assertFalse("Queue still has active consumer", + assertFalse("Queue still has active consumer", 1 == _queue.getActiveConsumerCount()); - + AMQMessage messageB = createMessage(new Long (25)); _queue.enqueue(messageB); - QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry(); - assertNull(entry); + assertNull(_subscription.getQueueContext()); + } - + public void testQueueNoSubscriber() throws AMQException, InterruptedException { AMQMessage messageA = createMessage(new Long(24)); @@ -214,18 +211,18 @@ public class SimpleAMQQueueTest extends TestCase { // Check adding an exclusive subscription adds it to the queue _queue.registerSubscription(_subscription, true); - assertEquals("Subscription did not get queue", _queue, + assertEquals("Subscription did not get queue", _queue, _subscription.getQueue()); - assertEquals("Queue does not have consumer", 1, + assertEquals("Queue does not have consumer", 1, _queue.getConsumerCount()); - assertEquals("Queue does not have active consumer", 1, + assertEquals("Queue does not have active consumer", 1, _queue.getActiveConsumerCount()); // Check sending a message ends up with the subscriber AMQMessage messageA = createMessage(new Long(24)); _queue.enqueue(messageA); assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage()); - + // Check we cannot add a second subscriber to the queue Subscription subB = new MockSubscription(); Exception ex = null; @@ -235,12 +232,12 @@ public class SimpleAMQQueueTest extends TestCase } catch (AMQException e) { - ex = e; + ex = e; } assertNotNull(ex); assertTrue(ex instanceof AMQException); - // Check we cannot add an exclusive subscriber to a queue with an + // Check we cannot add an exclusive subscriber to a queue with an // existing subscription _queue.unregisterSubscription(_subscription); _queue.registerSubscription(_subscription, false); @@ -250,15 +247,15 @@ public class SimpleAMQQueueTest extends TestCase } catch (AMQException e) { - ex = e; + ex = e; } assertNotNull(ex); } - - public void testAutoDeleteQueue() throws Exception + + public void testAutoDeleteQueue() throws Exception { _queue.stop(); - _queue = new SimpleAMQQueue(_qname, false, _owner, true, _virtualHost); + _queue = new SimpleAMQQueue(_qname, false, null, true, _virtualHost); _queue.registerSubscription(_subscription, false); AMQMessage message = createMessage(new Long(25)); _queue.enqueue(message); @@ -266,7 +263,7 @@ public class SimpleAMQQueueTest extends TestCase assertTrue("Queue was not deleted when subscription was removed", _queue.isDeleted()); } - + public void testResend() throws Exception { _queue.registerSubscription(_subscription, false); @@ -276,9 +273,9 @@ public class SimpleAMQQueueTest extends TestCase QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry(); entry.setRedelivered(true); _queue.resend(entry, _subscription); - + } - + public void testGetFirstMessageId() throws Exception { // Create message @@ -335,7 +332,7 @@ public class SimpleAMQQueueTest extends TestCase assertEquals("Message ID was wrong", messageId, msgids.get(i)); } } - + public void testGetMessagesRangeOnTheQueue() throws Exception { for (int i = 1 ; i <= 10; i++) @@ -346,12 +343,12 @@ public class SimpleAMQQueueTest extends TestCase // Put message on queue _queue.enqueue(message); } - + // Get non-existent 0th QueueEntry & check returned list was empty // (the position parameters in this method are indexed from 1) List<QueueEntry> entries = _queue.getMessagesRangeOnTheQueue(0, 0); assertTrue(entries.size() == 0); - + // Check that when 'from' is 0 it is ignored and the range continues from 1 entries = _queue.getMessagesRangeOnTheQueue(0, 2); assertTrue(entries.size() == 2); @@ -363,13 +360,13 @@ public class SimpleAMQQueueTest extends TestCase // Check that when 'from' is greater than 'to' the returned list is empty entries = _queue.getMessagesRangeOnTheQueue(5, 4); assertTrue(entries.size() == 0); - - // Get first QueueEntry & check id + + // Get first QueueEntry & check id entries = _queue.getMessagesRangeOnTheQueue(1, 1); assertTrue(entries.size() == 1); msgID = entries.get(0).getMessage().getMessageNumber(); assertEquals("Message ID was wrong", msgID, 1L); - + // Get 5th,6th,7th entries and check id's entries = _queue.getMessagesRangeOnTheQueue(5, 7); assertTrue(entries.size() == 3); @@ -379,17 +376,17 @@ public class SimpleAMQQueueTest extends TestCase assertEquals("Message ID was wrong", msgID, 6L); msgID = entries.get(2).getMessage().getMessageNumber(); assertEquals("Message ID was wrong", msgID, 7L); - + // Get 10th QueueEntry & check id entries = _queue.getMessagesRangeOnTheQueue(10, 10); assertTrue(entries.size() == 1); msgID = entries.get(0).getMessage().getMessageNumber(); assertEquals("Message ID was wrong", msgID, 10L); - + // Get non-existent 11th QueueEntry & check returned set was empty entries = _queue.getMessagesRangeOnTheQueue(11, 11); assertTrue(entries.size() == 0); - + // Get 9th,10th, and non-existent 11th entries & check result is of size 2 with correct IDs entries = _queue.getMessagesRangeOnTheQueue(9, 11); assertTrue(entries.size() == 2); @@ -398,35 +395,51 @@ public class SimpleAMQQueueTest extends TestCase msgID = entries.get(1).getMessage().getMessageNumber(); assertEquals("Message ID was wrong", msgID, 10L); } - + public void testEnqueueDequeueOfPersistentMessageToNonDurableQueue() throws AMQException { // Create IncomingMessage and nondurable queue - NonTransactionalContext txnContext = new NonTransactionalContext(_store, null, null, null); - IncomingMessage msg = new IncomingMessage(1L, info, txnContext, null); + final IncomingMessage msg = new IncomingMessage(1L, info, null); ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); contentHeaderBody.properties = new BasicContentHeaderProperties(); ((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) 2); msg.setContentHeaderBody(contentHeaderBody); - ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); - + final ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); + // Send persistent message + qs.add(_queue); - msg.enqueue(qs); msg.routingComplete(_store, new MessageHandleFactory()); - _store.storeMessageMetaData(null, new Long(1L), new MessageMetaData(info, contentHeaderBody, 1)); - + _store.storeMessageMetaData(new Long(1L), new MessageMetaData(info, contentHeaderBody, 1)); + + + Transaction txn = new AutoCommitTransaction(_store); + + txn.enqueue(qs, msg, new Transaction.Action() + { + public void postCommit() + { + msg.enqueue(qs); + } + + public void onRollback() + { + } + }); + + + // Check that it is enqueued AMQQueue data = _store.getMessages().get(1L); - assertNotNull(data); - + assertNull(data); + // Dequeue message MockQueueEntry entry = new MockQueueEntry(); - AMQMessage amqmsg = new AMQMessage(1L, _store, new MessageHandleFactory(), txnContext); - + AMQMessage amqmsg = new AMQMessage(1L, _store, new MessageHandleFactory()); + entry.setMessage(amqmsg); - _queue.dequeue(null, entry); - + _queue.dequeue(entry); + // Check that it is dequeued data = _store.getMessages().get(1L); assertNull(data); @@ -434,29 +447,13 @@ public class SimpleAMQQueueTest extends TestCase // FIXME: move this to somewhere useful - private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody) + private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody) { final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, null, false); - try - { - amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(), - publishBody, - new ContentHeaderBody() - { - public int getSize() - { - return 1; - } - }); - } - catch (AMQException e) - { - // won't happen - } - + amqMessageHandle.setPublishAndContentHeaderBody(publishBody, contentHeaderBody); return amqMessageHandle; } @@ -468,11 +465,16 @@ public class SimpleAMQQueueTest extends TestCase TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext) throws AMQException { - super(createMessageHandle(messageId, publishBody), storeContext, publishBody); + this(tag, messageId, publishBody, new ContentHeaderBody(1, 1, new BasicContentHeaderProperties(), 0)); + + } + TestMessage(long tag, long messageId, MessagePublishInfo publishBody, ContentHeaderBody chb) + throws AMQException + { + super(createMessageHandle(messageId, publishBody, chb), chb, 0, publishBody); _tag = tag; } - public boolean incrementReference() { _count++; @@ -489,7 +491,7 @@ public class SimpleAMQQueueTest extends TestCase assertEquals("Wrong count for message with tag " + _tag, expected, _count); } } - + protected AMQMessage createMessage(Long id) throws AMQException { AMQMessage messageA = new TestMessage(id, id, info, new StoreContext()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java index 5802655cfc..18ba9c13ed 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -29,15 +29,9 @@ import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.exchange.TopicExchange; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.queue.MessageHandleFactory; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.queue.AMQPriorityQueue; -import org.apache.qpid.server.queue.SimpleAMQQueue; -import org.apache.qpid.server.queue.ExchangeBinding; -import org.apache.qpid.server.txn.NonTransactionalContext; +import org.apache.qpid.server.queue.*; +import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.framing.AMQShortString; @@ -344,22 +338,21 @@ public class MessageStoreTest extends TestCase MessagePublishInfo messageInfo = new TestMessagePublishInfo(directExchange, false, false, routingKey); - IncomingMessage currentMessage = null; + final IncomingMessage currentMessage; try { currentMessage = new IncomingMessage(_virtualHost.getMessageStore().getNewMessageId(), messageInfo, - new NonTransactionalContext(_virtualHost.getMessageStore(), - new StoreContext(), null, null), new InternalTestProtocolSession(_virtualHost)); } catch (AMQException e) { fail(e.getMessage()); + //help compiler - next line never reached + throw new RuntimeException(); } - currentMessage.setMessageStore(_virtualHost.getMessageStore()); currentMessage.setExchange(directExchange); ContentHeaderBody headerBody = new ContentHeaderBody(); @@ -379,14 +372,9 @@ public class MessageStoreTest extends TestCase currentMessage.setExpiration(); - try - { - currentMessage.route(); - } - catch (AMQException e) - { - fail(e.getMessage()); - } + + currentMessage.route(); + try { @@ -400,14 +388,32 @@ public class MessageStoreTest extends TestCase // check and deliver if header says body length is zero if (currentMessage.allContentReceived()) { - try - { - currentMessage.deliverToQueues(); - } - catch (AMQException e) - { - fail(e.getMessage()); - } + // TODO Deliver to queues + Transaction trans = new AutoCommitTransaction(_virtualHost.getMessageStore()); + final List<AMQQueue> destinationQueues = currentMessage.getDestinationQueues(); + trans.enqueue(currentMessage.getDestinationQueues(), currentMessage, new Transaction.Action() { + public void postCommit() + { + try + { + AMQMessage message = new AMQMessage(currentMessage.getMessageHandle(), currentMessage.getContentHeader(), currentMessage.getSize() ,currentMessage.getMessagePublishInfo()); + + for(AMQQueue queue : destinationQueues) + { + QueueEntry entry = queue.enqueue(message); + } + } + catch (AMQException e) + { + e.printStackTrace(); + } + } + + public void onRollback() + { + //To change body of implemented methods use File | Settings | File Templates. + } + }); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java index fd6789f5ce..eb83f6ae1f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java @@ -55,7 +55,7 @@ public class SkeletonMessageStore implements MessageStore { } - public void removeMessage(StoreContext s, Long messageId) + public void removeMessage(Long messageId) { } @@ -100,6 +100,23 @@ public class SkeletonMessageStore implements MessageStore { } + public StoreFuture commitTranAsync(StoreContext context) throws AMQException + { + commitTran(context); + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + } + public void abortTran(StoreContext storeContext) throws AMQException { } @@ -114,22 +131,26 @@ public class SkeletonMessageStore implements MessageStore return _messageId.getAndIncrement(); } - public void storeContentBodyChunk(StoreContext sc, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException + public void storeContentBodyChunk( + Long messageId, + int index, + ContentChunk contentBody, + boolean lastContentBody) throws AMQException { } - public void storeMessageMetaData(StoreContext sc, Long messageId, MessageMetaData messageMetaData) throws AMQException + public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException { } - public MessageMetaData getMessageMetaData(StoreContext s,Long messageId) throws AMQException + public MessageMetaData getMessageMetaData(Long messageId) throws AMQException { return null; } - public ContentChunk getContentBodyChunk(StoreContext s,Long messageId, int index) throws AMQException + public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException { return null; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java index d88d39002a..f44330d00c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java @@ -29,6 +29,7 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.MessageHandleFactory; import org.apache.qpid.server.queue.AMQMessageHandle; +import org.apache.qpid.server.queue.MessageMetaData; /** * Tests that reference counting works correctly with AMQMessage and the message store @@ -37,14 +38,12 @@ public class TestReferenceCounting extends TestCase { private TestMemoryMessageStore _store; - private StoreContext _storeContext = new StoreContext(); - protected void setUp() throws Exception { super.setUp(); _store = new TestMemoryMessageStore(); - StoreContext.setCurrentContext(_storeContext); + } /** @@ -86,9 +85,13 @@ public class TestReferenceCounting extends TestCase final long messageId = _store.getNewMessageId(); AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true); - messageHandle.setPublishAndContentHeaderBody(_storeContext,info, chb); + + MessageMetaData mmd = messageHandle.setPublishAndContentHeaderBody(info, chb); + _store.storeMessageMetaData(messageId, mmd); + + AMQMessage message = new AMQMessage(messageHandle, - _storeContext,info); + chb, chb.bodySize,info); message = message.takeReference(); @@ -145,9 +148,12 @@ public class TestReferenceCounting extends TestCase final Long messageId = _store.getNewMessageId(); final ContentHeaderBody chb = createPersistentContentHeader(); AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true); - messageHandle.setPublishAndContentHeaderBody(_storeContext,info,chb); + + MessageMetaData mmd = messageHandle.setPublishAndContentHeaderBody(info, chb); + _store.storeMessageMetaData(messageId, mmd); + AMQMessage message = new AMQMessage(messageHandle, - _storeContext, + chb, chb.bodySize, info); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java index 060343d8ae..deb97bc8b0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java @@ -47,6 +47,10 @@ public class MockSubscription implements Subscription private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>(); private final Lock _stateChangeLock = new ReentrantLock(); + private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this); + + private static final AtomicLong idGenerator = new AtomicLong(0); // Create a simple ID that increments for ever new Subscription private final long _subscriptionID = idGenerator.getAndIncrement(); @@ -88,7 +92,12 @@ public class MockSubscription implements Subscription public SubscriptionAcquiredState getOwningState() { - return new QueueEntry.SubscriptionAcquiredState(this); + return _owningState; + } + + public QueueEntry.SubscriptionAssignedState getAssignedState() + { + return _assignedState; } public LogActor getLogActor() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java deleted file mode 100644 index 84d3d313d1..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.txn; - -import junit.framework.TestCase; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TestMemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; - -import java.util.LinkedList; -import java.util.NoSuchElementException; - -public class TxnBufferTest extends TestCase -{ - private final LinkedList<MockOp> ops = new LinkedList<MockOp>(); - - public void testCommit() throws AMQException - { - MockStore store = new MockStore(); - - TxnBuffer buffer = new TxnBuffer(); - buffer.enlist(new MockOp().expectPrepare().expectCommit()); - //check relative ordering - MockOp op = new MockOp().expectPrepare().expectPrepare().expectCommit().expectCommit(); - buffer.enlist(op); - buffer.enlist(op); - buffer.enlist(new MockOp().expectPrepare().expectCommit()); - - buffer.commit(null); - - validateOps(); - store.validate(); - } - - public void testRollback() throws AMQException - { - MockStore store = new MockStore(); - - TxnBuffer buffer = new TxnBuffer(); - buffer.enlist(new MockOp().expectRollback()); - buffer.enlist(new MockOp().expectRollback()); - buffer.enlist(new MockOp().expectRollback()); - - buffer.rollback(null); - - validateOps(); - store.validate(); - } - - public void testCommitWithFailureDuringPrepare() throws AMQException - { - MockStore store = new MockStore(); - store.beginTran(null); - - TxnBuffer buffer = new TxnBuffer(); - buffer.enlist(new StoreMessageOperation(store)); - buffer.enlist(new MockOp().expectPrepare().expectUndoPrepare()); - buffer.enlist(new TxnTester(store)); - buffer.enlist(new MockOp().expectPrepare().expectUndoPrepare()); - buffer.enlist(new FailedPrepare()); - buffer.enlist(new MockOp()); - - try - { - buffer.commit(null); - } - catch (NoSuchElementException e) - { - - } - - validateOps(); - store.validate(); - } - - public void testCommitWithPersistance() throws AMQException - { - MockStore store = new MockStore(); - store.beginTran(null); - store.expectCommit(); - - TxnBuffer buffer = new TxnBuffer(); - buffer.enlist(new MockOp().expectPrepare().expectCommit()); - buffer.enlist(new MockOp().expectPrepare().expectCommit()); - buffer.enlist(new MockOp().expectPrepare().expectCommit()); - buffer.enlist(new StoreMessageOperation(store)); - buffer.enlist(new TxnTester(store)); - - buffer.commit(null); - validateOps(); - store.validate(); - } - - private void validateOps() - { - for (MockOp op : ops) - { - op.validate(); - } - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(TxnBufferTest.class); - } - - class MockOp implements TxnOp - { - final Object PREPARE = "PREPARE"; - final Object COMMIT = "COMMIT"; - final Object UNDO_PREPARE = "UNDO_PREPARE"; - final Object ROLLBACK = "ROLLBACK"; - - private final LinkedList expected = new LinkedList(); - - MockOp() - { - ops.add(this); - } - - public void prepare(StoreContext context) - { - assertEquals(expected.removeLast(), PREPARE); - } - - public void commit(StoreContext context) - { - assertEquals(expected.removeLast(), COMMIT); - } - - public void undoPrepare() - { - assertEquals(expected.removeLast(), UNDO_PREPARE); - } - - public void rollback(StoreContext context) - { - assertEquals(expected.removeLast(), ROLLBACK); - } - - private MockOp expect(Object optype) - { - expected.addFirst(optype); - return this; - } - - MockOp expectPrepare() - { - return expect(PREPARE); - } - - MockOp expectCommit() - { - return expect(COMMIT); - } - - MockOp expectUndoPrepare() - { - return expect(UNDO_PREPARE); - } - - MockOp expectRollback() - { - return expect(ROLLBACK); - } - - void validate() - { - assertEquals("Expected ops were not all invoked", new LinkedList(), expected); - } - - void clear() - { - expected.clear(); - } - } - - class MockStore extends TestMemoryMessageStore - { - final Object BEGIN = "BEGIN"; - final Object ABORT = "ABORT"; - final Object COMMIT = "COMMIT"; - - private final LinkedList expected = new LinkedList(); - private boolean inTran; - - public void beginTran(StoreContext context) throws AMQException - { - inTran = true; - } - - public void commitTran(StoreContext context) throws AMQException - { - assertEquals(expected.removeLast(), COMMIT); - inTran = false; - } - - public void abortTran(StoreContext context) throws AMQException - { - assertEquals(expected.removeLast(), ABORT); - inTran = false; - } - - public boolean inTran(StoreContext context) - { - return inTran; - } - - private MockStore expect(Object optype) - { - expected.addFirst(optype); - return this; - } - - MockStore expectBegin() - { - return expect(BEGIN); - } - - MockStore expectCommit() - { - return expect(COMMIT); - } - - MockStore expectAbort() - { - return expect(ABORT); - } - - void clear() - { - expected.clear(); - } - - void validate() - { - assertEquals("Expected ops were not all invoked", new LinkedList(), expected); - } - } - - class NullOp implements TxnOp - { - public void prepare(StoreContext context) throws AMQException - { - } - public void commit(StoreContext context) - { - } - public void undoPrepare() - { - } - public void rollback(StoreContext context) - { - } - } - - class FailedPrepare extends NullOp - { - public void prepare() throws AMQException - { - throw new AMQException(null, "Fail!", null); - } - } - - class TxnTester extends NullOp - { - private final MessageStore store; - - private final StoreContext context = new StoreContext(); - - TxnTester(MessageStore store) - { - this.store = store; - } - - public void prepare() throws AMQException - { - assertTrue("Expected prepare to be performed under txn", store.inTran(context)); - } - - public void commit() - { - assertTrue("Expected commit not to be performed under txn", !store.inTran(context)); - } - } - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java index f2096df9d1..c9f36d45c3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java @@ -41,12 +41,10 @@ import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.util.MockChannel; -import java.security.Principal; public class InternalBrokerBaseCase extends TestCase { @@ -55,7 +53,6 @@ public class InternalBrokerBaseCase extends TestCase protected MockChannel _channel; protected InternalTestProtocolSession _session; protected VirtualHost _virtualHost; - protected StoreContext _storeContext = new StoreContext(); protected AMQQueue _queue; protected AMQShortString QUEUE_NAME; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/SimpleConnectionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/SimpleConnectionTest.java index 0c432eba6f..bbdf994d2f 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/client/SimpleConnectionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/SimpleConnectionTest.java @@ -28,21 +28,43 @@ import javax.jms.*; public class SimpleConnectionTest extends TestCase { - public void testConnection() +/* public void testConnection() { try { AMQConnection conn = new AMQConnection("127.0.0.1", 5673, "guest", "guest", "test", "/test"); + + QueueSession s = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueSender p = s.createSender(new AMQQueue("amq.direct", "queue")); - p.send(s.createTextMessage("test")); + for(int i = 0; i < 6000; i++) + { + p.send(s.createTextMessage("test("+i+")")); + } QueueReceiver r = s.createReceiver(new AMQQueue("amq.direct", "queue")); conn.start(); - Message m = r.receive(); - - Thread.sleep(60000L); + Thread.sleep(1000L); + for(int i = 0; i < 3000; i++) + { + Message m = r.receive(); + } conn.close(); + + conn = new AMQConnection("127.0.0.1", 5673, "guest", "guest", "test", "/test"); + s = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + r = s.createReceiver(new AMQQueue("amq.direct", "queue")); + conn.start(); + Message m; + int rcvCnt = 0; + while((m = r.receive(1000))!= null) + { + rcvCnt++; + } + System.out.print(rcvCnt); + + Thread.sleep(60000l); + } catch (AMQException e) { @@ -61,4 +83,68 @@ public class SimpleConnectionTest extends TestCase e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } -} + + + public void testConnection2() + { + try + { + AMQConnection conn = new AMQConnection("127.0.0.1", 5673, "guest", "guest", "test", "/test"); + AMQConnection conn2 = new AMQConnection("127.0.0.1", 5673, "guest", "guest", "test", "/test"); + + AMQQueue amqQueue = new AMQQueue("amq.direct", "queue"); + + QueueSession s = conn.createQueueSession(true, Session.SESSION_TRANSACTED); + QueueSender p = s.createSender(amqQueue); + + QueueSession s2 = conn2.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + QueueReceiver r2 = s2.createReceiver(amqQueue); + r2.setMessageListener(new MessageListener() + { + + public void onMessage(Message message) + { + try + { + System.out.println("***************************************************************************"); + System.out.println("***************************************************************************"); + System.out.println("** " +((TextMessage)message).getText()); + System.out.println("***************************************************************************"); + System.out.println("***************************************************************************"); + } + catch (JMSException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + }); + conn2.start(); + + for(int i = 0; i < 6000; i++) + { + p.send(s.createTextMessage("test("+i+")")); + if(i%10 == 0) + { Thread.sleep(5000); + s.commit(); + + } + } + } + catch (JMSException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (URLSyntaxException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (InterruptedException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } +*/} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java index ba05dc6b3e..266cb42ad7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java @@ -215,7 +215,7 @@ public class BindingLoggingTest extends AbstractTestLogging List<String> results = _monitor.findMatches(BND_PREFIX); // We will have two binds as we bind all queues to the default exchange - assertEquals("Result set larger than expected.", 4, results.size()); + assertEquals("Result not as expected." + results, 4, results.size()); String messageID = "BND-1001"; @@ -241,7 +241,7 @@ public class BindingLoggingTest extends AbstractTestLogging String subject = fromSubject(log); - assertTrue("Routing Key does not start with TempQueue:"+AbstractTestLogSubject.getSlice("rk", subject), + assertTrue("Routing Key does not start with TempQueue:"+AbstractTestLogSubject.getSlice("rk", subject), AbstractTestLogSubject.getSlice("rk", subject).startsWith("TempQueue")); assertEquals("Virtualhost not correct.", "/test", AbstractTestLogSubject.getSlice("vh", subject)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java index b5de04b7d8..14dfe448ae 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java @@ -183,6 +183,11 @@ public class SubscriptionTestHelper implements Subscription return null; //To change body of implemented methods use File | Settings | File Templates. } + public QueueEntry.SubscriptionAssignedState getAssignedState() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + public void queueDeleted(AMQQueue queue) { } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java index 7d8c81f4d5..5bce98aeb0 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java @@ -155,10 +155,10 @@ public class SlowMessageStore implements MessageStore doPostDelay("close"); } - public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException + public void removeMessage(Long messageId) throws AMQException { doPreDelay("removeMessage"); - _realStore.removeMessage(storeContext, messageId); + _realStore.removeMessage(messageId); doPostDelay("removeMessage"); } @@ -237,6 +237,24 @@ public class SlowMessageStore implements MessageStore doPostDelay("commitTran"); } + public StoreFuture commitTranAsync(StoreContext context) throws AMQException + { + commitTran(context); + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + + } + public void abortTran(StoreContext context) throws AMQException { doPreDelay("abortTran"); @@ -260,32 +278,36 @@ public class SlowMessageStore implements MessageStore return l; } - public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException + public void storeContentBodyChunk( + Long messageId, + int index, + ContentChunk contentBody, + boolean lastContentBody) throws AMQException { doPreDelay("storeContentBodyChunk"); - _realStore.storeContentBodyChunk(context, messageId, index, contentBody, lastContentBody); + _realStore.storeContentBodyChunk(messageId, index, contentBody, lastContentBody); doPostDelay("storeContentBodyChunk"); } - public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException + public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException { doPreDelay("storeMessageMetaData"); - _realStore.storeMessageMetaData(context, messageId, messageMetaData); + _realStore.storeMessageMetaData(messageId, messageMetaData); doPostDelay("storeMessageMetaData"); } - public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException + public MessageMetaData getMessageMetaData(Long messageId) throws AMQException { doPreDelay("getMessageMetaData"); - MessageMetaData mmd = _realStore.getMessageMetaData(context, messageId); + MessageMetaData mmd = _realStore.getMessageMetaData(messageId); doPostDelay("getMessageMetaData"); return mmd; } - public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException + public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException { doPreDelay("getContentBodyChunk"); - ContentChunk c = _realStore.getContentBodyChunk(context, messageId, index); + ContentChunk c = _realStore.getContentBodyChunk(messageId, index); doPostDelay("getContentBodyChunk"); return c; } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java index f8ba7060a9..742e2ac518 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java @@ -311,11 +311,13 @@ public class TopicSessionTest extends QpidTestCase AMQTopic topic = new AMQTopic(con, "testNoLocal"); - TopicSession session1 = con.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE); + TopicSession session1 = con.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE); TopicSubscriber noLocal = session1.createSubscriber(topic, "", true); + TopicSubscriber select = session1.createSubscriber(topic, "Selector = 'select'", false); TopicSubscriber normal = session1.createSubscriber(topic); + TopicPublisher publisher = session1.createPublisher(topic); con.start(); @@ -329,12 +331,12 @@ public class TopicSessionTest extends QpidTestCase m = (TextMessage) normal.receive(1000); assertNotNull(m); session1.commit(); - + //test selector subscriber doesn't message m = (TextMessage) select.receive(1000); assertNull(m); session1.commit(); - + //test nolocal subscriber doesn't message m = (TextMessage) noLocal.receive(1000); if (m != null) @@ -349,12 +351,12 @@ public class TopicSessionTest extends QpidTestCase publisher.publish(message); session1.commit(); - + //test normal subscriber gets message m = (TextMessage) normal.receive(1000); assertNotNull(m); session1.commit(); - + //test selector subscriber does get message m = (TextMessage) select.receive(1000); assertNotNull(m); @@ -365,7 +367,7 @@ public class TopicSessionTest extends QpidTestCase assertNull(m); AMQConnection con2 = (AMQConnection) getConnection("guest", "guest", "foo"); - TopicSession session2 = con2.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE); + TopicSession session2 = con2.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE); TopicPublisher publisher2 = session2.createPublisher(topic); @@ -386,18 +388,18 @@ public class TopicSessionTest extends QpidTestCase session1.commit(); //test nolocal subscriber does message - m = (TextMessage) noLocal.receive(100); + m = (TextMessage) noLocal.receive(1000); assertNotNull(m); con.close(); con2.close(); } - + /** * This tests QPID-1191, where messages which are sent to a topic but are not consumed by a subscriber * due to a selector can be leaked. - * @throws Exception + * @throws Exception */ public void testNonMatchingMessagesDoNotFillQueue() throws Exception { @@ -420,27 +422,27 @@ public class TopicSessionTest extends QpidTestCase message = session.createTextMessage("non-matching 1"); publisher.publish(message); session.commit(); - + // Send and consume matching message message = session.createTextMessage("hello"); message.setStringProperty("Selector", "select"); publisher.publish(message); session.commit(); - + m = (TextMessage) selector.receive(1000); assertNotNull("should have received message", m); assertEquals("Message contents were wrong", "hello", m.getText()); - + // Send non-matching message message = session.createTextMessage("non-matching 2"); publisher.publish(message); session.commit(); - + // Assert queue count is 0 long depth = ((AMQTopicSessionAdaptor) session).getSession().getQueueDepth(topic); assertEquals("Queue depth was wrong", 0, depth); - + } public static junit.framework.Test suite() |