diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2009-10-20 16:23:01 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2009-10-20 16:23:01 +0000 |
commit | 2aff2a16161c1912aa355dd88696ebf5f48317f4 (patch) | |
tree | a77bf4adb86c4c50eefc5e543e0ceadaa2ed08c2 | |
parent | f772c4f42999d902722584623910184c8f439a1b (diff) | |
download | qpid-python-2aff2a16161c1912aa355dd88696ebf5f48317f4.tar.gz |
Implemented persistence, changed transactions, implemented message conversion, fixed for all Java tests
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-0-10@827724 13f79535-47bb-0310-9956-ffa450edef68
188 files changed, 5319 insertions, 4767 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 47d0749818..637997a947 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 @@ -38,21 +38,25 @@ import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.junit.extensions.util.SizeOf; import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.log4j.Logger; /** - * + * * This is a special diagnostic exchange type which doesn't actually do anything * with messages. When it receives a message, it writes information about the * current memory usage to the "memory" property of the message and places it on the - * diagnosticqueue for retrieval - * + * diagnosticqueue for retrieval + * * @author Aidan Skinner - * + * */ public class DiagnosticExchange extends AbstractExchange { - + + private static final Logger _logger = Logger.getLogger(DiagnosticExchange.class); + + public static final AMQShortString DIAGNOSTIC_EXCHANGE_CLASS = new AMQShortString("x-diagnostic"); public static final AMQShortString DIAGNOSTIC_EXCHANGE_NAME = new AMQShortString("diagnostic"); @@ -70,7 +74,7 @@ public class DiagnosticExchange extends AbstractExchange /** * Usual constructor. - * + * * @throws JMException */ @MBeanConstructor("Creates an MBean for AMQ Diagnostic exchange") @@ -83,7 +87,7 @@ public class DiagnosticExchange extends AbstractExchange /** * Returns nothing, there can be no tabular data for this... - * + * * @throws OpenDataException * @returns null * @todo ... or can there? Could this actually return all the @@ -97,7 +101,7 @@ public class DiagnosticExchange extends AbstractExchange /** * This exchange type doesn't support queues, so this method does * nothing. - * + * * @param queueName * the queue you'll fail to create * @param binding @@ -114,22 +118,20 @@ public class DiagnosticExchange extends AbstractExchange /** * Creates a new MBean instance - * + * * @return the newly created MBean * @throws AMQException * if something goes wrong */ - protected ExchangeMBean createMBean() throws AMQException + protected ExchangeMBean createMBean() throws JMException { - try - { - return new DiagnosticExchange.DiagnosticExchangeMBean(); - } - catch (JMException ex) - { - // _logger.error("Exception occured in creating the direct exchange mbean", ex); - throw new AMQException(null, "Exception occured in creating the direct exchange mbean", ex); - } + return new DiagnosticExchange.DiagnosticExchangeMBean(); + + } + + public Logger getLogger() + { + return _logger; } public AMQShortString getType() @@ -139,7 +141,7 @@ public class DiagnosticExchange extends AbstractExchange /** * Does nothing. - * + * * @param routingKey * pointless * @param queue @@ -162,7 +164,7 @@ public class DiagnosticExchange extends AbstractExchange /** * Does nothing. - * + * * @param routingKey * pointless * @param queue @@ -199,7 +201,7 @@ public class DiagnosticExchange extends AbstractExchange public ArrayList<AMQQueue> route(InboundMessage payload) { - + Long value = new Long(SizeOf.getUsedMemory()); AMQShortString key = new AMQShortString("memory"); @@ -212,10 +214,10 @@ public class DiagnosticExchange extends AbstractExchange ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>(); queues.add(q); return queues; - + } - + public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) { // TODO Auto-generated method stub diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java index d96b4dc99e..b4d0d1aa0d 100644 --- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java +++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java @@ -31,7 +31,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; */ public final class DiagnosticExchangeType implements ExchangeType<DiagnosticExchange> { - + public AMQShortString getName() { return DiagnosticExchange.DIAGNOSTIC_EXCHANGE_CLASS; 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 b228e7270c..cb46b9c815 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 @@ -1,6 +1,6 @@ package org.apache.qpid.extras.exchanges.example; /* - * + * * 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.extras.exchanges.example; * 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. - * + * */ @@ -29,6 +29,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeReferrer; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.message.InboundMessage; @@ -76,12 +77,27 @@ public class TestExchange implements Exchange public Exchange getAlternateExchange() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void setAlternateExchange(Exchange exchange) { - //To change body of implemented methods use File | Settings | File Templates. + + } + + public void removeReference(ExchangeReferrer exchange) + { + + } + + public void addReference(ExchangeReferrer exchange) + { + + } + + public boolean hasReferrers() + { + return false; } public void initialise(VirtualHost host, AMQShortString name, boolean durable, boolean autoDelete) diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java index 22833693ca..db02ca13ea 100644 --- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java +++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java @@ -40,7 +40,7 @@ public class TestExchangeType implements ExchangeType return null; } - public Exchange newInstance(VirtualHost host, AMQShortString name, boolean durable, + public Exchange newInstance(VirtualHost host, AMQShortString name, boolean durable, int token, boolean autoDelete) throws AMQException { 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 c2e6a82372..08b3c08215 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 @@ -65,6 +65,7 @@ import org.apache.qpid.server.queue.AMQQueueMBean; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; @@ -80,10 +81,10 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr private final ExchangeFactory _exchangeFactory; private final DurableConfigurationStore _durableConfig; - private final VirtualHost.VirtualHostMBean _virtualHostMBean; + private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean; @MBeanConstructor("Creates the Broker Manager MBean") - public AMQBrokerManagerMBean(VirtualHost.VirtualHostMBean virtualHostMBean) throws JMException + public AMQBrokerManagerMBean(VirtualHostImpl.VirtualHostMBean virtualHostMBean) throws JMException { super(ManagedBroker.class, ManagedBroker.TYPE, ManagedBroker.VERSION); @@ -113,10 +114,10 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr { exchangeTypes.add(ex.getName().toString()); } - + return exchangeTypes.toArray(new String[0]); } - + /** * Returns a list containing the names of the attributes available for the Queue mbeans. * @since Qpid JMX API 1.3 @@ -129,12 +130,12 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr { attributeList.add(attr); } - + Collections.sort(attributeList); return attributeList; } - + /** * Returns a List of Object Lists containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost. * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-". @@ -147,22 +148,22 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr { return new ArrayList<List<Object>>(); } - + List<List<Object>> queueAttributesList = new ArrayList<List<Object>>(_queueRegistry.getQueues().size()); - + int attributesLength = attributes.length; - + for(AMQQueue queue : _queueRegistry.getQueues()) { AMQQueueMBean mbean = (AMQQueueMBean) queue.getManagedObject(); - + if(mbean == null) { continue; } - + List<Object> attributeValues = new ArrayList<Object>(attributesLength); - + for(int i=0; i < attributesLength; i++) { try @@ -174,13 +175,13 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr attributeValues.add(new String("-")); } } - + queueAttributesList.add(attributeValues); } - + return queueAttributesList; } - + /** * Creates new exchange and registers it with the registry. * @@ -330,7 +331,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr } finally { - CurrentActor.remove(); + CurrentActor.remove(); } } 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 6d27c1c07c..52059836b7 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 @@ -43,8 +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.StoredMessage; import org.apache.qpid.server.txn.*; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; @@ -99,12 +102,7 @@ public class AMQChannel private final AtomicBoolean _suspended = new AtomicBoolean(false); - private Transaction _transaction; - - - private final List<RequiredDeliveryException> _returnMessages = new LinkedList<RequiredDeliveryException>(); - - private MessageHandleFactory _messageHandleFactory = new MessageHandleFactory(); + private ServerTransaction _transaction; // Why do we need this reference ? - ritchiem private final AMQProtocolSession _session; @@ -161,7 +159,7 @@ public class AMQChannel public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQException { - _currentMessage = new IncomingMessage(_messageStore.getNewMessageId(), info, _session); + _currentMessage = new IncomingMessage(info); _currentMessage.setExchange(e); } @@ -183,17 +181,15 @@ public class AMQChannel _currentMessage.setExpiration(); - routeCurrentMessage(); - MessageMetaData mmd = _currentMessage.routingComplete(_messageStore, _messageHandleFactory); + MessageMetaData mmd = _currentMessage.headersReceived(); + final StoredMessage<MessageMetaData> handle = _messageStore.addMessage(mmd); + _currentMessage.setStoredMessage(handle); - if(_currentMessage.isPersistent()) - { - final Long messageNumber = _currentMessage.getMessageNumber(); + routeCurrentMessage(); - _messageStore.storeMessageMetaData(messageNumber, mmd); - _transaction.addPostCommitAction(new Transaction.Action() + _transaction.addPostCommitAction(new ServerTransaction.Action() { public void postCommit() @@ -202,17 +198,9 @@ public class AMQChannel public void onRollback() { - try - { - _messageStore.removeMessage(messageNumber); - } - catch (AMQException e) - { - - } + handle.remove(); } }); - } deliverCurrentMessageIfComplete(); @@ -283,16 +271,7 @@ public class AMQChannel 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()); - - - } + _currentMessage.addContentBodyFrame(contentChunk); deliverCurrentMessageIfComplete(); } @@ -320,6 +299,12 @@ public class AMQChannel return ++_consumerTag; } + + public Subscription getSubscription(AMQShortString subscription) + { + return _tag2SubscriptionMap.get(subscription); + } + /** * Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean * up all subscriptions, even if the client does not explicitly unsubscribe from all queues. @@ -333,11 +318,10 @@ public class AMQChannel * @param exclusive Flag requesting exclusive access to the queue * @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests * - * @throws ConsumerTagNotUniqueException if the tag is not unique * @throws AMQException if something goes wrong */ public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks, - FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException, ConsumerTagNotUniqueException + FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException { if (tag == null) { @@ -346,7 +330,7 @@ public class AMQChannel if (_tag2SubscriptionMap.containsKey(tag)) { - throw new ConsumerTagNotUniqueException(); + throw new AMQException("Consumer already exists with same tag: " + tag); } Subscription subscription = @@ -532,7 +516,7 @@ public class AMQChannel if (!unacked.isQueueDeleted()) { // Mark message redelivered - unacked.setRedelivered(true); + unacked.setRedelivered(); // Ensure message is released for redelivery unacked.release(); @@ -560,7 +544,7 @@ public class AMQChannel if (unacked != null) { // Mark message redelivered - unacked.setRedelivered(true); + unacked.setRedelivered(); // Ensure message is released for redelivery if (!unacked.isQueueDeleted()) @@ -655,7 +639,7 @@ public class AMQChannel // Without any details from the client about what has been processed we have to mark // all messages in the unacked map as redelivered. - message.setRedelivered(true); + message.setRedelivered(); Subscription sub = message.getDeliveredSubscription(); @@ -696,7 +680,7 @@ public class AMQChannel long deliveryTag = entry.getKey(); _unacknowledgedMessageMap.remove(deliveryTag); - message.setRedelivered(true); + message.setRedelivered(); message.release(); } @@ -931,16 +915,8 @@ public class AMQChannel public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) throws AMQException { - ServerMessage msg = entry.getMessage(); - if(msg instanceof AMQMessage) - { - getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(), - deliveryTag, sub.getConsumerTag()); - } - else - { - //TODO - Convert 0-10 Message into 0-8/9 message - } + getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(), + deliveryTag, sub.getConsumerTag()); } }; @@ -969,15 +945,7 @@ public class AMQChannel 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); + AMQMessage message = new AMQMessage(incomingMessage.getStoredMessage()); message.setExpiration(incomingMessage.getExpiration()); message.setClientIdentifier(_session); @@ -985,7 +953,6 @@ public class AMQChannel } private boolean checkMessageUserId(ContentHeaderBody header) - throws UnauthorizedAccessException { AMQShortString userID = header.properties instanceof BasicContentHeaderProperties @@ -996,7 +963,7 @@ public class AMQChannel } - private class MessageDeliveryAction implements Transaction.Action + private class MessageDeliveryAction implements ServerTransaction.Action { private IncomingMessage _incommingMessage; private ArrayList<AMQQueue> _destinationQueues; @@ -1014,7 +981,7 @@ public class AMQChannel { final boolean immediate = _incommingMessage.isImmediate(); - Transaction txn = null; + ServerTransaction txn = null; for(AMQQueue queue : _destinationQueues) { @@ -1036,7 +1003,7 @@ public class AMQChannel AMQMessage message = (AMQMessage) entry.getMessage(); _session.getProtocolOutputConverter().writeReturn(message.getMessagePublishInfo(), message.getContentHeaderBody(), - message.getBodyFrameIterator(_session,_channelId), + message, _channelId, AMQConstant.NO_CONSUMERS.getCode(), new AMQShortString("Immediate delivery is not possible.")); @@ -1069,7 +1036,7 @@ public class AMQChannel } } - private class MessageAcknowledgeAction implements Transaction.Action + private class MessageAcknowledgeAction implements ServerTransaction.Action { private final Collection<QueueEntry> _ackedMessages; @@ -1120,7 +1087,7 @@ public class AMQChannel } } - private class WriteReturnAction implements Transaction.Action + private class WriteReturnAction implements ServerTransaction.Action { private final AMQConstant _errorCode; private final IncomingMessage _message; @@ -1141,7 +1108,7 @@ public class AMQChannel { _session.getProtocolOutputConverter().writeReturn(_message.getMessagePublishInfo(), _message.getContentHeader(), - new BodyFrameIterator(_session,_channelId,_message), + _message, _channelId, _errorCode.getCode(), new AMQShortString(_description)); 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 a0b907c518..9da02e0600 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 @@ -24,7 +24,7 @@ import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.store.TransactionLog; -import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.AMQException; import org.apache.log4j.Logger; @@ -56,8 +56,8 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException { - - message.setRedelivered(true); + + message.setRedelivered(); final Subscription subscription = message.getDeliveredSubscription(); if (subscription != null) { @@ -103,14 +103,14 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor private void dequeueEntry(final QueueEntry node) { - Transaction txn = new AutoCommitTransaction(_transactionLog); + ServerTransaction txn = new AutoCommitTransaction(_transactionLog); dequeueEntry(node, txn); } - private void dequeueEntry(final QueueEntry node, Transaction txn) + private void dequeueEntry(final QueueEntry node, ServerTransaction txn) { txn.dequeue(node.getQueue(), node.getMessage(), - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() 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 de095a3bc2..326352b644 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 @@ -318,6 +318,9 @@ public class Main } } + //TODO - HACK + port += 10; + String bindAddr = commandLine.getOptionValue("b"); if (bindAddr == null) { @@ -363,17 +366,19 @@ public class Main _brokerLogger.info("Qpid Broker Ready :" + QpidProperties.getReleaseVersion() + " build: " + QpidProperties.getBuildVersion()); - CurrentActor.get().message(BrokerMessages.BRK_1004()); - int port_0_10 = port + 1; + int port_0_10 = port - 10; IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); final ConnectionDelegate delegate = new org.apache.qpid.server.transport.ServerConnectionDelegate(appRegistry, bindAddress.getCanonicalHostName()); + + + /* NetworkDriver driver = new MINANetworkDriver(); - driver.bind(port, new InetAddress[]{bindAddress}, new ProtocolEngineFactory_0_10(delegate), + driver.bind(port_0_10, new InetAddress[]{bindAddress}, new ProtocolEngineFactory_0_10(delegate), serverConfig.getNetworkConfiguration(), null); ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port), new QpidAcceptor(driver,"TCP")); @@ -381,6 +386,9 @@ public class Main */ + + + // TODO - Fix to use a proper binding @@ -401,6 +409,9 @@ public class Main org.apache.qpid.transport.network.io.IoAcceptor ioa = new org.apache.qpid.transport.network.io.IoAcceptor ("0.0.0.0", port_0_10, cb); ioa.start(); + + CurrentActor.get().message(BrokerMessages.BRK_1004()); + } finally { @@ -532,13 +543,6 @@ public class Main { LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime); - try - { - blm.register(); - } - catch (AMQException e) - { - throw new InitException("Unable to initialise the Logging Management MBean: ", e); - } + blm.register(); } } 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 deleted file mode 100644 index eeb04c9077..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java +++ /dev/null @@ -1,87 +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; - -import org.apache.qpid.AMQException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.message.AMQMessageReference; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.ServerMessage; - -/** - * Signals that a required delivery could not be made. This could be bacuse of the immediate flag being set and the - * queue having no consumers, or the mandatory flag being set and the exchange having no valid bindings. - * - * <p/>The failed message is associated with this error condition, by taking a reference to it. This enables the - * correct compensating action to be taken against the message, for example, bouncing it back to the sender. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Represent failure to deliver a message that must be delivered. - * <tr><td> Associate the failed message with the error condition. <td> {@link AMQMessage} - * </table> - */ -public abstract class RequiredDeliveryException extends AMQException -{ - private MessageReference _amqMessage; - - public RequiredDeliveryException(String message, ServerMessage payload) - { - super(message); - - setMessage(payload); - } - - - public RequiredDeliveryException(String message) - { - super(message); - } - - public void setMessage(final ServerMessage payload) - { - - // Increment the reference as this message is in the routing phase - // and so will have the ref decremented as routing fails. - // we need to keep this message around so we can return it in the - // handler. So increment here. - _amqMessage = payload.newReference(); - - } - - public ServerMessage getAMQMessage() - { - return _amqMessage.getMessage(); - } - - public AMQConstant getErrorCode() - { - return getReplyCode(); - } - - public abstract AMQConstant getReplyCode(); - - public void release() - { - //_amqMessage.release(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index 641b44bb18..566f5a2de1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -14,8 +14,8 @@ * "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. - * + * under the License. + * */ package org.apache.qpid.server.configuration; @@ -124,7 +124,7 @@ public class ServerConfiguration implements SignalHandler } catch (IllegalArgumentException e) { - // We're on something that doesn't handle SIGHUP, how sad, Windows. + // We're on something that doesn't handle SIGHUP, how sad, Windows. } } @@ -221,7 +221,7 @@ public class ServerConfiguration implements SignalHandler String localeString = getConfig().getString(ADVANCED_LOCALE); // Expecting locale of format langauge_country_variant - // If the configuration does not have a defined locale use the JVM default + // If the configuration does not have a defined locale use the JVM default if (localeString == null) { return Locale.getDefault(); @@ -625,48 +625,48 @@ public class ServerConfiguration implements SignalHandler { return new NetworkDriverConfiguration() { - + public Integer getTrafficClass() { return null; } - + public Boolean getTcpNoDelay() { // Can't call parent getTcpNoDelay since it just calls this one return getConfig().getBoolean("connector.tcpNoDelay", true); } - + public Integer getSoTimeout() { return null; } - + public Integer getSoLinger() { return null; } - + public Integer getSendBufferSize() { return getBufferWriteLimit(); } - + public Boolean getReuseAddress() { return null; } - + public Integer getReceiveBufferSize() { return getBufferReadLimit(); } - + public Boolean getOOBInline() { return null; } - + public Boolean getKeepAlive() { return null; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index cacd294464..7983c62443 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.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 @@ -23,6 +23,7 @@ package org.apache.qpid.server.exchange; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; +import javax.management.JMException; import javax.management.openmbean.OpenType; import javax.management.openmbean.CompositeType; import javax.management.openmbean.TabularType; @@ -46,7 +47,7 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.logging.subjects.ExchangeLogSubject; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.ExchangeReferrer; +import org.apache.log4j.Logger; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -86,14 +87,14 @@ public abstract class AbstractExchange implements Exchange, Managable protected CompositeType _bindingDataType; protected TabularType _bindinglistDataType; protected TabularDataSupport _bindingList; - + public ExchangeMBean() throws NotCompliantMBeanException { super(ManagedExchange.class, ManagedExchange.TYPE, ManagedExchange.VERSION); } protected void init() throws OpenDataException - { + { _bindingItemTypes = new OpenType[2]; _bindingItemTypes[0] = SimpleType.STRING; _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING); @@ -162,23 +163,33 @@ public abstract class AbstractExchange implements Exchange, Managable * called during initialisation (template method pattern). * @return the MBean */ - protected abstract ExchangeMBean createMBean() throws AMQException; + protected abstract ExchangeMBean createMBean() throws JMException; - public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException + public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) + throws AMQException { _virtualHost = host; _name = name; _durable = durable; _autoDelete = autoDelete; _ticket = ticket; - _exchangeMbean = createMBean(); - _exchangeMbean.register(); + try + { + _exchangeMbean = createMBean(); + _exchangeMbean.register(); + } + catch (JMException e) + { + getLogger().error(e); + } _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); // Log Exchange creation CurrentActor.get().message(ExchangeMessages.EXH_1001(String.valueOf(getType()), String.valueOf(name), durable)); } + public abstract Logger getLogger(); + public boolean isDurable() { return _durable; @@ -206,7 +217,7 @@ public abstract class AbstractExchange implements Exchange, Managable } CurrentActor.get().message(_logSubject, ExchangeMessages.EXH_1002()); - } + } public String toString() { 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 55ff948471..2a8a87be7d 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 @@ -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 @@ -23,7 +23,7 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.protocol.ExchangeInitialiser; +import org.apache.qpid.server.exchange.ExchangeInitialiser; import org.apache.qpid.server.queue.IncomingMessage; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -40,6 +40,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry * Maps from exchange name to exchange instance */ private ConcurrentMap<AMQShortString, Exchange> _exchangeMap = new ConcurrentHashMap<AMQShortString, Exchange>(); + private ConcurrentMap<String, Exchange> _exchangeMapStr = new ConcurrentHashMap<String, Exchange>(); private Exchange _defaultExchange; private VirtualHost _host; @@ -56,10 +57,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry new ExchangeInitialiser().initialise(_host.getExchangeFactory(), this); } - public Exchange getExchange(String exchangeName) - { - return getExchange(new AMQShortString(exchangeName)); - } + public DurableConfigurationStore getDurableConfigurationStore() { @@ -69,6 +67,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry public void registerExchange(Exchange exchange) throws AMQException { _exchangeMap.put(exchange.getName(), exchange); + _exchangeMapStr.put(exchange.getName().toString(), exchange); if (exchange.isDurable()) { getDurableConfigurationStore().createExchange(exchange); @@ -94,6 +93,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry { // TODO: check inUse argument Exchange e = _exchangeMap.remove(name); + _exchangeMapStr.remove(name.toString()); if (e != null) { if (e.isDurable()) @@ -126,6 +126,19 @@ public class DefaultExchangeRegistry implements ExchangeRegistry } + public Exchange getExchange(String name) + { + if ((name == null) || name.length() == 0) + { + return getDefaultExchange(); + } + else + { + return _exchangeMapStr.get(name); + } + } + + /** * Routes content through exchanges, delivering it to 1 or more queues. * @param payload 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 2832c7f2bd..4788f96d6c 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 @@ -149,17 +149,14 @@ public class DirectExchange extends AbstractExchange }// End of MBean class - protected ExchangeMBean createMBean() throws AMQException + protected ExchangeMBean createMBean() throws JMException { - try - { - return new DirectExchangeMBean(); - } - catch (JMException ex) - { - _logger.error("Exception occured in creating the direct exchange mbean", ex); - throw new AMQException("Exception occured in creating the direct exchange mbean", ex); - } + return new DirectExchangeMBean(); + } + + public Logger getLogger() + { + return _logger; } public AMQShortString getType() @@ -212,7 +209,8 @@ public class DirectExchange extends AbstractExchange public ArrayList<AMQQueue> route(InboundMessage payload) { - final AMQShortString routingKey = payload.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : new AMQShortString(payload.getRoutingKey()); + final String routingKey = payload.getRoutingKey(); + final ArrayList<AMQQueue> queues = (routingKey == null) ? null : _index.get(routingKey); 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 2bcf5e3053..4bbdeaef1c 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 @@ -27,10 +27,9 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.ExchangeReferrer; +import javax.management.JMException; import java.util.ArrayList; -import java.util.Map; public interface Exchange extends ExchangeReferrer { @@ -38,7 +37,8 @@ public interface Exchange extends ExchangeReferrer AMQShortString getType(); - void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException; + void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) + throws AMQException, JMException; boolean isDurable(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ExchangeInitialiser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java index 2abcecb6de..59fe94ddc0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ExchangeInitialiser.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.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 @@ -18,15 +18,11 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; public class ExchangeInitialiser { @@ -35,7 +31,7 @@ public class ExchangeInitialiser { define (registry, factory, type.getDefaultExchangeName(), type.getName()); } - + define(registry, factory, ExchangeDefaults.DEFAULT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); registry.setDefaultExchange(registry.getExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME)); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExchangeReferrer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeReferrer.java index 314f2761a8..e41d63d97d 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExchangeReferrer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeReferrer.java @@ -19,7 +19,7 @@ * */ -package org.apache.qpid.server; +package org.apache.qpid.server.exchange; public interface ExchangeReferrer { 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 62172bbfb2..00f8ebd856 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 @@ -62,7 +62,7 @@ public class FanoutExchange extends AbstractExchange private final class FanoutExchangeMBean extends ExchangeMBean { private static final String BINDING_KEY_SUBSTITUTE = "*"; - + @MBeanConstructor("Creates an MBean for AMQ fanout exchange") public FanoutExchangeMBean() throws JMException { @@ -75,7 +75,7 @@ public class FanoutExchange extends AbstractExchange { _bindingList = new TabularDataSupport(_bindinglistDataType); - + if(_queues.isEmpty()) { return _bindingList; @@ -88,7 +88,7 @@ public class FanoutExchange extends AbstractExchange String queueName = queue.getName().toString(); queueNames.add(queueName); } - + Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])}; CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); _bindingList.put(bindingData); @@ -121,17 +121,14 @@ public class FanoutExchange extends AbstractExchange } // End of MBean class - protected ExchangeMBean createMBean() throws AMQException + protected ExchangeMBean createMBean() throws JMException { - try - { - return new FanoutExchange.FanoutExchangeMBean(); - } - catch (JMException ex) - { - _logger.error("Exception occured in creating the direct exchange mbean", ex); - throw new AMQException("Exception occured in creating the direct exchange mbean", ex); - } + return new FanoutExchange.FanoutExchangeMBean(); + } + + public Logger getLogger() + { + return _logger; } public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>() @@ -202,7 +199,7 @@ public class FanoutExchange extends AbstractExchange public ArrayList<AMQQueue> route(InboundMessage payload) { - + if (_logger.isDebugEnabled()) { _logger.debug("Publishing message to queue " + _queues); 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 fb43f97530..5677cc4510 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 @@ -83,6 +83,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public class HeadersExchange extends AbstractExchange { + private static final Logger _logger = Logger.getLogger(HeadersExchange.class); public static final ExchangeType<HeadersExchange> TYPE = new ExchangeType<HeadersExchange>() @@ -102,6 +103,7 @@ public class HeadersExchange extends AbstractExchange boolean autoDelete) throws AMQException { HeadersExchange exch = new HeadersExchange(); + exch.initialise(host, name, durable, ticket, autoDelete); return exch; } @@ -210,7 +212,7 @@ public class HeadersExchange extends AbstractExchange { throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" "); } - + if(keyAndValue.length ==1) { //no value was given, only a key. Use an empty value @@ -249,7 +251,7 @@ public class HeadersExchange extends AbstractExchange if(!_bindings.remove(new Registration(args == null ? null : new HeadersBinding(args), queue, routingKey))) { throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() - + " with headers args " + args); + + " with headers args " + args); } } @@ -320,17 +322,9 @@ public class HeadersExchange extends AbstractExchange return ((BasicContentHeaderProperties) contentHeaderFrame.properties).getHeaders(); } - protected ExchangeMBean createMBean() throws AMQException + protected ExchangeMBean createMBean() throws JMException { - try - { - return new HeadersExchangeMBean(); - } - catch (JMException ex) - { - _logger.error("Exception occured in creating the HeadersExchangeMBean", ex); - throw new AMQException("Exception occured in creating the HeadersExchangeMBean", ex); - } + return new HeadersExchangeMBean(); } public Map<AMQShortString, List<AMQQueue>> getBindings() @@ -338,6 +332,12 @@ public class HeadersExchange extends AbstractExchange return null; } + public Logger getLogger() + { + return _logger; + } + + private static class Registration { private final HeadersBinding binding; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java index ec83161029..90d04c814a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java @@ -39,6 +39,9 @@ class Index { private ConcurrentMap<AMQShortString, ArrayList<AMQQueue>> _index = new ConcurrentHashMap<AMQShortString, ArrayList<AMQQueue>>(); + private ConcurrentMap<String, ArrayList<AMQQueue>> _stringIndex + = new ConcurrentHashMap<String, ArrayList<AMQQueue>>(); + synchronized boolean add(AMQShortString key, AMQQueue queue) { @@ -51,8 +54,10 @@ class Index { queues = new ArrayList<AMQQueue>(queues); } + //next call is atomic, so there is no race to create the list _index.put(key, queues); + _stringIndex.put(key.toString(), queues); if(queues.contains(queue)) { @@ -64,6 +69,8 @@ class Index } } + + synchronized boolean remove(AMQShortString key, AMQQueue queue) { ArrayList<AMQQueue> queues = _index.get(key); @@ -76,10 +83,12 @@ class Index if (queues.size() == 0) { _index.remove(key); + _stringIndex.remove(key.toString()); } else { _index.put(key, queues); + _stringIndex.put(key.toString(), queues); } } return removed; @@ -92,6 +101,12 @@ class Index return _index.get(key); } + ArrayList<AMQQueue> get(String key) + { + return _stringIndex.get(key); + } + + Map<AMQShortString, List<AMQQueue>> getBindingsMap() { return new HashMap<AMQShortString, List<AMQQueue>>(_index); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java index db9beb6da7..025a8014aa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.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 @@ -21,7 +21,6 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.IncomingMessage; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java deleted file mode 100644 index d18ad7ab14..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java +++ /dev/null @@ -1,49 +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.exchange; - -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.queue.IncomingMessage; - -/** - * NoRouteException is a {@link RequiredDeliveryException} that represents the failure case where a manadatory message - * cannot be delivered because there is no route for the message. The AMQP status code, 312, is always used to report - * this condition. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Represent failure to deliver a message that must be delivered. - * </table> - */ -public class NoRouteException extends RequiredDeliveryException -{ - public NoRouteException(String msg, AMQMessage amqMessage) - { - super(msg, amqMessage); - } - - public AMQConstant getReplyCode() - { - return AMQConstant.NO_ROUTE; - } -} 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 bffdbe4a80..d5ca5a8a81 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 @@ -228,7 +228,7 @@ public class TopicExchange extends AbstractExchange _filteredQueues.remove(queue); } } - else + else { filters.put(filter, instances - 1); } @@ -443,10 +443,10 @@ public class TopicExchange extends AbstractExchange { result.addUnfilteredQueue(queue); } - _parser.addBinding(routingKey, result); + _parser.addBinding(routingKey, result); _topicExchangeResults.put(routingKey,result); } - else + else { if(argumentsContainSelector(args)) { @@ -490,7 +490,7 @@ public class TopicExchange extends AbstractExchange { routingKey = AMQShortString.EMPTY_STRING; } - + AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR); List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>(); @@ -574,7 +574,7 @@ public class TopicExchange extends AbstractExchange { return false; } - + } } @@ -642,17 +642,14 @@ public class TopicExchange extends AbstractExchange } - protected ExchangeMBean createMBean() throws AMQException + protected ExchangeMBean createMBean() throws JMException { - try - { - return new TopicExchangeMBean(); - } - catch (JMException ex) - { - _logger.error("Exception occured in creating the topic exchenge mbean", ex); - throw new AMQException("Exception occured in creating the topic exchenge mbean", ex); - } + return new TopicExchangeMBean(); + } + + public Logger getLogger() + { + return _logger; } private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java index da9737e780..06e8664470 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java @@ -20,8 +20,6 @@ package org.apache.qpid.server.filter; // Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html> // -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java index e1cfda6b21..f0650cb642 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java @@ -27,8 +27,6 @@ import java.util.HashSet; import java.util.List; import java.util.regex.Pattern; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java index 5cb0cde9fb..15cb770216 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java @@ -25,8 +25,6 @@ package org.apache.qpid.server.filter; import java.math.BigDecimal; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java index ae9eaaefd3..97e9915271 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java @@ -20,8 +20,6 @@ package org.apache.qpid.server.filter; // Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html> // -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java index a7a1eab3c3..b5e282038b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java @@ -14,18 +14,16 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.filter; // // Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html> // -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; -import org.apache.qpid.AMQException; public interface FilterManager { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java index 2d8e01a49a..fdba184da4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java @@ -20,8 +20,6 @@ package org.apache.qpid.server.filter; // Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html> // -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; /** diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java index febe68ece9..f5416af09a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java @@ -14,14 +14,12 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.filter; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; public interface MessageFilter diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java index 75010a79cf..aa35cb5a76 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.filter; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; import java.lang.reflect.Constructor; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java index 55954c7578..ae22f17413 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java @@ -18,7 +18,6 @@ package org.apache.qpid.server.filter; import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; // @@ -43,16 +42,16 @@ public final class XQueryExpression implements BooleanExpression { public String toString() { return "XQUERY "+ConstantExpression.encodeString(xpath); } - + /** * @param message * @return true if the expression evaluates to Boolean.TRUE. * @throws AMQException */ - public boolean matches(Filterable message) + public boolean matches(Filterable message) { Object object = evaluate(message); - return object!=null && object==Boolean.TRUE; + return object!=null && object==Boolean.TRUE; } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java index a423370b11..f83eb63ac5 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java @@ -27,8 +27,6 @@ import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.Filterable; import org.apache.xpath.CachedXPathAPI; import org.w3c.dom.Document; @@ -36,14 +34,14 @@ import org.w3c.dom.traversal.NodeIterator; import org.xml.sax.InputSource; public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator { - + private final String xpath; public XalanXPathEvaluator(String xpath) { this.xpath = xpath; } - - public boolean evaluate(Filterable m) + + public boolean evaluate(Filterable m) { // TODO - we would have to check the content type and then evaluate the content // here... is this really a feature we wish to implement? - RobG @@ -65,18 +63,18 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator { private boolean evaluate(byte[] data) { try { - + InputSource inputSource = new InputSource(new ByteArrayInputStream(data)); - + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder dbuilder = factory.newDocumentBuilder(); Document doc = dbuilder.parse(inputSource); - + CachedXPathAPI cachedXPathAPI = new CachedXPathAPI(); NodeIterator iterator = cachedXPathAPI.selectNodeIterator(doc,xpath); return iterator.nextNode()!=null; - + } catch (Throwable e) { return false; } @@ -85,12 +83,12 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator { private boolean evaluate(String text) { try { InputSource inputSource = new InputSource(new StringReader(text)); - + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder dbuilder = factory.newDocumentBuilder(); Document doc = dbuilder.parse(inputSource); - + // We should associated the cachedXPathAPI object with the message being evaluated // since that should speedup subsequent xpath expressions. CachedXPathAPI cachedXPathAPI = new CachedXPathAPI(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java index 59c3395929..bec51d361d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java @@ -1,6 +1,5 @@ package org.apache.qpid.server.flow; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.message.ServerMessage; /* diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java index 08610f24cd..859a3477e6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java @@ -25,7 +25,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.*; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.ConsumerTagNotUniqueException; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.Permission; @@ -116,17 +115,31 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic try { - AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(), - body.getArguments(), body.getNoLocal(), body.getExclusive()); - if (!body.getNowait()) + if(consumerTagName == null || channel.getSubscription(consumerTagName) == null) { - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag); - session.writeFrame(responseBody.generateFrame(channelId)); + AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(), + body.getArguments(), body.getNoLocal(), body.getExclusive()); + if (!body.getNowait()) + { + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag); + session.writeFrame(responseBody.generateFrame(channelId)); + + } + } + else + { + AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'"); + + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode + msg, // replytext + body.getClazz(), + body.getMethod()); + session.writeFrame(responseBody.generateFrame(0)); } - } catch (org.apache.qpid.AMQInvalidArgumentException ise) { @@ -141,17 +154,6 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic } - catch (ConsumerTagNotUniqueException e) - { - AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'"); - - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode - msg, // replytext - body.getClazz(), - body.getMethod()); - session.writeFrame(responseBody.generateFrame(0)); - } catch (AMQQueue.ExistingExclusiveSubscription e) { throw body.getChannelException(AMQConstant.ACCESS_REFUSED, 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 55b1802f88..a473184efb 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 @@ -30,6 +30,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.MessageOnlyCreditManager;
import org.apache.qpid.server.subscription.SubscriptionImpl;
@@ -40,9 +41,6 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java index 824f084f57..31bafac0a2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java @@ -24,7 +24,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.*; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; @@ -96,7 +95,7 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con session.writeFrame(responseBody.generateFrame(channelId)); - + } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java index 0fe8c5dc92..9f392ffc44 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java @@ -50,5 +50,6 @@ public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener<C } stateManager.changeState(AMQState.CONNECTION_NOT_OPENED); session.initHeartbeats(body.getHeartbeat()); + session.setMaxFrameSize(body.getFrameMax()); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java index ba60808492..b0ee5fff08 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.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 @@ -92,11 +92,11 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange try { - exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(), - body.getType() == null ? null : body.getType().intern(), - body.getDurable(), - body.getPassive(), body.getTicket()); - exchangeRegistry.registerExchange(exchange); + exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(), + body.getType() == null ? null : body.getType().intern(), + body.getDurable(), + body.getPassive(), body.getTicket()); + exchangeRegistry.registerExchange(exchange); } catch(AMQUnknownExchangeType e) { 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 54f8e70965..4f69afe755 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 @@ -40,7 +40,6 @@ import org.apache.qpid.server.queue.QueueRegistry; 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; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties index eafcb43cc0..1a2cb7251c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties @@ -61,13 +61,32 @@ MST-1001 = Created : {0} # 0 - path MST-1002 = Store location : {0} MST-1003 = Closed +MST-1004 = Recovery Start +MST-1005 = Recovered {0,number} messages +MST-1006 = Recovery Complete + +#ConfigStore +# 0 - name +CFG-1001 = Created : {0} +# 0 - path +CFG-1002 = Store location : {0} +CFG-1003 = Closed +CFG-1004 = Recovery Start +CFG-1005 = Recovery Complete + +#TransactionLog +# 0 - name +TXN-1001 = Created : {0} +# 0 - path +TXN-1002 = Store location : {0} +TXN-1003 = Closed # 0 - queue name -MST-1004 = Recovery Start[ : {0}] +TXN-1004 = Recovery Start[ : {0}] # 0 - count # 1 - queue count -MST-1005 = Recovered {0,number} messages for queue {1} +TXN-1005 = Recovered {0,number} messages for queue {1} # 0 - queue name -MST-1006 = Recovery Complete[ : {0}] +TXN-1006 = Recovery Complete[ : {0}] #Connection # 0 - Client id @@ -83,12 +102,18 @@ CHN-1003 = Close # 0 - bytes allowed in prefetch # 1 - number of messagse. CHN-1004 = Prefetch Size (bytes) {0,number} : Count {1,number} +# 0 - queue causing flow control +CHN-1005 = Flow Control Enforced (Queue {0}) +CHN-1006 = Flow Control Removed #Queue # 0 - owner # 1 - priority QUE-1001 = Create :[ Owner: {0}][ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] QUE-1002 = Deleted +QUE-1003 = Overfull : Size : {0,number} bytes, Capacity : {1,number} +QUE-1004 = Underfull : Size : {0,number} bytes, Resume Capacity : {1,number} + #Exchange # 0 - type @@ -104,4 +129,4 @@ BND-1002 = Deleted SUB-1001 = Create[ : Durable][ : Arguments : {0}] SUB-1002 = Close # 0 - The current subscription state -SUB-1003 = State : {0}
\ No newline at end of file +SUB-1003 = State : {0} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties index 9169a1a651..1a2cb7251c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties @@ -16,173 +16,7 @@ # specific language governing permissions and limitations # under the License. # -# LogMessages used within the Java Broker as originally defined on the wiki: -# -# http://cwiki.apache.org/confluence/display/qpid/Status+Update+Design#StatusUpdateDesign-InitialStatusMessages -# -# Technical Notes: -# This is a standard Java Properties file so white space is respected at the -# end of the lines. This file is processed in a number of ways. -# 1) ResourceBundle -# This file is loaded through a ResourceBundle named LogMessages. the en_US -# addition to the file is the localisation. Additional localisations can be -# provided and will automatically be selected based on the <locale> value in -# the config.xml. The default is en_US. -# -# 2) MessasgeFormat -# Each entry is prepared with the Java Core MessageFormat methods. Therefore -# most functionality you can do via MessageFormat can be done here: -# -# http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html -# -# The cavet here is that only default String and number FormatTypes can be used. -# This is due to the processing described in 3 below. If support for date, time -# or choice is requried then the GenerateLogMessages class should be updated to -# provide support. -# -# Format Note: -# As mentioned earlier white space in this file is very important. One thing -# in particular to note is the way MessageFormat peforms its replacements. -# The replacement text will totally replace the {xxx} section so there will be -# no addtion of white space or removal e.g. -# MSG = Text----{0}---- -# When given parameter 'Hello' result in text: -# Text----Hello---- -# -# For simple arguments this is expected however when using Style formats then -# it can be a little unexepcted. In particular a common pattern is used for -# number replacements : {0,number,#}. This is used in the Broker to display an -# Integer simply as the Integer with no formating. e.g new Integer(1234567) -# becomes the String "1234567" which is can be contrasted with the pattern -# without a style format field : {0,number} which becomes string "1,234,567". -# -# What you may not expect is that {0,number, #} would produce the String " 1234567" -# note the space after the ',' here /\ has resulted in a space /\ in -# the output. -# -# More details on the SubformatPattern can be found on the API link above. -# -# 3) GenerateLogMessage/Velocity Macro -# This is the first and final stage of processing that this file goes through. -# 1) Class Generation: -# The GenerateLogMessage processes this file and uses the velocity Macro -# to create classes with static methods to perform the logging and give us -# compile time validation. -# -# 2) Property Processing: -# During the class generation the message properties ({x}) are identified -# and used to create the method signature. -# -# 3) Option Processing: -# The Classes perform final formatting of the messages at runtime based on -# optional parameters that are defined within the message. Optional -# paramters are enclosed in square brackets e.g. [optional]. -# -# To provide fixed log messages as required by the Technical Specification: -# http://cwiki.apache.org/confluence/display/qpid/Operational+Logging+-+Status+Update+-+Technical+Specification#OperationalLogging-StatusUpdate-TechnicalSpecification-Howtoprovidefixedlogmessages -# -# This file is processed by Velocity to create a number of classes that contain -# static methods that provide LogMessages in the code to provide compile time -# validation. -# -# For details of what processing is done see GenerateLogMessages. -# -# What a localiser or developer need know is the following: -# -# The Property structure is important is it defines how the class and methods -# will be built. -# -# Class Generation: -# ================= -# -# Each class of messages will be split in to their own <Class>Messages.java -# Currently the following classes are created and are populated with the -# messages that bear their 3-digit type identifier: -# -# Class | Type -# ---------------------|-------- -# Broker | BKR -# ManagementConsole | MNG -# VirtualHost | VHT -# MessageStore | MST -# Connection | CON -# Channel | CHN -# Queue | QUE -# Exchange | EXH -# Binding | BND -# Subscription | SUB -# -# Property Processing: -# ==================== -# -# Each property is then processed by the GenerateLogMessages class to identify -# The number and type of parameters, {x} entries. Parameters are defaulted to -# String types but the use of FormatType number (e.g.{0,number}) will result -# in a Number type being used. These parameters are then used to build the -# method parameter list. e.g: -# Property: -# BRK-1003 = Shuting down : {0} port {1,number,#} -# becomes Method: -# public static LogMessage BRK_1003(String param1, Number param2) -# -# This improves our compile time validation of log message content and -# ensures that change in the message format does not accidentally cause -# erroneous messages. -# -# Option Processing: -# ==================== -# -# Options are identified in the log message as being surrounded by square -# brackets ([ ]). These optional values can themselves contain paramters -# however nesting of options is not permitted. Identification is performed on -# first matchings so give the message: -# Msg = Log Message [option1] [option2] -# Two options will be identifed and enabled to select text 'option1 and -# 'option2'. -# -# The nesting of a options is not supported and will provide -# unexpected results. e.g. Using Message: -# Msg = Log Message [option1 [sub-option2]] -# -# The options will be 'option1 [sub-option2' and 'sub-option2'. The first -# option includes the second option as the nesting is not detected. -# -# The detected options are presented in the method signature as boolean options -# numerically identified by their position in the message. e.g. -# Property: -# CON-1001 = Open : Client ID {0} [: Protocol Version : {1}] -# becomes Method: -# public static LogMessage CON_1001(String param1, String param2, boolean opt1) -# -# The value of 'opt1' will show/hide the option in the message. Note that -# 'param2' is still required however a null value can be used if the optional -# section is not desired. -# -# Again here the importance of white space needs to be highlighted. -# Looking at the QUE-1001 message as an example. The first thought on how this -# would look would be as follows: -# QUE-1001 = Create : Owner: {0} [AutoDelete] [Durable] [Transient] [Priority: {1,number,#}] -# Each option is correctly defined so the text that is defined will appear when -# selected. e.g. 'AutoDelete'. However, what may not be immediately apparent is -# the white space. Using the above definition of QUE-1001 if we were to print -# the message with only the Priority option displayed it would appear as this: -# "Create : Owner: guest Priority: 1" -# Note the spaces here /\ This is because only the text between the brackets -# has been removed. -# -# Each option needs to include white space to correctly format the message. So -# the correct definition of QUE-1001 is as follows: -# QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] -# Note that white space is included with each option and there is no extra -# white space between the options. As a result the output with just Priority -# enabled is as follows: -# "Create : Owner: guest Priority: 1" -# -# The final processing that is done in the generation is the conversion of the -# property name. As a '-' is an illegal character in the method name it is -# converted to '_' This processing gives the final method signature as follows: -# <Class>Message.<Type>_<Number>(<parmaters>,<options>) -# +# Default File used for all non-defined locales. #Broker # 0 - Version # 1 = Build @@ -227,13 +61,32 @@ MST-1001 = Created : {0} # 0 - path MST-1002 = Store location : {0} MST-1003 = Closed +MST-1004 = Recovery Start +MST-1005 = Recovered {0,number} messages +MST-1006 = Recovery Complete + +#ConfigStore +# 0 - name +CFG-1001 = Created : {0} +# 0 - path +CFG-1002 = Store location : {0} +CFG-1003 = Closed +CFG-1004 = Recovery Start +CFG-1005 = Recovery Complete + +#TransactionLog +# 0 - name +TXN-1001 = Created : {0} +# 0 - path +TXN-1002 = Store location : {0} +TXN-1003 = Closed # 0 - queue name -MST-1004 = Recovery Start[ : {0}] +TXN-1004 = Recovery Start[ : {0}] # 0 - count # 1 - queue count -MST-1005 = Recovered {0,number} messages for queue {1} +TXN-1005 = Recovered {0,number} messages for queue {1} # 0 - queue name -MST-1006 = Recovery Complete[ : {0}] +TXN-1006 = Recovery Complete[ : {0}] #Connection # 0 - Client id @@ -247,8 +100,9 @@ CHN-1001 = Create CHN-1002 = Flow {0} CHN-1003 = Close # 0 - bytes allowed in prefetch -# 1 - number of messagse. +# 1 - number of messagse. CHN-1004 = Prefetch Size (bytes) {0,number} : Count {1,number} +# 0 - queue causing flow control CHN-1005 = Flow Control Enforced (Queue {0}) CHN-1006 = Flow Control Removed @@ -260,6 +114,7 @@ QUE-1002 = Deleted QUE-1003 = Overfull : Size : {0,number} bytes, Capacity : {1,number} QUE-1004 = Underfull : Size : {0,number} bytes, Resume Capacity : {1,number} + #Exchange # 0 - type # 1 - name @@ -273,4 +128,5 @@ BND-1002 = Deleted #Subscription SUB-1001 = Create[ : Durable][ : Arguments : {0}] SUB-1002 = Close +# 0 - The current subscription state SUB-1003 = State : {0} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java index 67aee90ba4..d72b8f24ec 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.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 @@ -65,16 +65,9 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana return null; } - public void register() throws AMQException + public void register() throws JMException { - try - { - getManagedObjectRegistry().registerObject(this); - } - catch (JMException e) - { - throw new AMQException("Error registering managed object " + this + ": " + e, e); - } + getManagedObjectRegistry().registerObject(this); } protected ManagedObjectRegistry getManagedObjectRegistry() @@ -98,7 +91,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana { return getObjectInstanceName() + "[" + getType() + "]"; } - + /** * Created the ObjectName as per the JMX Specs @@ -140,7 +133,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana objectName.append(","); objectName.append("version=").append(_version); - + return new ObjectName(objectName.toString()); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java index aea9ab43ea..92657d7f3c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java @@ -54,6 +54,7 @@ import java.lang.reflect.Proxy; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.UnknownHostException; import java.rmi.AlreadyBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; @@ -236,8 +237,17 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's. */ - final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env); - final String hostname = InetAddress.getLocalHost().getHostName(); + final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env); + String localHost; + try + { + localHost = InetAddress.getLocalHost().getHostName(); + } + catch(UnknownHostException ex) + { + localHost="127.0.0.1"; + } + final String hostname = localHost; final JMXServiceURL externalUrl = new JMXServiceURL( "service:jmx:rmi://"+hostname+":"+(port+PORT_EXPORT_OFFSET)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi"); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java index 42ea8921a4..de14785fb0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.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 @@ -22,6 +22,7 @@ package org.apache.qpid.server.management; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; +import javax.management.JMException; import org.apache.qpid.AMQException; @@ -45,7 +46,7 @@ public interface ManagedObject ManagedObject getParentObject(); - void register() throws AMQException; + void register() throws AMQException, JMException; void unregister() throws AMQException; 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/message/AMQMessage.java index 1d4fd6b1ea..b8a36aba58 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/message/AMQMessage.java @@ -18,21 +18,18 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.message; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQDataBlock; 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.protocol.AMQProtocolSession; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.message.*; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.queue.AMQQueue; -import java.util.Iterator; import java.util.concurrent.atomic.AtomicInteger; +import java.nio.ByteBuffer; /** * A deliverable message. @@ -44,8 +41,6 @@ public class AMQMessage implements ServerMessage private final AtomicInteger _referenceCount = new AtomicInteger(0); - private final AMQMessageHandle _messageHandle; - /** Flag to indicate that this message requires 'immediate' delivery. */ private static final byte IMMEDIATE = 0x01; @@ -65,73 +60,21 @@ public class AMQMessage implements ServerMessage private Object _sessionIdentifier; private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER); - private final AMQMessageHeader _messageHeader; - - - /** - * Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal - * enqueue/routingComplete is not done since the recovery process is responsible for routing the messages to - * queues. - * - * @param messageId - * @param store - * @param factory - * - * @throws AMQException - */ - public AMQMessage(Long messageId, MessageStore store, MessageHandleFactory factory) - throws AMQException - { - _messageHandle = factory.createMessageHandle(messageId, store, true); - _size = _messageHandle.getBodySize(); - _messageHeader = new ContentHeaderBodyAdapter(_messageHandle.getContentHeaderBody()); - } - /** - * Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal - * enqueue/routingComplete is not done since the recovery process is responsible for routing the messages to - * queues. - * - * @param messageHandle - * - * @throws AMQException - */ - public AMQMessage( - AMQMessageHandle messageHandle, - MessagePublishInfo info) - throws AMQException - { - this(messageHandle, messageHandle.getContentHeaderBody(), messageHandle.getBodySize(), info); - } + private final StoredMessage<MessageMetaData> _handle; - public AMQMessage( - AMQMessageHandle messageHandle, - ContentHeaderBody chb, - long size, - MessagePublishInfo info) - throws AMQException + public AMQMessage(StoredMessage<MessageMetaData> handle) { - _messageHandle = messageHandle; - - _messageHeader = new ContentHeaderBodyAdapter(chb); + _handle = handle; + final MessageMetaData metaData = handle.getMetaData(); + _size = metaData.getContentSize(); + final MessagePublishInfo messagePublishInfo = metaData.getMessagePublishInfo(); - if(info.isImmediate()) + if(messagePublishInfo.isImmediate()) { _flags |= IMMEDIATE; } - _size = size; - - } - - - protected AMQMessage(AMQMessage msg) throws AMQException - { - _messageHandle = msg._messageHandle; - _messageHeader = msg._messageHeader; - _flags = msg._flags; - _size = msg._size; - } @@ -152,26 +95,21 @@ public class AMQMessage implements ServerMessage return _referenceCount.get() > 0; } - public Iterator<AMQDataBlock> getBodyFrameIterator(AMQProtocolSession protocolSession, int channel) - { - return new BodyFrameIterator(protocolSession, channel, _messageHandle); - } - - public Iterator<ContentChunk> getContentBodyIterator() + public MessageMetaData getMessageMetaData() { - return new BodyContentIterator(_messageHandle); + return _handle.getMetaData(); } public ContentHeaderBody getContentHeaderBody() throws AMQException { - return _messageHandle.getContentHeaderBody(); + return getMessageMetaData().getContentHeaderBody(); } public Long getMessageId() { - return _messageHandle.getMessageId(); + return _handle.getMessageNumber(); } /** @@ -211,10 +149,10 @@ public class AMQMessage implements ServerMessage * message store. * * - * @throws MessageCleanupException when an attempt was made to remove the message from the message store and that + * @throws org.apache.qpid.server.queue.MessageCleanupException when an attempt was made to remove the message from the message store and that * failed */ - public void decrementReference() throws MessageCleanupException + public void decrementReference() { int count = _referenceCount.decrementAndGet(); @@ -229,27 +167,19 @@ public class AMQMessage implements ServerMessage // by copying from other queues at the same time as it is being removed. _referenceCount.set(Integer.MIN_VALUE/2); - try + // 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 (_handle != null) { - // 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 && isPersistent()) - { - _messageHandle.removeMessage(); + _handle.remove(); - } - } - catch (AMQException e) - { - - throw new MessageCleanupException(getMessageId(), e); } } else { if (count < 0) { - throw new MessageCleanupException("Reference count for message id " + debugIdentity() + throw new RuntimeException("Reference count for message id " + debugIdentity() + " has gone below 0."); } } @@ -274,12 +204,12 @@ public class AMQMessage implements ServerMessage public AMQMessageHeader getMessageHeader() { - return _messageHeader; + return getMessageMetaData().getMessageHeader(); } public boolean isPersistent() { - return _messageHandle.isPersistent(); + return getMessageMetaData().isPersistent(); } /** @@ -297,12 +227,12 @@ public class AMQMessage implements ServerMessage public MessagePublishInfo getMessagePublishInfo() throws AMQException { - return _messageHandle.getMessagePublishInfo(); + return getMessageMetaData().getMessagePublishInfo(); } public long getArrivalTime() { - return _messageHandle.getArrivalTime(); + return getMessageMetaData().getArrivalTime(); } /** @@ -336,13 +266,6 @@ public class AMQMessage implements ServerMessage _flags |= DELIVERED_TO_CONSUMER; } - - - public AMQMessageHandle getMessageHandle() - { - return _messageHandle; - } - public long getSize() { return _size; @@ -394,4 +317,13 @@ public class AMQMessage implements ServerMessage return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + _referenceCount; } + public int getContent(ByteBuffer buf, int offset) + { + return _handle.getContent(offset, buf); + } + + public StoredMessage<MessageMetaData> getStoredMessage() + { + return _handle; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java index 3e79bc2260..6c9311c3de 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java @@ -30,6 +30,10 @@ public interface AMQMessageHeader String getMessageId(); + String getMimeType(); + + String getEncoding(); + byte getPriority(); long getTimestamp(); 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 1b4b9a270c..940caaefe4 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 @@ -20,13 +20,9 @@ */ package org.apache.qpid.server.message; -import org.apache.qpid.server.queue.AMQMessage; +import org.apache.qpid.server.message.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> { @@ -43,22 +39,6 @@ public class AMQMessageReference extends MessageReference<AMQMessage> protected void onRelease(AMQMessage message) { - try - { - if(message !=null) - { - message.decrementReference(); - } - else - { - //TODO - System.err.println("Shouldn't happen!!!!"); - } - } - catch (MessageCleanupException e) - { - // TODO - throw new RuntimeException(e); - } + message.decrementReference(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java index 37e7bcc566..4a1f8dd191 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java @@ -55,6 +55,16 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader return getProperties().getMessageIdAsString(); } + public String getMimeType() + { + return getProperties().getContentTypeAsString(); + } + + public String getEncoding() + { + return getProperties().getEncodingAsString(); + } + public byte getPriority() { return getProperties().getPriority(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ConsumerTagNotUniqueException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java index 9a98af5689..08a09c4a85 100644..100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ConsumerTagNotUniqueException.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.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 @@ -18,8 +18,14 @@ * under the License. * */ -package org.apache.qpid.server; -public class ConsumerTagNotUniqueException extends Exception +package org.apache.qpid.server.message; + +import java.nio.ByteBuffer; + +public interface MessageContentSource { + public int getContent(ByteBuffer buf, int offset); + + long getSize(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java new file mode 100644 index 0000000000..b34a8fc470 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java @@ -0,0 +1,309 @@ +/* + * + * 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; + +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.EncodingUtils; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.AMQException; + +import java.nio.ByteBuffer; +import java.util.Set; + +/** + * Encapsulates a publish body and a content header. In the context of the message store these are treated as a + * single unit. + */ +public class MessageMetaData implements StorableMessageMetaData +{ + private MessagePublishInfo _messagePublishInfo; + + private ContentHeaderBody _contentHeaderBody; + + private int _contentChunkCount; + + private long _arrivalTime; + private static final byte MANDATORY_FLAG = 1; + private static final byte IMMEDIATE_FLAG = 2; + public static final MessageMetaDataType.Factory<MessageMetaData> FACTORY = new MetaDataFactory(); + + public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount) + { + this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis()); + } + + public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime) + { + _contentHeaderBody = contentHeaderBody; + _messagePublishInfo = publishBody; + _contentChunkCount = contentChunkCount; + _arrivalTime = arrivalTime; + } + + public int getContentChunkCount() + { + return _contentChunkCount; + } + + public void setContentChunkCount(int contentChunkCount) + { + _contentChunkCount = contentChunkCount; + } + + public ContentHeaderBody getContentHeaderBody() + { + return _contentHeaderBody; + } + + public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) + { + _contentHeaderBody = contentHeaderBody; + } + + public MessagePublishInfo getMessagePublishInfo() + { + return _messagePublishInfo; + } + + public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo) + { + _messagePublishInfo = messagePublishInfo; + } + + public long getArrivalTime() + { + return _arrivalTime; + } + + public void setArrivalTime(long arrivalTime) + { + _arrivalTime = arrivalTime; + } + + public MessageMetaDataType getType() + { + return MessageMetaDataType.META_DATA_0_8; + } + + public int getStorableSize() + { + BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties); + int size = _contentHeaderBody.getSize(); + size += 4; + size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getExchange()); + size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getRoutingKey()); + size += 1; // flags for immediate/mandatory + size += EncodingUtils.encodedLongLength(); + + return size; + } + + public int writeToBuffer(int offset, ByteBuffer dest) + { + ByteBuffer src = ByteBuffer.allocate((int)getStorableSize()); + + org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(src); + EncodingUtils.writeInteger(minaSrc, _contentHeaderBody.getSize()); + _contentHeaderBody.writePayload(minaSrc); + EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getExchange()); + EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getRoutingKey()); + byte flags = 0; + if(_messagePublishInfo.isMandatory()) + { + flags |= MANDATORY_FLAG; + } + if(_messagePublishInfo.isImmediate()) + { + flags |= IMMEDIATE_FLAG; + } + EncodingUtils.writeByte(minaSrc, flags); + EncodingUtils.writeLong(minaSrc,_arrivalTime); + src.position(minaSrc.position()); + src.flip(); + src.position(offset); + src = src.slice(); + if(dest.remaining() < src.limit()) + { + src.limit(dest.remaining()); + } + dest.put(src); + + + return src.limit(); + } + + public int getContentSize() + { + return (int) _contentHeaderBody.bodySize; + } + + public boolean isPersistent() + { + BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties); + return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT; + } + + private static class MetaDataFactory implements MessageMetaDataType.Factory + { + + + public MessageMetaData createMetaData(ByteBuffer buf) + { + try + { + org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(buf); + int size = EncodingUtils.readInteger(minaSrc); + ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(minaSrc, size); + final AMQShortString exchange = EncodingUtils.readAMQShortString(minaSrc); + final AMQShortString routingKey = EncodingUtils.readAMQShortString(minaSrc); + + final byte flags = EncodingUtils.readByte(minaSrc); + long arrivalTime = EncodingUtils.readLong(minaSrc); + + MessagePublishInfo publishBody = + new MessagePublishInfo() + { + + public AMQShortString getExchange() + { + return exchange; + } + + public void setExchange(AMQShortString exchange) + { + } + + public boolean isImmediate() + { + return (flags & IMMEDIATE_FLAG) != 0; + } + + public boolean isMandatory() + { + return (flags & MANDATORY_FLAG) != 0; + } + + public AMQShortString getRoutingKey() + { + return routingKey; + } + }; + return new MessageMetaData(publishBody, chb, 0, arrivalTime); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + + } + }; + + public AMQMessageHeader getMessageHeader() + { + return new MessageHeaderAdapter(); + } + + private final class MessageHeaderAdapter implements AMQMessageHeader + { + private BasicContentHeaderProperties getProperties() + { + return (BasicContentHeaderProperties) getContentHeaderBody().properties; + } + + public String getCorrelationId() + { + return getProperties().getCorrelationIdAsString(); + } + + public long getExpiration() + { + return getProperties().getExpiration(); + } + + public String getMessageId() + { + return getProperties().getMessageIdAsString(); + } + + public String getMimeType() + { + return getProperties().getContentTypeAsString(); + } + + public String getEncoding() + { + return getProperties().getEncodingAsString(); + } + + public byte getPriority() + { + return getProperties().getPriority(); + } + + public long getTimestamp() + { + return getProperties().getTimestamp(); + } + + public String getType() + { + return getProperties().getTypeAsString(); + } + + public String getReplyTo() + { + return getProperties().getReplyToAsString(); + } + + public Object getHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.get(name); + } + + public boolean containsHeaders(Set<String> names) + { + FieldTable ft = getProperties().getHeaders(); + for(String name : names) + { + if(!ft.containsKey(name)) + { + return false; + } + } + return true; + } + + public boolean containsHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.containsKey(name); + } + + + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java new file mode 100755 index 0000000000..5a5e2fe5b4 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java @@ -0,0 +1,242 @@ +/* +* +* 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; + +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.transport.Struct; +import org.apache.qpid.transport.codec.BBEncoder; +import org.apache.qpid.transport.codec.BBDecoder; + +import java.nio.ByteBuffer; +import java.lang.ref.WeakReference; + +public class MessageMetaData_0_10 implements StorableMessageMetaData +{ + private Header _header; + private DeliveryProperties _deliveryProps; + private MessageProperties _messageProps; + private MessageTransferHeader _messageHeader; + private long _arrivalTime; + private int _bodySize; + private volatile WeakReference<ByteBuffer> _body; + + private static final int ENCODER_SIZE = 1 << 16; + + public static final MessageMetaDataType.Factory<MessageMetaData_0_10> FACTORY = new MetaDataFactory(); + + private volatile ByteBuffer _encoded; + + + public MessageMetaData_0_10(MessageTransfer xfr) + { + this(xfr.getHeader(), xfr.getBodySize(), xfr.getBody(), System.currentTimeMillis()); + } + + private MessageMetaData_0_10(Header header, int bodySize, long arrivalTime) + { + this(header, bodySize, null, arrivalTime); + } + + private MessageMetaData_0_10(Header header, int bodySize, ByteBuffer xfrBody, long arrivalTime) + { + _header = header; + if(_header != null) + { + _deliveryProps = _header.get(DeliveryProperties.class); + _messageProps = _header.get(MessageProperties.class); + } + else + { + _deliveryProps = null; + _messageProps = null; + } + _messageHeader = new MessageTransferHeader(_deliveryProps, _messageProps); + _arrivalTime = arrivalTime; + _bodySize = bodySize; + + + + if(xfrBody == null) + { + _body = null; + } + else + { + ByteBuffer body = ByteBuffer.allocate(_bodySize); + body.put(xfrBody); + body.flip(); + _body = new WeakReference(body); + } + + + } + + + + public MessageMetaDataType getType() + { + return MessageMetaDataType.META_DATA_0_10; + } + + public int getStorableSize() + { + ByteBuffer buf = _encoded; + + if(buf == null) + { + buf = encodeAsBuffer(); + _encoded = buf; + } + + //TODO -- need to add stuff + return buf.limit(); + } + + private ByteBuffer encodeAsBuffer() + { + BBEncoder encoder = new BBEncoder(ENCODER_SIZE); + + encoder.writeInt64(_arrivalTime); + encoder.writeInt32(_bodySize); + Struct[] headers = _header == null ? new Struct[0] : _header.getStructs(); + encoder.writeInt32(headers.length); + + + for(Struct header : headers) + { + encoder.writeStruct32(header); + + } + + ByteBuffer buf = encoder.buffer(); + return buf; + } + + public int writeToBuffer(int offsetInMetaData, ByteBuffer dest) + { + ByteBuffer buf = _encoded; + + if(buf == null) + { + buf = encodeAsBuffer(); + _encoded = buf; + } + + buf = buf.duplicate(); + + buf.position(offsetInMetaData); + + if(dest.remaining() < buf.limit()) + { + buf.limit(dest.remaining()); + } + dest.put(buf); + return buf.limit(); + } + + public int getContentSize() + { + return _bodySize; + } + + public boolean isPersistent() + { + return _deliveryProps == null ? false : _deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT; + } + + public String getRoutingKey() + { + return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); + } + + public AMQMessageHeader getMessageHeader() + { + return _messageHeader; + } + + public long getSize() + { + + return _bodySize; + } + + public boolean isImmediate() + { + return _deliveryProps != null && _deliveryProps.getImmediate(); + } + + public long getExpiration() + { + return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); + } + + public long getArrivalTime() + { + return _arrivalTime; + } + + public Header getHeader() + { + return _header; + } + + public ByteBuffer getBody() + { + ByteBuffer body = _body == null ? null : _body.get(); + return body; + } + + public void setBody(ByteBuffer body) + { + _body = new WeakReference(body); + } + + private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_0_10> + { + public MessageMetaData_0_10 createMetaData(ByteBuffer buf) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(buf); + + long arrivalTime = decoder.readInt64(); + int bodySize = decoder.readInt32(); + int headerCount = decoder.readInt32(); + + Struct[] headers = new Struct[headerCount]; + + for(int i = 0 ; i < headerCount; i++) + { + headers[i] = decoder.readStruct32(); + } + + Header header = new Header(headers); + + return new MessageMetaData_0_10(header, bodySize, arrivalTime); + + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java index 0c03cb0ea7..1a75d7ca65 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java @@ -57,6 +57,16 @@ class MessageTransferHeader implements AMQMessageHeader return _messageProps == null ? null : String.valueOf(_messageProps.getMessageId()); } + public String getMimeType() + { + return _messageProps == null ? null : _messageProps.getContentType(); + } + + public String getEncoding() + { + return _messageProps == null ? null : _messageProps.getContentEncoding(); + } + public byte getPriority() { MessageDeliveryPriority priority = _deliveryProps == null diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java index 580e7d21f0..e866ad5078 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.message; import org.apache.qpid.transport.*; +import org.apache.qpid.server.store.StoredMessage; import java.util.concurrent.atomic.AtomicLong; import java.nio.ByteBuffer; @@ -29,76 +30,65 @@ import java.lang.ref.WeakReference; public class MessageTransferMessage implements InboundMessage, ServerMessage { - private static final AtomicLong _numberSource = new AtomicLong(0L); - - private final MessageTransfer _xfr; - private final DeliveryProperties _deliveryProps; - private final MessageProperties _messageProps; - private final AMQMessageHeader _messageHeader; - private final long _messageNumber; - private final long _arrivalTime; + + + private StoredMessage<MessageMetaData_0_10> _storeMessage; + + private WeakReference<Session> _sessionRef; - public MessageTransferMessage(MessageTransfer xfr, WeakReference<Session> sessionRef) - { - this(_numberSource.getAndIncrement(), xfr, sessionRef); - } - public MessageTransferMessage(long messageNumber, MessageTransfer xfr, WeakReference<Session> sessionRef) + public MessageTransferMessage(StoredMessage<MessageMetaData_0_10> storeMessage, WeakReference<Session> sessionRef) { - _xfr = xfr; - _messageNumber = messageNumber; - Header header = _xfr.getHeader(); - if(header != null) - { - _deliveryProps = header.get(DeliveryProperties.class); - _messageProps = header.get(MessageProperties.class); - } - else - { - _deliveryProps = null; - _messageProps = null; - } - _messageHeader = new MessageTransferHeader(_deliveryProps, _messageProps); - _arrivalTime = System.currentTimeMillis(); + _storeMessage = storeMessage; _sessionRef = sessionRef; + + } + + private MessageMetaData_0_10 getMetaData() + { + return _storeMessage.getMetaData(); } public String getRoutingKey() { - return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); + return getMetaData().getRoutingKey(); + } public AMQMessageHeader getMessageHeader() { - return _messageHeader; + return getMetaData().getMessageHeader(); } public boolean isPersistent() { - return (_deliveryProps != null) && (_deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT); + return getMetaData().isPersistent(); } + public boolean isRedelivered() { + // The *Message* is never redelivered, only queue entries are... this is here so that filters + // can run against the message on entry to an exchange return false; } public long getSize() { - return _xfr.getBodySize(); + return getMetaData().getSize(); } public boolean isImmediate() { - return _deliveryProps != null && _deliveryProps.getImmediate(); + return getMetaData().isImmediate(); } public long getExpiration() { - return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); + return getMetaData().getExpiration(); } public MessageReference newReference() @@ -108,23 +98,43 @@ public class MessageTransferMessage implements InboundMessage, ServerMessage public Long getMessageNumber() { - return _messageNumber; + return _storeMessage.getMessageNumber(); } public long getArrivalTime() { - return _arrivalTime; + return getMetaData().getArrivalTime(); } - public Header getHeader() + public int getContent(ByteBuffer buf, int offset) { - return _xfr.getHeader(); + return _storeMessage.getContent(offset, buf); + } + public Header getHeader() + { + return getMetaData().getHeader(); } public ByteBuffer getBody() { - return _xfr.getBody(); + ByteBuffer body = getMetaData().getBody(); + if(body == null) + { + final int size = (int) getSize(); + int pos = 0; + body = ByteBuffer.allocate(size); + + while(pos < size) + { + pos += getContent(body, pos); + } + + body.flip(); + + getMetaData().setBody(body.duplicate()); + } + return body; } public Session getSession() @@ -132,4 +142,5 @@ public class MessageTransferMessage implements InboundMessage, ServerMessage return _sessionRef == null ? null : _sessionRef.get(); } + } 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 7702e4729f..1ac538c15b 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,7 +20,9 @@ */ package org.apache.qpid.server.message; -public interface ServerMessage extends EnqueableMessage +import java.nio.ByteBuffer; + +public interface ServerMessage extends EnqueableMessage, MessageContentSource { String getRoutingKey(); @@ -39,4 +41,7 @@ public interface ServerMessage extends EnqueableMessage Long getMessageNumber(); long getArrivalTime(); + + public int getContent(ByteBuffer buf, int offset); + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java new file mode 100755 index 0000000000..aded3f3d2a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java @@ -0,0 +1,124 @@ +/* +* +* 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.output; + +import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.AMQPInvalidClassException; + +import java.util.Map; + +public class HeaderPropertiesConverter +{ + + public static BasicContentHeaderProperties convert(MessageTransferMessage messageTransferMessage) + { + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + + Header header = messageTransferMessage.getHeader(); + DeliveryProperties deliveryProps = header.get(DeliveryProperties.class); + MessageProperties messageProps = header.get(MessageProperties.class); + + if(deliveryProps != null) + { + if(deliveryProps.hasDeliveryMode()) + { + props.setDeliveryMode((byte)(deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT)); + } + if(deliveryProps.hasExpiration()) + { + props.setExpiration(deliveryProps.getExpiration()); + } + if(deliveryProps.hasPriority()) + { + props.setPriority((byte)deliveryProps.getPriority().getValue()); + } + if(deliveryProps.hasTimestamp()) + { + props.setTimestamp(deliveryProps.getTimestamp()); + } + } + if(messageProps != null) + { + if(messageProps.hasAppId()) + { + props.setAppId(new AMQShortString(messageProps.getAppId())); + } + if(messageProps.hasContentType()) + { + props.setContentType(messageProps.getContentType()); + } + if(messageProps.hasCorrelationId()) + { + props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId())); + } + if(messageProps.hasContentEncoding()) + { + props.setEncoding(messageProps.getContentEncoding()); + } + if(messageProps.hasMessageId()) + { + props.setMessageId(messageProps.getMessageId().toString()); + } + + // TODO Reply-to + + if(messageProps.hasUserId()) + { + props.setUserId(new AMQShortString(messageProps.getUserId())); + } + + if(messageProps.hasApplicationHeaders()) + { + Map<String, Object> appHeaders = messageProps.getApplicationHeaders(); + FieldTable ft = new FieldTable(); + for(Map.Entry<String, Object> entry : appHeaders.entrySet()) + { + try + { + ft.put(new AMQShortString(entry.getKey()), entry.getValue()); + } + catch(AMQPInvalidClassException e) + { + // TODO + // log here, but ignore - just can;t convert + } + } + props.setHeaders(ft); + + } + } + + + + + + + + return props; + } +} 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 5b6150f964..5300bad613 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 @@ -26,17 +26,15 @@ */
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.server.message.MessageContentSource;
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);
@@ -55,7 +53,7 @@ public interface ProtocolOutputConverter byte getProtocolMajorVersion();
- void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, Iterator<AMQDataBlock> bodyFrameIterator, int channelId, int replyCode, AMQShortString replyText)
+ void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource msgContent, 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 304d543609..2cebec373e 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 @@ -27,27 +27,34 @@ 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.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.output.HeaderPropertiesConverter;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.DeliveryProperties;
-import java.util.Iterator;
+import java.nio.ByteBuffer;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
- private final MethodRegistry _methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+
+ private static final ProtocolVersionMethodConverter PROTOCOL_CONVERTER =
+ METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
{
return new Factory()
{
-
+
public ProtocolOutputConverter newInstance(AMQProtocolSession session)
{
return new ProtocolOutputConverterImpl(session);
@@ -71,67 +78,44 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- 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 int bodyCount = messageHandle.getBodyCount();
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ }
- if(bodyCount == 0)
+ private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
+ throws AMQException
+ {
+ if(entry.getMessage() instanceof AMQMessage)
{
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
-
- writeFrame(compositeBlock);
+ return ((AMQMessage)entry.getMessage()).getContentHeaderBody();
}
else
{
-
-
- //
- // 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(0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
+ final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
+ ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
+ return chb;
}
-
-
}
public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
+ AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ }
- final AMQMessage message = (AMQMessage) entry.getMessage();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody chb, int channelId, AMQDataBlock deliver)
+ throws AMQException
+ {
- AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, chb);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
- final int bodyCount = messageHandle.getBodyCount();
- if(bodyCount == 0)
+ final int bodySize = (int) message.getSize();
+ if(bodySize == 0)
{
SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
contentHeader);
@@ -139,48 +123,63 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
else
{
+ int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ ByteBuffer buf = ByteBuffer.allocate(capacity);
- //
- // 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(0);
+ int writtenSize = 0;
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf));
AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
writeFrame(compositeBlock);
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
+ while(writtenSize < bodySize)
{
- cb = messageHandle.getContentChunk(i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ buf = java.nio.ByteBuffer.allocate(capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
}
-
}
-
-
}
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 AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+
+ final boolean isRedelivered = entry.isRedelivered();
BasicDeliverBody deliverBody =
- _methodRegistry.createBasicDeliverBody(consumerTag,
+ METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
deliveryTag,
- entry.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey());
+ isRedelivered,
+ exchangeName,
+ routingKey);
+
AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
@@ -190,14 +189,31 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter 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 AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+
+ final boolean isRedelivered = entry.isRedelivered();
BasicGetOkBody getOkBody =
- _methodRegistry.createBasicGetOkBody(deliveryTag,
- entry.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
+ METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
+ isRedelivered,
+ exchangeName,
+ routingKey,
queueSize);
AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
@@ -217,7 +233,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
{
BasicReturnBody basicReturnBody =
- _methodRegistry.createBasicReturnBody(replyCode,
+ METHOD_REGISTRY.createBasicReturnBody(replyCode,
replyText,
messagePublishInfo.getExchange(),
messagePublishInfo.getRoutingKey());
@@ -228,7 +244,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeReturn(MessagePublishInfo messagePublishInfo,
ContentHeaderBody header,
- Iterator<AMQDataBlock> bodyFrameIterator,
+ MessageContentSource content,
int channelId,
int replyCode,
AMQShortString replyText)
@@ -237,36 +253,8 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- header);
+ writeMessageDelivery(content, header, channelId, returnFrame);
-
- //
- // 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.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
}
@@ -278,7 +266,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
{
- BasicCancelOkBody basicCancelOkBody = _methodRegistry.createBasicCancelOkBody(consumerTag);
+ BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.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 6363be3dfc..319b5cc7bd 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 @@ -1,6 +1,6 @@ package org.apache.qpid.server.output.amqp0_9;
/*
- *
+ *
* 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,39 +8,41 @@ package org.apache.qpid.server.output.amqp0_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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
+ *
*/
import org.apache.mina.common.ByteBuffer;
-import java.util.Iterator;
-
import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.output.HeaderPropertiesConverter;
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.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.amqp_0_9.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
+ private static final ProtocolVersionMethodConverter
+ PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
@@ -71,16 +73,43 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQMessage message = (AMQMessage) entry.getMessage();
- AMQBody deliverBody = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
- final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
+ AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag);
+ writeMessageDelivery(entry, channelId, deliverBody);
+ }
+
+
+ private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
+ throws AMQException
+ {
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ return ((AMQMessage)entry.getMessage()).getContentHeaderBody();
+ }
+ else
+ {
+ final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
+ ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
+ return chb;
+ }
+ }
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody)
+ throws AMQException
+ {
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody);
+ }
+
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody)
+ throws AMQException
+ {
- final int bodyCount = messageHandle.getBodyCount();
- if(bodyCount == 0)
+ int bodySize = (int) message.getSize();
+
+ if(bodySize == 0)
{
SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
contentHeaderBody);
@@ -89,36 +118,37 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter }
else
{
+ int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
+
+
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
+ int writtenSize = 0;
- //
- // 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(0);
- AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
- CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
+ CompositeAMQBodyBlock
+ compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
writeFrame(compositeBlock);
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
+ while(writtenSize < bodySize)
{
- cb = messageHandle.getContentChunk(i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
+ buf = java.nio.ByteBuffer.allocate(capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
+ }
}
-
}
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
-
+
AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
contentHeaderBody);
return contentHeader;
@@ -127,63 +157,36 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
- final AMQMessage message = (AMQMessage) entry.getMessage();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
+ writeMessageDelivery(entry, channelId, deliver);
+ }
- AMQFrame deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
+ private AMQBody createEncodedDeliverBody(QueueEntry entry,
+ final long deliveryTag,
+ final AMQShortString consumerTag)
+ throws AMQException
+ {
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
- final int bodyCount = messageHandle.getBodyCount();
- if(bodyCount == 0)
+ if(entry.getMessage() instanceof AMQMessage)
{
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
}
else
{
-
-
- //
- // 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(0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
}
-
- }
-
-
- 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 = entry.isRedelivered();
- final AMQShortString exchangeName = pb.getExchange();
- final AMQShortString routingKey = pb.getRoutingKey();
final AMQBody returnBlock = new AMQBody()
{
@@ -236,21 +239,37 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return returnBlock;
}
- private AMQFrame createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
+ private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
throws AMQException
{
- final AMQMessage message = (AMQMessage) entry.getMessage();
- final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+
+ final boolean isRedelivered = entry.isRedelivered();
BasicGetOkBody getOkBody =
METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
- entry.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
+ isRedelivered,
+ exchangeName,
+ routingKey,
queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
- return getOkFrame;
+ return getOkBody;
}
public byte getProtocolMinorVersion()
@@ -263,7 +282,9 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
+ int replyCode,
+ AMQShortString replyText) throws AMQException
{
BasicReturnBody basicReturnBody =
@@ -271,47 +292,18 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter replyText,
messagePublishInfo.getExchange(),
messagePublishInfo.getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
- return returnFrame;
+
+ return basicReturnBody;
}
- public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, Iterator<AMQDataBlock> bodyFrameIterator, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
-
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, header);
+ AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
-
- //
- // 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.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
+ writeMessageDelivery(message, header, channelId, returnFrame);
}
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 5895a22f1a..f9641d6eab 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 @@ -83,8 +83,8 @@ import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.Sender; @@ -139,7 +139,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private Principal _authorizedID; private MethodDispatcher _dispatcher; private ProtocolSessionIdentifier _sessionIdentifier; - + // Create a simple ID that increments for ever new Session private final long _sessionID = idGenerator.getAndIncrement(); @@ -152,11 +152,12 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private long _writtenBytes; private long _readBytes; - + private Job _readJob; private Job _writeJob; private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance(); + private long _maxFrameSize; public ManagedObject getManagedObject() { @@ -167,7 +168,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { _stateManager = new AMQStateManager(virtualHostRegistry, this); _networkDriver = driver; - + _codecFactory = new AMQCodecFactory(true, this); _poolReference.acquireExecutorService(); _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true); @@ -178,17 +179,9 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } - private AMQProtocolSessionMBean createMBean() throws AMQException + private AMQProtocolSessionMBean createMBean() throws JMException { - try - { - return new AMQProtocolSessionMBean(this); - } - catch (JMException ex) - { - _logger.error("AMQProtocolSession MBean creation has failed ", ex); - throw new AMQException("AMQProtocolSession MBean creation has failed ", ex); - } + return new AMQProtocolSessionMBean(this); } public long getSessionID() @@ -200,7 +193,17 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { return _actor; } - + + public void setMaxFrameSize(long frameMax) + { + _maxFrameSize = frameMax; + } + + public long getMaxFrameSize() + { + return _maxFrameSize; + } + public void received(final ByteBuffer msg) { _lastIoTime = System.currentTimeMillis(); @@ -290,7 +293,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol else { // The channel has been told to close, we don't process any more frames until - // it's closed. + // it's closed. return; } } @@ -545,7 +548,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private void checkForNotification() { int channelsCount = _channelMap.size(); - if (channelsCount >= _maxNoOfChannels) + if (_managedObject != null && channelsCount >= _maxNoOfChannels) { _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); } @@ -560,7 +563,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { _maxNoOfChannels = value; } - + public void commitTransactions(AMQChannel channel) throws AMQException { if ((channel != null) && channel.isTransactional()) @@ -576,7 +579,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol channel.rollback(); } } - + /** * Close a specific channel. This will remove any resources used by the channel, including: <ul><li>any queue * subscriptions (this may in turn remove queues if they are auto delete</li> </ul> @@ -697,7 +700,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { task.doTask(this); } - + _closed = true; _poolReference.releaseExecutorService(); CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002()); @@ -775,7 +778,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol throw new IllegalArgumentException("Unsupported socket address class: " + address); } } - + public SaslServer getSaslServer() { return _saslServer; @@ -865,8 +868,15 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _virtualHost.getConnectionRegistry().registerConnection(this); - _managedObject = createMBean(); - _managedObject.register(); + try + { + _managedObject = createMBean(); + _managedObject.register(); + } + catch (JMException e) + { + _logger.error(e); + } } public void addSessionCloseTask(Task task) @@ -878,7 +888,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { _taskList.remove(task); } - + public ProtocolOutputConverter getProtocolOutputConverter() { return _protocolOutputConverter; @@ -905,7 +915,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol public SocketAddress getRemoteAddress() { return _networkDriver.getRemoteAddress(); - } + } public SocketAddress getLocalAddress() { @@ -941,7 +951,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol public void setNetworkDriver(NetworkDriver driver) { - _networkDriver = driver; + _networkDriver = driver; } public void writerIdle() @@ -970,7 +980,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion()); ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0); - + writeFrame(closeBody.generateFrame(0)); _networkDriver.close(); @@ -986,7 +996,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { // Do nothing } - + public long getReadBytes() { return _readBytes; @@ -1006,7 +1016,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { return _sessionIdentifier; } - + public String getClientVersion() { return (_clientVersion == null) ? null : _clientVersion.toString(); @@ -1024,5 +1034,5 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } } } - + } 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 924e395521..54b38a7f26 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 @@ -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 @@ -28,8 +28,7 @@ import org.apache.qpid.framing.*; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.PrincipalHolder; -import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -44,6 +43,10 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin LogActor getLogActor(); + void setMaxFrameSize(long frameMax); + + long getMaxFrameSize(); + public static final class ProtocolSessionIdentifier { private final Object _sessionIdentifier; @@ -227,5 +230,5 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin List<AMQChannel> getChannels(); void closeIfLingeringClosedChannels(); - + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ProtocolEngineFactory_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java index 4c84b47d43..7c3adf8b7d 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ProtocolEngineFactory_0_10.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java @@ -18,22 +18,20 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.Connection; import org.apache.qpid.transport.ConnectionDelegate; -import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.server.transport.ServerConnection; +import org.apache.qpid.server.protocol.ProtocolEngine_0_10; public class ProtocolEngineFactory_0_10 implements ProtocolEngineFactory { private ConnectionDelegate _delegate; - public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; - - public ProtocolEngineFactory_0_10(ConnectionDelegate delegate) { _delegate = delegate; @@ -41,10 +39,8 @@ public class ProtocolEngineFactory_0_10 implements ProtocolEngineFactory public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver) { - Connection conn = new Connection(); + Connection conn = new ServerConnection(); conn.setConnectionDelegate(_delegate); - Disassembler dis = new Disassembler(networkDriver, MAX_FRAME_SIZE); - conn.setSender(dis); - return new ProtocolEngine_0_10(conn, networkDriver); //To change body of implemented methods use File | Settings | File Templates. + return new ProtocolEngine_0_10(conn, networkDriver); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ProtocolEngine_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java index 7ddd3da1a6..e3cd3acd98 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ProtocolEngine_0_10.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java @@ -18,31 +18,38 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.Connection; import org.apache.qpid.transport.network.InputHandler; import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.Disassembler; import java.net.SocketAddress; public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine { + public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; + private NetworkDriver _networkDriver; private long _readBytes; private long _writtenBytes; + private Connection _connection; public ProtocolEngine_0_10(Connection conn, NetworkDriver networkDriver) { super(new Assembler(conn)); + _connection = conn; _networkDriver = networkDriver; } public void setNetworkDriver(NetworkDriver driver) { _networkDriver = driver; + Disassembler dis = new Disassembler(driver, MAX_FRAME_SIZE); + _connection.setSender(dis); } public SocketAddress getRemoteAddress() 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 deleted file mode 100644 index 5798dca079..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java +++ /dev/null @@ -1,60 +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.queue; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; - -/** - * A pluggable way of getting message data. Implementations can provide intelligent caching for example or - * even no caching at all to minimise the broker memory footprint. - */ -public interface AMQMessageHandle extends BodyContentHolder -{ - ContentHeaderBody getContentHeaderBody() throws AMQException; - - /** - * - * @return the messageId for the message associated with this handle - */ - Long getMessageId(); - - - /** - * @return the size of the body - */ - long getBodySize() throws AMQException; - - void addContentBodyFrame(ContentChunk contentBody, boolean isLastContentBody) throws AMQException; - - MessagePublishInfo getMessagePublishInfo() throws AMQException; - - boolean isPersistent(); - - MessageMetaData setPublishAndContentHeaderBody(MessagePublishInfo messagePublishInfo, - ContentHeaderBody contentHeaderBody); - - 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 37e8029796..51fbff76f4 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 @@ -24,7 +24,6 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.subscription.SubscriptionList; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.AMQException; public class AMQPriorityQueue extends SimpleAMQQueue { @@ -34,7 +33,6 @@ public class AMQPriorityQueue extends SimpleAMQQueue final boolean autoDelete, final VirtualHost virtualHost, int priorities) - throws AMQException { super(name, durable, owner, autoDelete, virtualHost, new PriorityQueueList.Factory(priorities)); } @@ -43,7 +41,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue boolean durable, String owner, boolean autoDelete, - VirtualHost virtualHost, int priorities) throws AMQException + VirtualHost virtualHost, int priorities) { this(new AMQShortString(queueName), durable, new AMQShortString(owner),autoDelete,virtualHost,priorities); } @@ -70,7 +68,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue 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)) + if(QueueContext._releasedUpdater.compareAndSet(context,released,entry)) { break; } 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 95ca18c778..c9d20c53e4 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 @@ -22,16 +22,16 @@ package org.apache.qpid.server.queue; import org.apache.qpid.server.management.Managable; import org.apache.qpid.server.management.ManagedObject; -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.exchange.ExchangeReferrer; import org.apache.qpid.server.virtualhost.VirtualHost; 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.ExchangeReferrer; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.security.PrincipalHolder; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.AMQException; @@ -40,7 +40,7 @@ import java.util.List; import java.util.Set; import java.util.Map; -public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer +public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource { @@ -51,6 +51,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer AMQShortString getName(); + void setNoLocal(boolean b); + boolean isDurable(); boolean isAutoDelete(); @@ -114,7 +116,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException; - + void addQueueDeleteTask(final Task task); @@ -128,11 +130,11 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer List<Long> getMessagesOnTheQueue(int num, int offest); QueueEntry getMessageOnTheQueue(long messageId); - + /** * Returns a list of QueEntries from a given range of queue positions, eg messages 5 to 10 on the queue. - * - * The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1. + * + * The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1. * Using 0 in the 'to' field will return an empty list regardless of the 'from' value. * @param fromPosition * @param toPosition @@ -142,9 +144,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, - StoreContext storeContext); + ServerTransaction transaction); - void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext); + void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction transaction); void removeMessagesFromQueue(long fromMessageId, long toMessageId); @@ -265,6 +267,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer } void configure(QueueConfiguration config); - + ManagedObject getManagedObject(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index 71ad05ce25..d4a5b3258b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -27,7 +27,6 @@ import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Map; -import java.util.HashMap; public class AMQQueueFactory @@ -130,7 +129,6 @@ public class AMQQueueFactory AMQShortString owner, boolean autoDelete, VirtualHost virtualHost, final FieldTable arguments) - throws AMQException { final int priorities = arguments == null ? 1 : arguments.containsKey(X_QPID_PRIORITIES) ? arguments.getInteger(X_QPID_PRIORITIES) : 1; 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 795da14163..8e5310bc16 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 @@ -22,21 +22,19 @@ package org.apache.qpid.server.queue; import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.CommonContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; import org.apache.qpid.server.management.AMQManagedObject; import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.LocalTransaction; import javax.management.JMException; import javax.management.MBeanNotificationInfo; @@ -125,7 +123,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content - _msgContentType = new CompositeType("Message Content", "AMQ Message Content", + _msgContentType = new CompositeType("Message Content", "AMQ Message Content", VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, VIEW_MSG_CONTENT_COMPOSITE_ITEM_DESCRIPTIONS, _msgContentAttributeTypes); @@ -135,9 +133,9 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered _msgAttributeTypes[4] = SimpleType.LONG; // For queue position - _messageDataType = new CompositeType("Message", "AMQ Message", VIEW_MSGS_COMPOSITE_ITEM_NAMES, + _messageDataType = new CompositeType("Message", "AMQ Message", VIEW_MSGS_COMPOSITE_ITEM_NAMES, VIEW_MSGS_COMPOSITE_ITEM_DESCRIPTIONS, _msgAttributeTypes); - _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, + _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, VIEW_MSGS_TABULAR_UNIQUE_INDEX); } @@ -299,7 +297,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que /** * Clears the queue of non-acquired messages - * + * * @return the number of messages deleted * @see AMQQueue#clearQueue */ @@ -321,60 +319,40 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que } ServerMessage serverMsg = entry.getMessage(); - - if(serverMsg instanceof AMQMessage) - { - AMQMessage msg = (AMQMessage) serverMsg; - // get message content - Iterator<ContentChunk> cBodies = msg.getContentBodyIterator(); - List<Byte> msgContent = new ArrayList<Byte>(); - while (cBodies.hasNext()) - { - ContentChunk body = cBodies.next(); - if (body.getSize() != 0) - { - if (body.getSize() != 0) - { - ByteBuffer slice = body.getData().slice(); - for (int j = 0; j < slice.limit(); j++) - { - msgContent.add(slice.get()); - } - } - } - } + final int bodySize = (int) serverMsg.getSize(); - try - { - // Create header attributes list - CommonContentHeaderProperties headerProperties = - (CommonContentHeaderProperties) msg.getContentHeaderBody().properties; - String mimeType = null, encoding = null; - if (headerProperties != null) - { - AMQShortString mimeTypeShortSting = headerProperties.getContentType(); - mimeType = (mimeTypeShortSting == null) ? null : mimeTypeShortSting.toString(); - encoding = (headerProperties.getEncoding() == null) ? "" : headerProperties.getEncoding().toString(); - } + List<Byte> msgContent = new ArrayList<Byte>(); - Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) }; + java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(bodySize); + int position = 0; - return new CompositeDataSupport(_msgContentType, VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, itemValues); - } - catch (AMQException e) + while(position < bodySize) + { + position += serverMsg.getContent(buf, position); + buf.flip(); + for(int i = 0; i < buf.limit(); i++) { - JMException jme = new JMException("Error creating header attributes list: " + e); - jme.initCause(e); - throw jme; + msgContent.add(buf.get(i)); } - + buf.clear(); } - else + + AMQMessageHeader header = serverMsg.getMessageHeader(); + + String mimeType = null, encoding = null; + if (header != null) { - // TODO 0-10 Messages for MBean - return null; + mimeType = header.getMimeType(); + + encoding = header.getEncoding(); } + + + Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) }; + + return new CompositeDataSupport(_msgContentType, VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, itemValues); + } /** @@ -386,8 +364,8 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que { return viewMessages((long)beginIndex,(long)endIndex); } - - + + /** * Returns the header contents of the messages stored in this queue in tabular form. * @param startPosition The queue position of the first message to be viewed @@ -400,7 +378,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition + "\n\"From Index\" should be greater than 0 and less than \"To Index\""); } - + if ((endPosition - startPosition) > Integer.MAX_VALUE) { throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size"); @@ -489,7 +467,9 @@ 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, new StoreContext()); + ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog()); + _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn); + txn.commit(); } /** @@ -507,7 +487,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que _queue.removeMessagesFromQueue(fromMessageId, toMessageId); } - + /** * @see ManagedQueue#copyMessages * @param fromMessageId @@ -522,9 +502,15 @@ 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, new StoreContext()); + ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog()); + + _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn); + + txn.commit(); + + } - + /** * returns Notifications sent by this MBean. */ diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyContentIterator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyContentIterator.java deleted file mode 100755 index 1483177855..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyContentIterator.java +++ /dev/null @@ -1,75 +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.queue; - -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.AMQException; -import org.apache.log4j.Logger; - -import java.util.Iterator; - - -class BodyContentIterator implements Iterator<ContentChunk> -{ - private static final Logger _log = Logger.getLogger(BodyContentIterator.class); - - - private AMQMessageHandle _messageHandle; - private int _index = -1; - - - public BodyContentIterator(AMQMessageHandle messageHandle) - { - _messageHandle = messageHandle; - } - - - public boolean hasNext() - { - try - { - return _index < (_messageHandle.getBodyCount() - 1); - } - catch (AMQException e) - { - _log.error("Error getting body count: " + e, e); - - return false; - } - } - - public ContentChunk next() - { - try - { - return _messageHandle.getContentChunk(++_index); - } - catch (AMQException e) - { - throw new RuntimeException("Error getting content body: " + e, e); - } - } - - public void remove() - { - throw new UnsupportedOperationException(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyFrameIterator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyFrameIterator.java deleted file mode 100755 index fd9cfe45bb..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyFrameIterator.java +++ /dev/null @@ -1,94 +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.queue; - -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQBody; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.AMQException; -import org.apache.log4j.Logger; - -import java.util.Iterator; - - -public class BodyFrameIterator implements Iterator<AMQDataBlock> -{ - private static final Logger _log = Logger.getLogger(BodyFrameIterator.class); - - - private int _channel; - - private int _index = -1; - private AMQProtocolSession _protocolSession; - private BodyContentHolder _bodyContentHolder; - - public BodyFrameIterator(AMQProtocolSession protocolSession, int channel, BodyContentHolder messageHandle) - { - _channel = channel; - _protocolSession = protocolSession; - _bodyContentHolder = messageHandle; - } - - public boolean hasNext() - { - try - { - return _index < (_bodyContentHolder.getBodyCount() - 1); - } - catch (AMQException e) - { - _log.error("Unable to get body count: " + e, e); - - return false; - } - } - - public AMQDataBlock next() - { - try - { - - AMQBody cb = - getProtocolVersionMethodConverter().convertToBody(_bodyContentHolder.getContentChunk( - ++_index)); - - return new AMQFrame(_channel, cb); - } - catch (AMQException e) - { - // have no choice but to throw a runtime exception - throw new RuntimeException("Error getting content body: " + e, e); - } - - } - - private ProtocolVersionMethodConverter getProtocolVersionMethodConverter() - { - return _protocolSession.getMethodRegistry().getProtocolVersionMethodConverter(); - } - - public void remove() - { - throw new UnsupportedOperationException(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java index 0f33f5d8ee..aea485e749 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.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 @@ -44,12 +44,12 @@ public class DefaultQueueRegistry implements QueueRegistry return _virtualHost; } - public void registerQueue(AMQQueue queue) throws AMQException + public void registerQueue(AMQQueue queue) { _queueMap.put(queue.getName(), queue); } - public void unregisterQueue(AMQShortString name) throws AMQException + public void unregisterQueue(AMQShortString name) { _queueMap.remove(name); } 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 deleted file mode 100644 index bf0e803132..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java +++ /dev/null @@ -1,143 +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.queue; - -import java.util.List; -import java.util.Collections; -import java.util.ArrayList; - -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; - -/** - */ -public class InMemoryMessageHandle implements AMQMessageHandle -{ - - private ContentHeaderBody _contentHeaderBody; - - private MessagePublishInfo _messagePublishInfo; - - private List<ContentChunk> _contentBodies; - - private long _arrivalTime; - - private final Long _messageId; - - public InMemoryMessageHandle(final Long messageId) - { - _messageId = messageId; - } - - public ContentHeaderBody getContentHeaderBody() throws AMQException - { - return _contentHeaderBody; - } - - public Long getMessageId() - { - return _messageId; - } - - public int getBodyCount() - { - return _contentBodies.size(); - } - - public long getBodySize() throws AMQException - { - return getContentHeaderBody().bodySize; - } - - public ContentChunk getContentChunk(int index) throws AMQException, IllegalArgumentException - { - if (index > _contentBodies.size() - 1) - { - throw new IllegalArgumentException("Index " + index + " out of valid range 0 to " + - (_contentBodies.size() - 1)); - } - return _contentBodies.get(index); - } - - public void addContentBodyFrame(ContentChunk contentBody, boolean isLastContentBody) - throws AMQException - { - if(_contentBodies == null) - { - if(isLastContentBody) - { - _contentBodies = Collections.singletonList(contentBody); - } - else - { - _contentBodies = new ArrayList<ContentChunk>(); - _contentBodies.add(contentBody); - } - } - else - { - _contentBodies.add(contentBody); - } - } - - public MessagePublishInfo getMessagePublishInfo() throws AMQException - { - return _messagePublishInfo; - } - - public boolean isPersistent() - { - return false; - } - - /** - * This is called when all the content has been received. - * @param messagePublishInfo - * @param contentHeaderBody - * @throws AMQException - */ - public MessageMetaData setPublishAndContentHeaderBody(MessagePublishInfo messagePublishInfo, - ContentHeaderBody contentHeaderBody) - { - _messagePublishInfo = messagePublishInfo; - _contentHeaderBody = contentHeaderBody; - if(contentHeaderBody.bodySize == 0) - { - _contentBodies = Collections.EMPTY_LIST; - } - _arrivalTime = System.currentTimeMillis(); - MessageMetaData mmd = new MessageMetaData(messagePublishInfo, contentHeaderBody, _contentBodies == null ? 0 : _contentBodies.size(), _arrivalTime); - return mmd; - } - - public void removeMessage() throws AMQException - { - // NO OP - } - - public long getArrivalTime() - { - return _arrivalTime; - } - -} 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 ac82e1f2b3..da4173d5d3 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,21 +25,22 @@ 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.protocol.AMQProtocolSession; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.registry.ApplicationRegistry; 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.EnqueableMessage; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.AMQException; import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; +import java.nio.ByteBuffer; -public class IncomingMessage implements Filterable, InboundMessage, EnqueableMessage, BodyContentHolder +public class IncomingMessage implements Filterable, InboundMessage, EnqueableMessage, MessageContentSource { /** Used for debugging purposes. */ @@ -51,9 +52,6 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes private final MessagePublishInfo _messagePublishInfo; private ContentHeaderBody _contentHeaderBody; - private AMQMessageHandle _messageHandle; - private final Long _messageId; - /** * Keeps a track of how many bytes we have received in body frames @@ -70,25 +68,29 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes private long _expiration; private Exchange _exchange; - private AMQMessageHeader _messageHeader; private int _receivedChunkCount = 0; private List<ContentChunk> _contentChunks = new ArrayList<ContentChunk>(); + // we keep both the original meta data object and the store reference to it just in case the + // store would otherwise flow it to disk + + private MessageMetaData _messageMetaData; + + private StoredMessage<MessageMetaData> _storedMessageHandle; + - public IncomingMessage(final Long messageId, - final MessagePublishInfo info, - final AMQProtocolSession publisher) + public IncomingMessage( + final MessagePublishInfo info + ) { - _messageId = messageId; _messagePublishInfo = info; } public void setContentHeaderBody(final ContentHeaderBody contentHeaderBody) throws AMQException { _contentHeaderBody = contentHeaderBody; - _messageHeader = new ContentHeaderBodyAdapter(contentHeaderBody); } public void setExpiration() @@ -122,11 +124,10 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes } - public MessageMetaData routingComplete(final MessageStore store, - final MessageHandleFactory factory) throws AMQException + public MessageMetaData headersReceived() { - _messageHandle = factory.createMessageHandle(_messageId, store, isPersistent()); - return _messageHandle.setPublishAndContentHeaderBody(_messagePublishInfo, _contentHeaderBody); + _messageMetaData = new MessageMetaData(_messagePublishInfo, _contentHeaderBody, 0); + return _messageMetaData; } @@ -135,20 +136,15 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes return _destinationQueues; } - - public AMQMessageHandle getMessageHandle() - { - return _messageHandle; - } - - public int addContentBodyFrame(final ContentChunk contentChunk) throws AMQException { - + _storedMessageHandle.addContent((int)_bodyLengthReceived, contentChunk.getData().buf()); _bodyLengthReceived += contentChunk.getSize(); _contentChunks.add(contentChunk); - _messageHandle.addContentBodyFrame(contentChunk, allContentReceived()); + + + return _receivedChunkCount++; } @@ -192,7 +188,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes public AMQMessageHeader getMessageHeader() { - return _messageHeader; + return _messageMetaData.getMessageHeader(); } public boolean isPersistent() @@ -207,6 +203,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes return false; } + public long getSize() { return getContentHeader().bodySize; @@ -214,7 +211,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes public Long getMessageNumber() { - return _messageId; + return _storedMessageHandle.getMessageNumber(); } public void setExchange(final Exchange e) @@ -258,4 +255,46 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes { return _contentChunks.get(index); } + + + public int getContent(ByteBuffer buf, int offset) + { + int pos = 0; + int written = 0; + for(ContentChunk cb : _contentChunks) + { + ByteBuffer data = cb.getData().buf(); + if(offset+written >= pos && offset < pos + data.limit()) + { + ByteBuffer src = data.duplicate(); + src.position(offset+written - pos); + src = src.slice(); + + if(buf.remaining() < src.limit()) + { + src.limit(buf.remaining()); + } + int count = src.limit(); + buf.put(src); + written += count; + if(buf.remaining() == 0) + { + break; + } + } + pos+=data.limit(); + } + return written; + + } + + public void setStoredMessage(StoredMessage<MessageMetaData> storedMessageHandle) + { + _storedMessageHandle = storedMessageHandle; + } + + public StoredMessage<MessageMetaData> getStoredMessage() + { + return _storedMessageHandle; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java deleted file mode 100644 index 0b214ca336..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java +++ /dev/null @@ -1,46 +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.queue; - -import org.apache.qpid.server.store.MessageStore; - -/** - * Constructs a message handle based on the publish body, the content header and the queue to which the message - * has been routed. - * - * @author Robert Greig (robert.j.greig@jpmorgan.com) - */ -public class MessageHandleFactory -{ - - public AMQMessageHandle createMessageHandle(Long messageId, MessageStore store, boolean persistent) - { - // just hardcoded for now - if (persistent) - { - return new WeakReferenceMessageHandle(messageId, store); - } - else - { - return new InMemoryMessageHandle(messageId); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java deleted file mode 100644 index 6118a4c11f..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java +++ /dev/null @@ -1,92 +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.queue; - -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; - -/** - * Encapsulates a publish body and a content header. In the context of the message store these are treated as a - * single unit. - */ -public class MessageMetaData -{ - private MessagePublishInfo _messagePublishInfo; - - private ContentHeaderBody _contentHeaderBody; - - private int _contentChunkCount; - - private long _arrivalTime; - - public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount) - { - this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis()); - } - - public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime) - { - _contentHeaderBody = contentHeaderBody; - _messagePublishInfo = publishBody; - _contentChunkCount = contentChunkCount; - _arrivalTime = arrivalTime; - } - - public int getContentChunkCount() - { - return _contentChunkCount; - } - - public void setContentChunkCount(int contentChunkCount) - { - _contentChunkCount = contentChunkCount; - } - - public ContentHeaderBody getContentHeaderBody() - { - return _contentHeaderBody; - } - - public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) - { - _contentHeaderBody = contentHeaderBody; - } - - public MessagePublishInfo getMessagePublishInfo() - { - return _messagePublishInfo; - } - - public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo) - { - _messagePublishInfo = messagePublishInfo; - } - - public long getArrivalTime() - { - return _arrivalTime; - } - - public void setArrivalTime(long arrivalTime) - { - _arrivalTime = arrivalTime; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java deleted file mode 100644 index 97601048ee..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java +++ /dev/null @@ -1,48 +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.queue; - -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.RequiredDeliveryException; -import org.apache.qpid.server.message.ServerMessage; - -/** - * NoConsumersException is a {@link RequiredDeliveryException} that represents the failure case where an immediate - * message cannot be delivered because there are presently no consumers for the message. The AMQP status code, 313, is - * always used to report this condition. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Represent failure to deliver a message that must be delivered. - * </table> - */ -public class NoConsumersException extends RequiredDeliveryException -{ - public NoConsumersException(ServerMessage message) - { - super("Immediate delivery is not possible.", message); - } - - public AMQConstant getReplyCode() - { - return AMQConstant.NO_CONSUMERS; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/UnauthorizedAccessException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java index 295cb266b9..825a85a89c 100644..100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/UnauthorizedAccessException.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java @@ -21,25 +21,29 @@ package org.apache.qpid.server.queue; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.RequiredDeliveryException; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -/** - * UnauthorizedAccessException is a {@link RequiredDeliveryException} that represents the failure case where a message - * is published with a user id different from the one used when creating the connection . - * The AMQP status code, 403, is always used to report this condition. - * - */ - -public class UnauthorizedAccessException extends RequiredDeliveryException +final class QueueContext implements AMQQueue.Context { - public UnauthorizedAccessException(String msg, AMQMessage amqMessage) + volatile QueueEntry _lastSeenEntry; + volatile QueueEntry _releasedEntry; + + static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> + _lastSeenUpdater = + AtomicReferenceFieldUpdater.newUpdater + (QueueContext.class, QueueEntry.class, "_lastSeenEntry"); + static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> + _releasedUpdater = + AtomicReferenceFieldUpdater.newUpdater + (QueueContext.class, QueueEntry.class, "_releasedEntry"); + + public QueueContext(QueueEntry head) { - super(msg, amqMessage); + _lastSeenEntry = head; } - public AMQConstant getReplyCode() + public QueueEntry getLastSeenEntry() { - return AMQConstant.ACCESS_REFUSED; + return _lastSeenEntry; } } 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 6a303fd156..a50e2b561d 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 @@ -180,7 +180,7 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable boolean immediateAndNotDelivered(); - void setRedelivered(boolean b); + void setRedelivered(); boolean isRedelivered(); 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 74c034d305..5873e8f566 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 @@ -27,12 +27,10 @@ import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.log4j.Logger; -import java.util.Set; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.CopyOnWriteArraySet; @@ -80,8 +78,11 @@ public class QueueEntryImpl implements QueueEntry private volatile long _entryId; volatile QueueEntryImpl _next; - private boolean _deliveredToConsumer; - private boolean _redelivered; + + private static final int DELIVERED_TO_CONSUMER = 1; + private static final int REDELIVERED = 2; + + private volatile int _deliveryState; QueueEntryImpl(SimpleQueueEntryList queueEntryList) @@ -94,6 +95,7 @@ public class QueueEntryImpl implements QueueEntry public QueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message, final long entryId) { _queueEntryList = queueEntryList; + _message = message == null ? null : message.newReference(); _entryIdUpdater.set(this, entryId); @@ -132,7 +134,7 @@ public class QueueEntryImpl implements QueueEntry public boolean getDeliveredToConsumer() { - return _deliveredToConsumer; + return (_deliveryState & DELIVERED_TO_CONSUMER) != 0; } public boolean expired() throws AMQException @@ -194,9 +196,9 @@ public class QueueEntryImpl implements QueueEntry public boolean acquire(Subscription sub) { final boolean acquired = acquire(sub.getOwningState()); - if(acquired && !_deliveredToConsumer) + if(acquired) { - _deliveredToConsumer = true; + _deliveryState |= DELIVERED_TO_CONSUMER; } return acquired; } @@ -259,9 +261,9 @@ public class QueueEntryImpl implements QueueEntry } - public boolean immediateAndNotDelivered() + public boolean immediateAndNotDelivered() { - return !_deliveredToConsumer && isImmediate(); + return !getDeliveredToConsumer() && isImmediate(); } private boolean isImmediate() @@ -270,9 +272,9 @@ public class QueueEntryImpl implements QueueEntry return message != null && message.isImmediate(); } - public void setRedelivered(boolean b) + public void setRedelivered() { - _redelivered = b; + _deliveryState |= REDELIVERED; } public AMQMessageHeader getMessageHeader() @@ -289,7 +291,7 @@ public class QueueEntryImpl implements QueueEntry public boolean isRedelivered() { - return _redelivered; + return (_deliveryState & REDELIVERED) != 0; } public Subscription getDeliveredSubscription() @@ -329,7 +331,7 @@ public class QueueEntryImpl implements QueueEntry } public boolean isRejectedBy(Subscription subscription) - { + { if (_rejectedBy != null) // We have subscriptions that rejected this message { @@ -410,9 +412,9 @@ public class QueueEntryImpl implements QueueEntry final ServerMessage message = getMessage(); if(rerouteQueues != null && rerouteQueues.size() != 0) { - Transaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); + ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); - txn.enqueue(rerouteQueues, message, new Transaction.Action() { + txn.enqueue(rerouteQueues, message, new ServerTransaction.Action() { public void postCommit() { try @@ -434,7 +436,7 @@ public class QueueEntryImpl implements QueueEntry } }); txn.dequeue(currentQueue,message, - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() { @@ -523,7 +525,7 @@ public class QueueEntryImpl implements QueueEntry if(state != DELETED_STATE && _stateUpdater.compareAndSet(this,state,DELETED_STATE)) { - _queueEntryList.advanceHead(); + _queueEntryList.advanceHead(); return true; } else diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java index b47182e750..a537e0c83f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.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 @@ -30,9 +30,9 @@ public interface QueueRegistry { VirtualHost getVirtualHost(); - void registerQueue(AMQQueue queue) throws AMQException; + void registerQueue(AMQQueue queue); - void unregisterQueue(AMQShortString name) throws AMQException; + void unregisterQueue(AMQShortString name); AMQQueue getQueue(AMQShortString name); 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 de74974d2d..a8ad52f6ee 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 @@ -19,13 +19,11 @@ import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.store.TransactionLog; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionList; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.QueueActor; import org.apache.qpid.server.logging.subjects.QueueLogSubject; @@ -33,7 +31,7 @@ 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.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; @@ -61,62 +59,40 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class); - private int unused; - - private PrincipalHolder _prinicpalHolder; - - - private Object _exclusiveOwner; - - private Exchange _alternateExchange; - - - static final class QueueContext implements Context - { - volatile QueueEntry _lastSeenEntry; - volatile QueueEntry _releasedEntry; - - public QueueContext(QueueEntry head) - { - _lastSeenEntry = head; - } - - public QueueEntry getLastSeenEntry() - { - return _lastSeenEntry; - } - } - - - static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> - _lastSeenUpdater = - AtomicReferenceFieldUpdater.newUpdater - (QueueContext.class, QueueEntry.class, "_lastSeenEntry"); - - static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> - _releasedUpdater = - AtomicReferenceFieldUpdater.newUpdater - (QueueContext.class, QueueEntry.class, "_releasedEntry"); + private final VirtualHost _virtualHost; private final AMQShortString _name; + private final String _resourceName; /** null means shared */ private final AMQShortString _owner; + private PrincipalHolder _prinicpalHolder; + + private Object _exclusiveOwner; + + private final boolean _durable; /** If true, this queue is deleted when the last subscriber is removed */ private final boolean _autoDelete; - private final VirtualHost _virtualHost; + private Exchange _alternateExchange; /** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */ private final ExchangeBindings _bindings = new ExchangeBindings(this); - private final AtomicBoolean _deleted = new AtomicBoolean(false); - private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>(); + protected final QueueEntryList _entries; + + protected final SubscriptionList _subscriptionList = new SubscriptionList(this); + + private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead()); + + private volatile Subscription _exclusiveSubscriber; + + private final AtomicInteger _atomicQueueCount = new AtomicInteger(0); @@ -124,18 +100,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private final AtomicInteger _activeSubscriberCount = new AtomicInteger(); - protected final SubscriptionList _subscriptionList = new SubscriptionList(this); - private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead()); + private final AtomicLong _totalMessagesReceived = new AtomicLong(); - private volatile Subscription _exclusiveSubscriber; - protected final QueueEntryList _entries; - private final AMQQueueMBean _managedObject; - private final Executor _asyncDelivery; - private final AtomicLong _totalMessagesReceived = new AtomicLong(); - - private final ConcurrentMap<AMQChannel, Boolean> _blockedChannels = new ConcurrentHashMap<AMQChannel, Boolean>(); /** max allowed size(KB) of a single message */ public long _maximumMessageSize = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageSize(); @@ -152,23 +120,37 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener /** the minimum interval between sending out consecutive alerts of the same type */ public long _minimumAlertRepeatGap = ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap(); - private static final int MAX_ASYNC_DELIVERIES = 10; + private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity(); + + private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity(); private final Set<NotificationCheck> _notificationChecks = EnumSet.noneOf(NotificationCheck.class); + + static final int MAX_ASYNC_DELIVERIES = 10; + + private final AtomicLong _stateChangeCount = new AtomicLong(Long.MIN_VALUE); private AtomicReference _asynchronousRunner = new AtomicReference(null); + private final Executor _asyncDelivery; private AtomicInteger _deliveredMessages = new AtomicInteger(); private AtomicBoolean _stopped = new AtomicBoolean(false); + + private final ConcurrentMap<AMQChannel, Boolean> _blockedChannels = new ConcurrentHashMap<AMQChannel, Boolean>(); + + private final AtomicBoolean _deleted = new AtomicBoolean(false); + private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>(); + + private LogSubject _logSubject; private LogActor _logActor; + private AMQQueueMBean _managedObject; + private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER"; + private boolean _nolocal; - private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity(); - private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity(); protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost) - throws AMQException { this(name, durable, owner, autoDelete, virtualHost, new SimpleQueueEntryList.Factory()); } @@ -179,7 +161,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener boolean autoDelete, VirtualHost virtualHost, QueueEntryListFactory entryListFactory) - throws AMQException { if (name == null) @@ -193,6 +174,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } _name = name; + _resourceName = String.valueOf(name); _durable = durable; _owner = owner; _autoDelete = autoDelete; @@ -231,7 +213,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } catch (JMException e) { - throw new AMQException("AMQQueue MBean creation has failed ", e); + _logger.error("AMQQueue MBean creation has failed ", e); } resetNotifications(); @@ -255,11 +237,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener // ------ Getters and Setters + public void execute(ReadWriteRunnable runnable) + { + _asyncDelivery.execute(runnable); + } + public AMQShortString getName() { return _name; } + public void setNoLocal(boolean nolocal) + { + _nolocal = nolocal; + } + public boolean isDurable() { return _durable; @@ -401,6 +393,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener if (!isDeleted()) { subscription.setQueue(this, exclusive); + subscription.setNoLocal(_nolocal); _subscriptionList.add(subscription); if (isDeleted()) { @@ -540,7 +533,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener deliverAsync(); } - _managedObject.checkForNotification(entry.getMessage()); + if(_managedObject != null) + { + _managedObject.checkForNotification(entry.getMessage()); + } return entry; } @@ -612,10 +608,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener QueueContext subContext = (QueueContext) sub.getQueueContext(); QueueEntry releasedEntry = subContext._releasedEntry; - _lastSeenUpdater.set(subContext, entry); + QueueContext._lastSeenUpdater.set(subContext, entry); if(releasedEntry == entry) { - _releasedUpdater.compareAndSet(subContext, releasedEntry, null); + QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null); } } @@ -629,7 +625,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener while((oldEntry = subContext._releasedEntry) == null || oldEntry.compareTo(entry) > 0) { - if(_releasedUpdater.compareAndSet(subContext, oldEntry, entry)) + if(QueueContext._releasedUpdater.compareAndSet(subContext, oldEntry, entry)) { break; } @@ -939,11 +935,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void moveMessagesToAnotherQueue(final long fromMessageId, final long toMessageId, String queueName, - StoreContext storeContext) + ServerTransaction txn) { - AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName)); - TransactionLog txnLog = getVirtualHost().getTransactionLog(); + final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName)); + List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() { @@ -962,62 +958,48 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } }); - try + + + // Move the messages in on the message store. + for (final QueueEntry entry : entries) { - txnLog.beginTran(storeContext); + final ServerMessage message = entry.getMessage(); + txn.enqueue(toQueue, message, + new ServerTransaction.Action() + { - // Move the messages in on the message store. - for (QueueEntry entry : entries) - { - ServerMessage message = entry.getMessage(); + public void postCommit() + { + try + { + toQueue.enqueue(message); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } - if (message.isPersistent() && toQueue.isDurable()) - { - txnLog.enqueueMessage(storeContext, toQueue, message.getMessageNumber()); - } - // dequeue does not decrement the refence count - entry.dequeue(); - } + public void onRollback() + { + entry.release(); + } + }); + txn.dequeue(this, message, + new ServerTransaction.Action() + { - // Commit and flush the move transcations. - try - { - txnLog.commitTran(storeContext); - } - catch (AMQException e) - { - throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e); - } - } - catch (AMQException e) - { - try - { - txnLog.abortTran(storeContext); - } - catch (AMQException rollbackEx) - { - _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx); - } - throw new RuntimeException(e); - } + public void postCommit() + { + entry.discard(); + } - try - { + public void onRollback() + { + + } + }); - for (QueueEntry entry : entries) - { - toQueue.enqueue(entry.getMessage()); - entry.delete(); - } - } - catch (MessageCleanupException e) - { - throw new RuntimeException(e); - } - catch (AMQException e) - { - throw new RuntimeException(e); } } @@ -1025,10 +1007,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void copyMessagesToAnotherQueue(final long fromMessageId, final long toMessageId, String queueName, - final StoreContext storeContext) + final ServerTransaction txn) { - AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName)); - TransactionLog txnLog = getVirtualHost().getTransactionLog(); + final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName)); List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() { @@ -1046,66 +1027,37 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } }); - try + + // Move the messages in on the message store. + for (QueueEntry entry : entries) { - txnLog.beginTran(storeContext); + final ServerMessage message = entry.getMessage(); - // Move the messages in on the message store. - for (QueueEntry entry : entries) + if (message.isPersistent() && toQueue.isDurable()) { - ServerMessage message = entry.getMessage(); - if (message.isPersistent() && toQueue.isDurable()) - { - - txnLog.enqueueMessage(storeContext, toQueue, message.getMessageNumber()); - - } - } + txn.enqueue(toQueue, message, new ServerTransaction.Action() + { + public void postCommit() + { + try + { + toQueue.enqueue(message); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } - // Commit and flush the move transcations. - try - { - txnLog.commitTran(storeContext); - } - catch (AMQException e) - { - throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e); - } - } - catch (AMQException e) - { - try - { - txnLog.abortTran(storeContext); - } - catch (AMQException rollbackEx) - { - _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx); - } - throw new RuntimeException(e); - } + public void onRollback() + { - try - { - for (QueueEntry entry : entries) - { + } + }); - ServerMessage message = entry.getMessage(); - if (message != null) - { - toQueue.enqueue(entry.getMessage()); - } } } - catch (MessageCleanupException e) - { - throw new RuntimeException(e); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } } @@ -1160,7 +1112,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener QueueEntryIterator queueListIterator = _entries.iterator(); long count = 0; - Transaction txn = new LocalTransaction(getVirtualHost().getTransactionLog()); + ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog()); while (queueListIterator.advance()) { @@ -1181,14 +1133,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private void dequeueEntry(final QueueEntry node) { - Transaction txn = new AutoCommitTransaction(getVirtualHost().getTransactionLog()); + ServerTransaction txn = new AutoCommitTransaction(getVirtualHost().getTransactionLog()); dequeueEntry(node, txn); } - private void dequeueEntry(final QueueEntry node, Transaction txn) + private void dequeueEntry(final QueueEntry node, ServerTransaction txn) { txn.dequeue(this, node.getMessage(), - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() @@ -1241,7 +1193,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } }); - Transaction txn = new LocalTransaction(getVirtualHost().getTransactionLog()); + ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog()); if(_alternateExchange != null) { @@ -1255,7 +1207,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener if(rerouteQueues != null & rerouteQueues.size() != 0) { txn.enqueue(rerouteQueues, entry.getMessage(), - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() @@ -1280,7 +1232,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } }); txn.dequeue(this, entry.getMessage(), - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() @@ -1308,7 +1260,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener if(message != null) { txn.dequeue(this, message, - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() @@ -1327,7 +1279,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener txn.commit(); - _managedObject.unregister(); + if(_managedObject!=null) + { + _managedObject.unregister(); + } for (Task task : _deleteTaskList) { @@ -1417,7 +1372,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void deliverAsync(Subscription sub) { - _asyncDelivery.execute(new SubFlushRunner(sub)); + SubFlushRunner flusher = (SubFlushRunner) sub.get(SUB_FLUSH_RUNNER); + if(flusher == null) + { + flusher = new SubFlushRunner(sub); + sub.set(SUB_FLUSH_RUNNER, flusher); + } + _asyncDelivery.execute(flusher); } @@ -1466,66 +1427,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } - private class SubFlushRunner implements ReadWriteRunnable - { - private final Subscription _sub; - - public SubFlushRunner(Subscription sub) - { - _sub = sub; - } - - public void run() - { - - String originalName = Thread.currentThread().getName(); - try{ - Thread.currentThread().setName("SubFlushRunner-"+_sub); - - boolean complete = false; - try - { - CurrentActor.set(_sub.getLogActor()); - complete = flushSubscription(_sub, new Long(MAX_ASYNC_DELIVERIES)); - - } - catch (AMQException e) - { - _logger.error(e); - } - finally - { - CurrentActor.remove(); - } - if (!complete && !_sub.isSuspended()) - { - _asyncDelivery.execute(this); - } - } - finally - { - Thread.currentThread().setName(originalName); - } - - } - - public boolean isRead() - { - return false; - } - - public boolean isWrite() - { - return true; - } - } - public void flushSubscription(Subscription sub) throws AMQException { flushSubscription(sub, Long.MAX_VALUE); } - public boolean flushSubscription(Subscription sub, Long iterations) throws AMQException + public boolean flushSubscription(Subscription sub, long iterations) throws AMQException { boolean atTail = false; @@ -1655,9 +1562,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } - if(_lastSeenUpdater.compareAndSet(context, lastSeen, node)) + if(QueueContext._lastSeenUpdater.compareAndSet(context, lastSeen, node)) { - _releasedUpdater.compareAndSet(context, releasedNode, null); + QueueContext._releasedUpdater.compareAndSet(context, releasedNode, null); } lastSeen = context._lastSeenEntry; @@ -1774,7 +1681,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } else { - _managedObject.checkForNotification(node.getMessage()); + if(_managedObject!=null) + { + _managedObject.checkForNotification(node.getMessage()); + } } } @@ -1969,4 +1879,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _flowResumeCapacity = config.getFlowResumeCapacity(); } } + + public String getResourceName() + { + return _resourceName; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java index 7bdf516e44..d27a5ed234 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java @@ -4,6 +4,7 @@ import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.ServerMessage; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import java.util.concurrent.atomic.AtomicLong; /* * @@ -44,9 +45,7 @@ public class SimpleQueueEntryList implements QueueEntryList _nextUpdater = AtomicReferenceFieldUpdater.newUpdater (QueueEntryImpl.class, QueueEntryImpl.class, "_next"); - - - + private AtomicLong _deletes = new AtomicLong(0L); public SimpleQueueEntryList(AMQQueue queue) @@ -56,21 +55,77 @@ public class SimpleQueueEntryList implements QueueEntryList _tail = _head; } + + void advanceHead() { + _deletes.incrementAndGet(); QueueEntryImpl head = _head.nextNode(); + boolean deleted = head.isDeleted(); while(head._next != null && head.isDeleted()) { + deleted = true; final QueueEntryImpl newhead = head.nextNode(); if(newhead != null) { - _nextUpdater.compareAndSet(_head,head, newhead); + if(_nextUpdater.compareAndSet(_head,head, newhead)) + { + _deletes.decrementAndGet(); + } } head = _head.nextNode(); } + + if(!deleted) + { + deleted = true; + } + + if(_deletes.get() > 1000L) + { + _deletes.set(0L); + scavenge(); + } } + void scavenge() + { + QueueEntryImpl root = _head; + QueueEntryImpl next = root.nextNode(); + + do + { + + + while(next._next != null && next.isDeleted()) + { + + final QueueEntryImpl newhead = next.nextNode(); + if(newhead != null) + { + _nextUpdater.compareAndSet(root,next, newhead); + } + next = root.nextNode(); + } + if(next._next != null) + { + if(!next.isDeleted()) + { + root = next; + next = root.nextNode(); + } + } + else + { + break; + } + + } while (next != null && next._next != null); + + } + + public AMQQueue getQueue() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java new file mode 100755 index 0000000000..547365f647 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java @@ -0,0 +1,68 @@ +package org.apache.qpid.server.queue; + +import org.apache.qpid.pool.ReadWriteRunnable; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.AMQException; +import org.apache.log4j.Logger; + + +class SubFlushRunner implements ReadWriteRunnable +{ + private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class); + + + private final Subscription _sub; + private final String _name; + private static final long ITERATIONS = SimpleAMQQueue.MAX_ASYNC_DELIVERIES; + + public SubFlushRunner(Subscription sub) + { + _sub = sub; + _name = "SubFlushRunner-"+_sub; + } + + public void run() + { + + + Thread.currentThread().setName(_name); + + boolean complete = false; + try + { + CurrentActor.set(_sub.getLogActor()); + complete = getQueue().flushSubscription(_sub, ITERATIONS); + + } + catch (AMQException e) + { + _logger.error(e); + } + finally + { + CurrentActor.remove(); + } + if (!complete && !_sub.isSuspended()) + { + getQueue().execute(this); + } + + + } + + private SimpleAMQQueue getQueue() + { + return (SimpleAMQQueue) _sub.getQueue(); + } + + public boolean isRead() + { + return false; + } + + public boolean isWrite() + { + return true; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java deleted file mode 100644 index b09283b11f..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java +++ /dev/null @@ -1,127 +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.queue; - -import java.util.LinkedList; -import java.util.List; -import java.util.ArrayList; -import java.util.Collections; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; - -/** - * Contains data that is only used in AMQMessage transiently, e.g. while the content - * body fragments are arriving. - * - * Having this data stored in a separate class means that the AMQMessage class avoids - * the small overhead of numerous guaranteed-null references. - * - * @author Apache Software Foundation - */ -public class TransientMessageData -{ - /** - * Stored temporarily until the header has been received at which point it is used when - * constructing the handle - */ - private MessagePublishInfo _messagePublishInfo; - - /** - * Also stored temporarily. - */ - private ContentHeaderBody _contentHeaderBody; - - /** - * Keeps a track of how many bytes we have received in body frames - */ - private long _bodyLengthReceived = 0; - - /** - * This is stored during routing, to know the queues to which this message should immediately be - * delivered. It is <b>cleared after delivery has been attempted</b>. Any persistent record of destinations is done - * by the message handle. - */ - private List<AMQQueue> _destinationQueues; - - public MessagePublishInfo getMessagePublishInfo() - { - return _messagePublishInfo; - } - - public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo) - { - _messagePublishInfo = messagePublishInfo; - } - - public List<AMQQueue> getDestinationQueues() - { - return _destinationQueues == null ? (List<AMQQueue>) Collections.EMPTY_LIST : _destinationQueues; - } - - public void setDestinationQueues(List<AMQQueue> destinationQueues) - { - _destinationQueues = destinationQueues; - } - - public ContentHeaderBody getContentHeaderBody() - { - return _contentHeaderBody; - } - - public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) - { - _contentHeaderBody = contentHeaderBody; - } - - public long getBodyLengthReceived() - { - return _bodyLengthReceived; - } - - public void addBodyLength(int value) - { - _bodyLengthReceived += value; - } - - public boolean isAllContentReceived() throws AMQException - { - return _bodyLengthReceived == _contentHeaderBody.bodySize; - } - - public void addDestinationQueue(AMQQueue queue) - { - if(_destinationQueues == null) - { - _destinationQueues = new ArrayList<AMQQueue>(); - } - _destinationQueues.add(queue); - } - - public boolean isPersistent() - { - return _contentHeaderBody.properties instanceof BasicContentHeaderProperties && - ((BasicContentHeaderProperties) _contentHeaderBody.properties).getDeliveryMode() == - BasicContentHeaderProperties.PERSISTENT; - } -} 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 deleted file mode 100644 index 99387b210a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java +++ /dev/null @@ -1,201 +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.queue; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -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.MessageStore; - -/** - * @author Robert Greig (robert.j.greig@jpmorgan.com) - */ -public class WeakReferenceMessageHandle implements AMQMessageHandle -{ - private WeakReference<ContentHeaderBody> _contentHeaderBody; - - private WeakReference<MessagePublishInfo> _messagePublishInfo; - - private List<WeakReference<ContentChunk>> _contentBodies; - - private final MessageStore _messageStore; - - private final Long _messageId; - private long _arrivalTime; - - public WeakReferenceMessageHandle(final Long messageId, MessageStore messageStore) - { - _messageId = messageId; - _messageStore = messageStore; - } - - public ContentHeaderBody getContentHeaderBody() throws AMQException - { - ContentHeaderBody chb = (_contentHeaderBody != null ? _contentHeaderBody.get() : null); - if (chb == null) - { - MessageMetaData mmd = loadMessageMetaData(); - chb = mmd.getContentHeaderBody(); - } - return chb; - } - - public Long getMessageId() - { - return _messageId; - } - - private MessageMetaData loadMessageMetaData() - throws AMQException - { - MessageMetaData mmd = _messageStore.getMessageMetaData(_messageId); - populateFromMessageMetaData(mmd); - return mmd; - } - - private void populateFromMessageMetaData(MessageMetaData mmd) - { - _arrivalTime = mmd.getArrivalTime(); - _contentHeaderBody = new WeakReference<ContentHeaderBody>(mmd.getContentHeaderBody()); - _messagePublishInfo = new WeakReference<MessagePublishInfo>(mmd.getMessagePublishInfo()); - } - - public int getBodyCount() throws AMQException - { - if (_contentBodies == null) - { - MessageMetaData mmd = _messageStore.getMessageMetaData(_messageId); - int chunkCount = mmd.getContentChunkCount(); - _contentBodies = new ArrayList<WeakReference<ContentChunk>>(chunkCount); - for (int i = 0; i < chunkCount; i++) - { - _contentBodies.add(new WeakReference<ContentChunk>(null)); - } - } - return _contentBodies.size(); - } - - public long getBodySize() throws AMQException - { - return getContentHeaderBody().bodySize; - } - - public ContentChunk getContentChunk(int index) throws AMQException, IllegalArgumentException - { - if (index > _contentBodies.size() - 1) - { - throw new IllegalArgumentException("Index " + index + " out of valid range 0 to " + - (_contentBodies.size() - 1)); - } - WeakReference<ContentChunk> wr = _contentBodies.get(index); - ContentChunk cb = wr.get(); - if (cb == null) - { - cb = _messageStore.getContentBodyChunk(_messageId, index); - _contentBodies.set(index, new WeakReference<ContentChunk>(cb)); - } - return cb; - } - - /** - * Content bodies are set <i>before</i> the publish and header frames - * - * @param contentChunk - * @param isLastContentBody - * @throws AMQException - */ - public void addContentBodyFrame(ContentChunk contentChunk, boolean isLastContentBody) throws AMQException - { - if (_contentBodies == null && isLastContentBody) - { - _contentBodies = new ArrayList<WeakReference<ContentChunk>>(1); - } - else - { - if (_contentBodies == null) - { - _contentBodies = new LinkedList<WeakReference<ContentChunk>>(); - } - } - _contentBodies.add(new WeakReference<ContentChunk>(contentChunk)); - - } - - public MessagePublishInfo getMessagePublishInfo() throws AMQException - { - MessagePublishInfo bpb = (_messagePublishInfo != null ? _messagePublishInfo.get() : null); - if (bpb == null) - { - MessageMetaData mmd = loadMessageMetaData(); - - bpb = mmd.getMessagePublishInfo(); - } - return bpb; - } - - public boolean isPersistent() - { - return true; - } - - /** - * This is called when all the content has been received. - * - * @param publishBody - * @param 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 - if (contentHeaderBody.bodySize == 0) - { - _contentBodies = new LinkedList<WeakReference<ContentChunk>>(); - } - - final long arrivalTime = System.currentTimeMillis(); - - - MessageMetaData mmd = new MessageMetaData(publishBody, contentHeaderBody, _contentBodies == null ? 0 : _contentBodies.size(), arrivalTime); - - populateFromMessageMetaData(mmd); - return mmd; - } - - public void removeMessage() throws AMQException - { - _messageStore.removeMessage(_messageId); - } - - public long getArrivalTime() - { - return _arrivalTime; - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java index 831f928832..8e8581b66f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java @@ -35,8 +35,8 @@ import org.apache.qpid.server.plugins.PluginManager; import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.auth.database.ConfigurationFilePrincipalDatabaseManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; -import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import java.io.File; @@ -51,15 +51,15 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry public void initialise(int instanceID) throws Exception { - _rootMessageLogger = new RootMessageLoggerImpl(_configuration, + _rootMessageLogger = new RootMessageLoggerImpl(_configuration, new Log4jMessageLogger()); - + _registryName = String.valueOf(instanceID); // Set the Actor for current log messages CurrentActor.set(new BrokerActor(_registryName, _rootMessageLogger)); - CurrentActor.get().message(BrokerMessages.BRK_1001(QpidProperties.getReleaseVersion(),QpidProperties.getBuildVersion())); + CurrentActor.get().message(BrokerMessages.BRK_1001(QpidProperties.getReleaseVersion(),QpidProperties.getBuildVersion())); initialiseManagedObjectRegistry(); @@ -68,7 +68,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry _pluginManager = new PluginManager(_configuration.getPluginDirectory()); _accessManager = new ACLManager(_configuration.getSecurityConfiguration(), _pluginManager); - + _databaseManager = new ConfigurationFilePrincipalDatabaseManager(_configuration); _authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null); @@ -99,10 +99,10 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry } private void initialiseVirtualHosts() throws Exception - { + { for (String name : _configuration.getVirtualHosts()) { - _virtualHostRegistry.registerVirtualHost(new VirtualHost(_configuration.getVirtualHostConfig(name))); + _virtualHostRegistry.registerVirtualHost(new VirtualHostImpl(_configuration.getVirtualHostConfig(name))); } getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost()); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/PrincipalHolder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java index 07aa13b10d..7e93623cab 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/PrincipalHolder.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.security; import java.security.Principal; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java index c53403d0df..af0a1944cd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java @@ -14,9 +14,9 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.security.access; @@ -32,16 +32,12 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.configuration.SecurityConfiguration; -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.plugins.PluginManager; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; -import org.apache.qpid.server.security.access.plugins.SimpleXML; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; public class ACLManager { @@ -79,7 +75,7 @@ public class ACLManager { _hostPlugins = configurePlugins(hostConfig); } - + public Map<String, ACLPlugin> configurePlugins(SecurityConfiguration hostConfig) throws ConfigurationException { Configuration securityConfig = hostConfig.getConfiguration(); @@ -109,7 +105,7 @@ public class ACLManager } } return plugins; - } + } public static Logger getLogger() { @@ -132,18 +128,18 @@ public class ACLManager if (result == AuthzResult.DENIED) { // Something vetoed the access, we're done - return false; + return false; } else if (result == AuthzResult.ALLOWED) { - // Remove plugin from global check list since + // Remove plugin from global check list since // host allow overrides global allow remainingPlugins.remove(plugin.getKey()); } } - + for (ACLPlugin plugin : remainingPlugins.values()) - { + { result = checker.allowed(plugin); if (result == AuthzResult.DENIED) { @@ -271,7 +267,7 @@ public class ACLManager }); } - + public boolean authorisePublish(final PrincipalHolder session, final boolean immediate, final boolean mandatory, final AMQShortString routingKey, final Exchange e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java index 372a9f37a1..cf8a3fede9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java @@ -24,10 +24,9 @@ import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; public interface ACLPlugin { @@ -35,13 +34,13 @@ public interface ACLPlugin { ALLOWED, DENIED, - ABSTAIN + ABSTAIN } void setConfiguration(Configuration config) throws ConfigurationException; - // These return true if the plugin thinks the action should be allowed, and false if not. - + // These return true if the plugin thinks the action should be allowed, and false if not. + AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, AMQShortString routingKey); AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable, diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java index a66e4f3684..f99f3a60f7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java @@ -22,14 +22,13 @@ package org.apache.qpid.server.security.access.plugins; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ACLPlugin; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; /** - * This ACLPlugin abstains from all votes. Useful if your plugin only cares about a few operations. + * This ACLPlugin abstains from all votes. Useful if your plugin only cares about a few operations. */ public abstract class AbstractACLPlugin implements ACLPlugin { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java index 569dd8bdbd..d0df354d78 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java @@ -21,21 +21,19 @@ package org.apache.qpid.server.security.access.plugins; import org.apache.commons.configuration.Configuration; -import org.apache.qpid.AMQConnectionException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ACLPlugin; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; public abstract class BasicACLPlugin implements ACLPlugin { - // Returns true or false if the plugin should authorise or deny the request + // Returns true or false if the plugin should authorise or deny the request protected abstract AuthzResult getResult(); - + public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, AMQShortString routingKey) { @@ -51,7 +49,7 @@ public abstract class BasicACLPlugin implements ACLPlugin public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue) { - return getResult(); + return getResult(); } public AuthzResult authoriseConsume(PrincipalHolder session, diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java index 3f8ab8d9e6..b02e6b019c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java @@ -25,15 +25,14 @@ import org.apache.commons.configuration.Configuration; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ACLPlugin; import org.apache.qpid.server.security.access.ACLPluginFactory; import org.apache.qpid.server.security.access.AccessResult; import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.security.access.PrincipalPermissions; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -57,7 +56,7 @@ public class SimpleXML implements ACLPlugin return plugin; } }; - + private Map<String, PrincipalPermissions> _users; private final AccessResult GRANTED = new AccessResult(this, AccessResult.AccessStatus.GRANTED); @@ -82,7 +81,7 @@ public class SimpleXML implements ACLPlugin /** * Publish format takes Exchange + Routing Key Pairs - * + * * @param config * XML Configuration */ diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java index 393e792275..17d80c63fa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java @@ -32,12 +32,11 @@ import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.security.access.ACLPlugin; import org.apache.qpid.server.security.access.ACLPluginFactory; import org.apache.qpid.server.security.access.plugins.AbstractACLPlugin; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.PrincipalHolder; import org.apache.qpid.util.NetMatcher; public class FirewallPlugin extends AbstractACLPlugin @@ -59,7 +58,7 @@ public class FirewallPlugin extends AbstractACLPlugin return plugin; } }; - + public class FirewallRule { @@ -71,13 +70,13 @@ public class FirewallPlugin extends AbstractACLPlugin public FirewallRule(String access, List networks, List hostnames) { _access = (access.equals("allow")) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - + if (networks != null && networks.size() > 0) { String[] networkStrings = objListToStringArray(networks); _network = new NetMatcher(networkStrings); } - + if (hostnames != null && hostnames.size() > 0) { int i = 0; @@ -87,7 +86,7 @@ public class FirewallPlugin extends AbstractACLPlugin _hostnamePatterns[i++] = Pattern.compile(hostname); } } - + } private String[] objListToStringArray(List objList) @@ -149,7 +148,7 @@ public class FirewallPlugin extends AbstractACLPlugin thread.run(); long endTime = System.currentTimeMillis() + DNS_TIMEOUT; - + while (System.currentTimeMillis() < endTime && !done.get()) { try @@ -183,7 +182,7 @@ public class FirewallPlugin extends AbstractACLPlugin if(!(principalHolder instanceof ProtocolEngine)) { return AuthzResult.ABSTAIN; // We only deal with tcp sessions - } + } ProtocolEngine session = (ProtocolEngine) principalHolder; @@ -237,7 +236,7 @@ public class FirewallPlugin extends AbstractACLPlugin _default = AuthzResult.DENIED; } CompositeConfiguration finalConfig = new CompositeConfiguration(config); - + List subFiles = config.getList("xml[@fileName]"); for (Object subFile : subFiles) { @@ -245,7 +244,7 @@ public class FirewallPlugin extends AbstractACLPlugin } // all rules must have an access attribute - int numRules = finalConfig.getList("rule[@access]").size(); + int numRules = finalConfig.getList("rule[@access]").size(); _rules = new FirewallRule[numRules]; for (int i = 0; i < numRules; i++) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java index e0d4c49af1..2619a69cfd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java @@ -215,14 +215,7 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab _logger.warn("Unable to load access file:" + jmxaccesssFile); } - try - { - _mbean.register(); - } - catch (AMQException e) - { - _logger.warn("Unable to register user management MBean"); - } + _mbean.register(); } catch (JMException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java index fd2d09b777..f8bc530aa6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java @@ -31,12 +31,12 @@ public abstract class AbstractMessageStore implements MessageStore { protected LogSubject _logSubject; - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration hostConfig) throws Exception + public void configure(VirtualHost virtualHost) throws Exception { _logSubject = new MessageStoreLogSubject(virtualHost, this); CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName())); } - + public void close() throws Exception { CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java new file mode 100755 index 0000000000..c7606832d0 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -0,0 +1,57 @@ +/* +* +* 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 java.nio.ByteBuffer; +import org.apache.qpid.framing.FieldTable; + +public interface ConfigurationRecoveryHandler +{ + QueueRecoveryHandler begin(MessageStore store); + + public static interface QueueRecoveryHandler + { + void queue(String queueName, String owner, FieldTable arguments); + ExchangeRecoveryHandler completeQueueRecovery(); + } + + public static interface ExchangeRecoveryHandler + { + void exchange(String exchangeName, String type, boolean autoDelete); + BindingRecoveryHandler completeExchangeRecovery(); + } + + public static interface BindingRecoveryHandler + { + void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf); + void completeBindingRecovery(); + } + + public static interface QueueEntryRecoveryHandler + { + void complete(); + + void queueEntry(String queueName, long messageId); + } + + + +} 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 6dce764e63..edba56262a 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 @@ -21,26 +21,16 @@ package org.apache.qpid.server.store; import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; -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.CurrentActor; import org.apache.qpid.server.logging.messages.MessageStoreMessages; -import org.apache.qpid.server.queue.AMQMessage; +import org.apache.qpid.server.logging.messages.TransactionLogMessages; +import org.apache.qpid.server.logging.LogSubject; 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.virtualhost.VirtualHost; -import org.apache.qpid.server.message.ServerMessage; +import org.apache.commons.configuration.Configuration; import java.io.ByteArrayInputStream; @@ -55,15 +45,14 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.TreeMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; -public class DerbyMessageStore extends AbstractMessageStore +public class DerbyMessageStore implements MessageStore { private static final Logger _logger = Logger.getLogger(DerbyMessageStore.class); @@ -79,57 +68,66 @@ public class DerbyMessageStore extends AbstractMessageStore private static final String QUEUE_TABLE_NAME = "QPID_QUEUE"; private static final String BINDINGS_TABLE_NAME = "QPID_BINDINGS"; private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRY"; - private static final String MESSAGE_META_DATA_TABLE_NAME = "QPID_MESSAGE_META_DATA"; + + private static final String META_DATA_TABLE_NAME = "QPID_META_DATA"; private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT"; private static final int DB_VERSION = 1; - private VirtualHost _virtualHost; private static Class<Driver> DRIVER_CLASS; - private final AtomicLong _messageId = new AtomicLong(1); + private final AtomicLong _messageId = new AtomicLong(0); private AtomicBoolean _closed = new AtomicBoolean(false); private String _connectionURL; - Map<AMQShortString, Integer> _queueRecoveries = new TreeMap<AMQShortString, Integer>(); - + private static final String TABLE_EXISTANCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?"; private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+DB_VERSION_TABLE_NAME+" ( version int not null )"; private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+DB_VERSION_TABLE_NAME+" ( version ) VALUES ( ? )"; + private static final String CREATE_EXCHANGE_TABLE = "CREATE TABLE "+EXCHANGE_TABLE_NAME+" ( name varchar(255) not null, type varchar(255) not null, autodelete SMALLINT not null, PRIMARY KEY ( name ) )"; private static final String CREATE_QUEUE_TABLE = "CREATE TABLE "+QUEUE_TABLE_NAME+" ( name varchar(255) not null, owner varchar(255), PRIMARY KEY ( name ) )"; private static final String CREATE_BINDINGS_TABLE = "CREATE TABLE "+BINDINGS_TABLE_NAME+" ( exchange_name varchar(255) not null, queue_name varchar(255) not null, binding_key varchar(255) not null, arguments blob , PRIMARY KEY ( exchange_name, queue_name, binding_key ) )"; - private static final String CREATE_QUEUE_ENTRY_TABLE = "CREATE TABLE "+QUEUE_ENTRY_TABLE_NAME+" ( queue_name varchar(255) not null, message_id bigint not null, PRIMARY KEY (queue_name, message_id) )"; - private static final String CREATE_MESSAGE_META_DATA_TABLE = "CREATE TABLE "+MESSAGE_META_DATA_TABLE_NAME+" ( message_id bigint not null, exchange_name varchar(255) not null, routing_key varchar(255), flag_mandatory smallint not null, flag_immediate smallint not null, content_header blob, chunk_count int not null, PRIMARY KEY ( message_id ) )"; - private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE "+MESSAGE_CONTENT_TABLE_NAME+" ( message_id bigint not null, chunk_id int not null, content_chunk blob , PRIMARY KEY (message_id, chunk_id) )"; private static final String SELECT_FROM_QUEUE = "SELECT name, owner FROM " + QUEUE_TABLE_NAME; private static final String FIND_QUEUE = "SELECT name, owner FROM " + QUEUE_TABLE_NAME + " WHERE name = ?"; private static final String SELECT_FROM_EXCHANGE = "SELECT name, type, autodelete FROM " + EXCHANGE_TABLE_NAME; private static final String SELECT_FROM_BINDINGS = - "SELECT queue_name, binding_key, arguments FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ?"; + "SELECT exchange_name, queue_name, binding_key, arguments FROM " + BINDINGS_TABLE_NAME + " ORDER BY exchange_name"; private static final String FIND_BINDING = "SELECT * FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ? AND queue_name = ? AND binding_key = ? "; - private static final String DELETE_FROM_MESSAGE_META_DATA = "DELETE FROM " + MESSAGE_META_DATA_TABLE_NAME + " WHERE message_id = ?"; - private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ?"; private static final String INSERT_INTO_EXCHANGE = "INSERT INTO " + EXCHANGE_TABLE_NAME + " ( name, type, autodelete ) VALUES ( ?, ?, ? )"; private static final String DELETE_FROM_EXCHANGE = "DELETE FROM " + EXCHANGE_TABLE_NAME + " WHERE name = ?"; private static final String INSERT_INTO_BINDINGS = "INSERT INTO " + BINDINGS_TABLE_NAME + " ( exchange_name, queue_name, binding_key, arguments ) values ( ?, ?, ?, ? )"; private static final String DELETE_FROM_BINDINGS = "DELETE FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ? AND queue_name = ? AND binding_key = ?"; private static final String INSERT_INTO_QUEUE = "INSERT INTO " + QUEUE_TABLE_NAME + " (name, owner) VALUES (?, ?)"; private static final String DELETE_FROM_QUEUE = "DELETE FROM " + QUEUE_TABLE_NAME + " WHERE name = ?"; + + private static final String CREATE_QUEUE_ENTRY_TABLE = "CREATE TABLE "+QUEUE_ENTRY_TABLE_NAME+" ( queue_name varchar(255) not null, message_id bigint not null, PRIMARY KEY (queue_name, message_id) )"; private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_name, message_id) values (?,?)"; private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_name = ? AND message_id =?"; - private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME + "( message_id, chunk_id, content_chunk ) values (?, ?, ?)"; - private static final String INSERT_INTO_MESSAGE_META_DATA = "INSERT INTO " + MESSAGE_META_DATA_TABLE_NAME + "( message_id , exchange_name , routing_key , flag_mandatory , flag_immediate , content_header , chunk_count ) values (?, ?, ?, ?, ?, ?, ?)"; - private static final String SELECT_FROM_MESSAGE_META_DATA = - "SELECT exchange_name , routing_key , flag_mandatory , flag_immediate , content_header , chunk_count FROM " + MESSAGE_META_DATA_TABLE_NAME + " WHERE message_id = ?"; + private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_name, message_id FROM " + QUEUE_ENTRY_TABLE_NAME + " ORDER BY queue_name, message_id"; + + + private static final String CREATE_META_DATA_TABLE = "CREATE TABLE "+META_DATA_TABLE_NAME+" ( message_id bigint not null, meta_data blob, PRIMARY KEY ( message_id ) )"; + private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE "+MESSAGE_CONTENT_TABLE_NAME+" ( message_id bigint not null, offset int not null, content blob , PRIMARY KEY (message_id, offset) )"; + + private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME + "( message_id, offset, content ) values (?, ?, ?)"; private static final String SELECT_FROM_MESSAGE_CONTENT = - "SELECT content_chunk FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ? and chunk_id = ?"; - private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_name, message_id FROM " + QUEUE_ENTRY_TABLE_NAME; - private static final String TABLE_EXISTANCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?"; + "SELECT offset, content FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ? AND offset >= ? AND offset < ? ORDER BY message_id, offset"; + private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ?"; + + private static final String INSERT_INTO_META_DATA = "INSERT INTO " + META_DATA_TABLE_NAME + "( message_id , meta_data ) values (?, ?)";; + private static final String SELECT_FROM_META_DATA = + "SELECT meta_data FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?"; + private static final String DELETE_FROM_META_DATA = "DELETE FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?"; + private static final String SELECT_ALL_FROM_META_DATA = "SELECT message_id, meta_data FROM " + META_DATA_TABLE_NAME; + + + private LogSubject _logSubject; + private boolean _configured; private enum State @@ -145,21 +143,82 @@ public class DerbyMessageStore extends AbstractMessageStore private State _state = State.INITIAL; - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception + public void configureConfigStore(String name, + ConfigurationRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception { - super.configure(virtualHost,base,config); - stateTransition(State.INITIAL, State.CONFIGURING); + _logSubject = logSubject; + CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName())); - initialiseDriver(); + if(!_configured) + { + commonConfiguration(name, storeConfiguration, logSubject); + _configured = true; + } + + // this recovers durable exchanges, queues, and bindings + recover(recoveryHandler); - _virtualHost = virtualHost; - _logger.info("Configuring Derby message store for virtual host " + virtualHost.getName()); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + stateTransition(State.RECOVERING, State.STARTED); + + } + + + public void configureMessageStore(String name, + MessageStoreRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception + { + CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName())); + + if(!_configured) + { + + _logSubject = logSubject; + + commonConfiguration(name, storeConfiguration, logSubject); + _configured = true; + } + + recoverMessages(recoveryHandler); + + } + + + + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception + { + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1001(this.getClass().getName())); + + if(!_configured) + { + + _logSubject = logSubject; + + commonConfiguration(name, storeConfiguration, logSubject); + _configured = true; + } + + recoverQueueEntries(recoveryHandler); + + } + + + + private void commonConfiguration(String name, Configuration storeConfiguration, LogSubject logSubject) + throws ClassNotFoundException, SQLException + { + initialiseDriver(); //Update to pick up QPID_WORK and use that as the default location not just derbyDB - final String databasePath = config.getStoreConfiguration().getString(ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")+"/derbyDB"); + + final String databasePath = storeConfiguration.getString(ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")+"/derbyDB"); File environmentPath = new File(databasePath); if (!environmentPath.exists()) @@ -171,17 +230,9 @@ public class DerbyMessageStore extends AbstractMessageStore } } - CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1002(environmentPath.getAbsolutePath())); - - createOrOpenDatabase(databasePath); - - // this recovers durable queues and persistent messages - - recover(); - - - stateTransition(State.RECOVERING, State.STARTED); + CurrentActor.get().message(logSubject, MessageStoreMessages.MST_1002(environmentPath.getAbsolutePath())); + createOrOpenDatabase(name, databasePath); } private static synchronized void initialiseDriver() throws ClassNotFoundException @@ -192,10 +243,10 @@ public class DerbyMessageStore extends AbstractMessageStore } } - private void createOrOpenDatabase(final String environmentPath) throws SQLException + private void createOrOpenDatabase(String name, final String environmentPath) throws SQLException { //fixme this the _vhost name should not be added here. - _connectionURL = "jdbc:derby:" + environmentPath + "/" + _virtualHost.getName() + ";create=true"; + _connectionURL = "jdbc:derby:" + environmentPath + "/" + name + ";create=true"; Connection conn = newConnection(); @@ -204,7 +255,7 @@ public class DerbyMessageStore extends AbstractMessageStore createQueueTable(conn); createBindingsTable(conn); createQueueEntryTable(conn); - createMessageMetaDataTable(conn); + createMetaDataTable(conn); createMessageContentTable(conn); conn.close(); @@ -275,12 +326,12 @@ public class DerbyMessageStore extends AbstractMessageStore } - private void createMessageMetaDataTable(final Connection conn) throws SQLException + private void createMetaDataTable(final Connection conn) throws SQLException { - if(!tableExists(MESSAGE_META_DATA_TABLE_NAME, conn)) + if(!tableExists(META_DATA_TABLE_NAME, conn)) { Statement stmt = conn.createStatement(); - stmt.execute(CREATE_MESSAGE_META_DATA_TABLE); + stmt.execute(CREATE_META_DATA_TABLE); stmt.close(); } @@ -313,38 +364,22 @@ public class DerbyMessageStore extends AbstractMessageStore return exists; } - public void recover() throws AMQException + public void recover(ConfigurationRecoveryHandler recoveryHandler) throws AMQException { stateTransition(State.CONFIGURING, State.RECOVERING); - CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1004(null, false)); - - StoreContext context = new StoreContext(); try { - Map<AMQShortString, AMQQueue> queues = loadQueues(); - - recoverExchanges(); - - try - { - - beginTran(context); + ConfigurationRecoveryHandler.QueueRecoveryHandler qrh = recoveryHandler.begin(this); + List<String> queues = loadQueues(qrh); - deliverMessages(context, queues); - commitTran(context); + ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh = qrh.completeQueueRecovery(); + List<String> exchanges = loadExchanges(erh); + ConfigurationRecoveryHandler.BindingRecoveryHandler brh = erh.completeExchangeRecovery(); + recoverBindings(brh, exchanges); + brh.completeBindingRecovery(); - //Recovery Complete - CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1006(null, false)); - } - finally - { - if(inTran(context)) - { - abortTran(context); - } - } } catch (SQLException e) @@ -356,53 +391,34 @@ public class DerbyMessageStore extends AbstractMessageStore } - private Map<AMQShortString, AMQQueue> loadQueues() throws SQLException, AMQException + private List<String> loadQueues(ConfigurationRecoveryHandler.QueueRecoveryHandler qrh) throws SQLException, AMQException { Connection conn = newConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE); - Map<AMQShortString, AMQQueue> queueMap = new HashMap<AMQShortString, AMQQueue>(); + List<String> queues = new ArrayList<String>(); + while(rs.next()) { String queueName = rs.getString(1); String owner = rs.getString(2); - AMQShortString queueNameShortString = new AMQShortString(queueName); - - AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueNameShortString); - - if (q == null) - { - q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost, - null); - _virtualHost.getQueueRegistry().registerQueue(q); - } - - queueMap.put(queueNameShortString,q); + qrh.queue(queueName, owner, null); - CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1004(String.valueOf(q.getName()), true)); + queues.add(queueName); - //Record that we have a queue for recovery - _queueRecoveries.put(new AMQShortString(queueName), 0); - } - return queueMap; - } - private void recoverExchanges() throws AMQException, SQLException - { - for (Exchange exchange : loadExchanges()) - { - recoverExchange(exchange); } + return queues; } - private List<Exchange> loadExchanges() throws AMQException, SQLException + private List<String> loadExchanges(ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh) throws AMQException, SQLException { - List<Exchange> exchanges = new ArrayList<Exchange>(); + List<String> exchanges = new ArrayList<String>(); Connection conn = null; try { @@ -412,21 +428,15 @@ public class DerbyMessageStore extends AbstractMessageStore Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(SELECT_FROM_EXCHANGE); - Exchange exchange; while(rs.next()) { String exchangeName = rs.getString(1); String type = rs.getString(2); boolean autoDelete = rs.getShort(3) != 0; - AMQShortString exchangeNameSS = new AMQShortString(exchangeName); - exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeNameSS); - if (exchange == null) - { - exchange = _virtualHost.getExchangeFactory().createExchange(exchangeNameSS, new AMQShortString(type), true, autoDelete, 0); - _virtualHost.getExchangeRegistry().registerExchange(exchange); - } - exchanges.add(exchange); + exchanges.add(exchangeName); + + erh.exchange(exchangeName, type, autoDelete); } return exchanges; @@ -442,11 +452,13 @@ public class DerbyMessageStore extends AbstractMessageStore } - private void recoverExchange(Exchange exchange) throws AMQException, SQLException + private void recoverBindings(ConfigurationRecoveryHandler.BindingRecoveryHandler brh, List<String> exchanges) throws AMQException, SQLException { - _logger.info("Recovering durable exchange " + exchange.getName() + " of type " + exchange.getType() + "..."); - QueueRegistry queueRegistry = _virtualHost.getQueueRegistry(); + + _logger.info("Recovering bindings..."); + + Connection conn = null; try @@ -454,41 +466,29 @@ public class DerbyMessageStore extends AbstractMessageStore conn = newConnection(); PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_BINDINGS); - stmt.setString(1, exchange.getName().toString()); ResultSet rs = stmt.executeQuery(); while(rs.next()) { - String queueName = rs.getString(1); - String bindingKey = rs.getString(2); - Blob arguments = rs.getBlob(3); - + String exchangeName = rs.getString(1); + String queueName = rs.getString(2); + String bindingKey = rs.getString(3); + Blob arguments = rs.getBlob(4); + java.nio.ByteBuffer buf; - AMQQueue queue = queueRegistry.getQueue(new AMQShortString(queueName)); - if (queue == null) + if(arguments != null && arguments.length() != 0) { - _logger.error("Unkown queue: " + queueName + " cannot be bound to exchange: " - + exchange.getName()); + byte[] argumentBytes = arguments.getBytes(1, (int) arguments.length()); + buf = java.nio.ByteBuffer.wrap(argumentBytes); } else { - _logger.info("Restoring binding: (Exchange: " + exchange.getName() + ", Queue: " + queueName - + ", Routing Key: " + bindingKey + ", Arguments: " + arguments - + ")"); - - FieldTable argumentsFT = null; - if(arguments != null) - { - byte[] argumentBytes = arguments.getBytes(0, (int) arguments.length()); - ByteBuffer buf = ByteBuffer.wrap(argumentBytes); - argumentsFT = new FieldTable(buf,arguments.length()); - } - - queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT); - + buf = null; } + + brh.binding(exchangeName, queueName, bindingKey, buf); } } finally @@ -500,45 +500,48 @@ public class DerbyMessageStore extends AbstractMessageStore } } + + public void close() throws Exception { + CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003()); _closed.getAndSet(true); - - super.close(); } - public void removeMessage(Long messageId) throws AMQException + public StoredMessage addMessage(StorableMessageMetaData metaData) { - StoreContext storeContext = new StoreContext(); - - boolean localTx = getOrCreateTransaction(storeContext); - - Connection conn = getConnection(storeContext); - ConnectionWrapper wrapper = (ConnectionWrapper) storeContext.getPayload(); - - - if (_logger.isDebugEnabled()) + if(metaData.isPersistent()) + { + return new StoredDerbyMessage(_messageId.incrementAndGet(), metaData); + } + else { - _logger.debug("Message Id: " + messageId + " Removing"); + return new StoredMemoryMessage(_messageId.incrementAndGet(), metaData); } + } + + public StoredMessage getMessage(long messageNumber) + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } - // first we need to look up the header to get the chunk count - MessageMetaData mmd = getMessageMetaData(messageId); + public void removeMessage(long messageId) + { + Connection conn = null; try { - PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_MESSAGE_META_DATA); + + + conn = newConnection(); + PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_META_DATA); stmt.setLong(1,messageId); - wrapper.setRequiresCommit(); int results = stmt.executeUpdate(); if (results == 0) { - if (localTx) - { - abortTran(storeContext); - } - throw new AMQException("Message metadata not found for message id " + messageId); + + throw new RuntimeException("Message metadata not found for message id " + messageId); } stmt.close(); @@ -551,29 +554,27 @@ public class DerbyMessageStore extends AbstractMessageStore stmt.setLong(1,messageId); results = stmt.executeUpdate(); - if(results != mmd.getContentChunkCount()) - { - if (localTx) - { - abortTran(storeContext); - } - throw new AMQException("Unexpected number of content chunks when deleting message. Expected " + mmd.getContentChunkCount() + " but found " + results); - } - if (localTx) - { - commitTran(storeContext); - } + conn.commit(); + conn.close(); } catch (SQLException e) { - if ((conn != null) && localTx) + if ((conn != null)) { - abortTran(storeContext); + try + { + conn.rollback(); + conn.close(); + } + catch (SQLException e1) + { + + } } - throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e); + throw new RuntimeException("Error removing Message with id " + messageId + " to database: " + e, e); } } @@ -879,29 +880,26 @@ public class DerbyMessageStore extends AbstractMessageStore } - public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + public Transaction newTransaction() { - AMQShortString name = queue.getName(); + return new DerbyTransaction(); + } + + public void enqueueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQException + { + String name = queue.getResourceName(); + + Connection conn = connWrapper.getConnection(); - boolean localTx = getOrCreateTransaction(context); - Connection conn = getConnection(context); - ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); try { PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_QUEUE_ENTRY); - stmt.setString(1,name.toString()); + stmt.setString(1,name); stmt.setLong(2,messageId); stmt.executeUpdate(); connWrapper.requiresCommit(); - if(localTx) - { - commitTran(context); - } - - - if (_logger.isDebugEnabled()) { _logger.debug("Enqueuing message " + messageId + " on queue " + name + "[Connection" + conn + "]"); @@ -909,10 +907,6 @@ public class DerbyMessageStore extends AbstractMessageStore } catch (SQLException e) { - if(localTx) - { - abortTran(context); - } _logger.error("Failed to enqueue: " + e, e); throw new AMQException("Error writing enqueued message with id " + messageId + " for queue " + name + " to database", e); @@ -920,18 +914,18 @@ public class DerbyMessageStore extends AbstractMessageStore } - public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + public void dequeueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQException { - AMQShortString name = queue.getName(); + String name = queue.getResourceName(); + + + Connection conn = connWrapper.getConnection(); - boolean localTx = getOrCreateTransaction(context); - Connection conn = getConnection(context); - ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); try { PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_QUEUE_ENTRY); - stmt.setString(1,name.toString()); + stmt.setString(1,name); stmt.setLong(2,messageId); int results = stmt.executeUpdate(); @@ -942,13 +936,6 @@ public class DerbyMessageStore extends AbstractMessageStore throw new AMQException("Unable to find message with id " + messageId + " on queue " + name); } - if(localTx) - { - commitTran(context); - } - - - if (_logger.isDebugEnabled()) { _logger.debug("Dequeuing message " + messageId + " on queue " + name );//+ "[Connection" + conn + "]"); @@ -956,10 +943,6 @@ public class DerbyMessageStore extends AbstractMessageStore } catch (SQLException e) { - if(localTx) - { - abortTran(context); - } _logger.error("Failed to dequeue: " + e, e); throw new AMQException("Error deleting enqueued message with id " + messageId + " for queue " + name + " from database", e); @@ -993,52 +976,20 @@ 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: " - + context.getPayload()); - } - else - { - try - { - Connection conn = newConnection(); - - context.setPayload(new ConnectionWrapper(conn)); - } - catch (SQLException e) - { - throw new AMQException("Error starting transaction: " + e, e); - } - } - } - - public void commitTran(StoreContext context) throws AMQException + public void commitTran(ConnectionWrapper connWrapper) throws AMQException { - ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); - - if (connWrapper == null) - { - throw new AMQException("Fatal internal error: transactional context is empty at commitTran"); - } try { Connection conn = connWrapper.getConnection(); - if(connWrapper.requiresCommit()) - { - conn.commit(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("commit tran completed"); - } + conn.commit(); + if (_logger.isDebugEnabled()) + { + _logger.debug("commit tran completed"); } + conn.close(); } catch (SQLException e) @@ -1047,13 +998,13 @@ public class DerbyMessageStore extends AbstractMessageStore } finally { - context.setPayload(null); + } } - public StoreFuture commitTranAsync(StoreContext context) throws AMQException + public StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws AMQException { - commitTran(context); + commitTran(connWrapper); return new StoreFuture() { public boolean isComplete() @@ -1069,10 +1020,8 @@ public class DerbyMessageStore extends AbstractMessageStore } - public void abortTran(StoreContext context) throws AMQException + public void abortTran(ConnectionWrapper connWrapper) throws AMQException { - ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); - if (connWrapper == null) { throw new AMQException("Fatal internal error: transactional context is empty at abortTran"); @@ -1097,275 +1046,258 @@ public class DerbyMessageStore extends AbstractMessageStore { throw new AMQException("Error aborting transaction: " + e, e); } - finally - { - context.setPayload(null); - } + } - public boolean inTran(StoreContext context) + public Long getNewMessageId() { - return context.getPayload() != null; + return _messageId.incrementAndGet(); } - public Long getNewMessageId() + + private void storeMetaData(Connection conn, long messageId, StorableMessageMetaData metaData) + throws SQLException { - return _messageId.getAndIncrement(); + PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_META_DATA); + stmt.setLong(1,messageId); + + final int bodySize = 1 + metaData.getStorableSize(); + byte[] underlying = new byte[bodySize]; + underlying[0] = (byte) metaData.getType().ordinal(); + java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(underlying); + buf.position(1); + buf = buf.slice(); + + metaData.writeToBuffer(0, buf); + ByteArrayInputStream bis = new ByteArrayInputStream(underlying); + stmt.setBinaryStream(2,bis,underlying.length); + stmt.executeUpdate(); + } - public void storeContentBodyChunk( - Long messageId, - int index, - ContentChunk contentBody, - boolean lastContentBody) throws AMQException + + + + private void recoverMessages(MessageStoreRecoveryHandler recoveryHandler) throws SQLException { - StoreContext context = new StoreContext(); - boolean localTx = getOrCreateTransaction(context); - Connection conn = getConnection(context); - ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload(); + Connection conn = newConnection(); - try - { - PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT); - stmt.setLong(1,messageId); - stmt.setInt(2, index); - byte[] chunkData = new byte[contentBody.getSize()]; - contentBody.getData().duplicate().get(chunkData); - /* this would be the Java 6 way of doing things - Blob dataAsBlob = conn.createBlob(); - dataAsBlob.setBytes(1L, chunkData); - stmt.setBlob(3, dataAsBlob); - */ - ByteArrayInputStream bis = new ByteArrayInputStream(chunkData); - stmt.setBinaryStream(3, bis, chunkData.length); - stmt.executeUpdate(); - connWrapper.requiresCommit(); + MessageStoreRecoveryHandler.StoredMessageRecoveryHandler messageHandler = recoveryHandler.begin(); - if(localTx) - { - commitTran(context); - } - } - catch (SQLException e) + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_META_DATA); + + long maxId = 0; + + while(rs.next()) { - if(localTx) + + long messageId = rs.getLong(1); + Blob dataAsBlob = rs.getBlob(2); + + if(messageId > maxId) { - abortTran(context); + maxId = messageId; } - throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e); + byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length()); + java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes); + buf.position(1); + buf = buf.slice(); + MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; + StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); + StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, false); + messageHandler.message(message); + + } + _messageId.set(maxId); + + messageHandler.completeMessageRecovery(); } - 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(); - try - { - PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_META_DATA); - stmt.setLong(1,messageId); - stmt.setString(2, mmd.getMessagePublishInfo().getExchange().toString()); - stmt.setString(3, mmd.getMessagePublishInfo().getRoutingKey().toString()); - stmt.setShort(4, mmd.getMessagePublishInfo().isMandatory() ? (short) 1 : (short) 0); - stmt.setShort(5, mmd.getMessagePublishInfo().isImmediate() ? (short) 1 : (short) 0); - - ContentHeaderBody headerBody = mmd.getContentHeaderBody(); - final int bodySize = headerBody.getSize(); - byte[] underlying = new byte[bodySize]; - ByteBuffer buf = ByteBuffer.wrap(underlying); - headerBody.writePayload(buf); -/* - Blob dataAsBlob = conn.createBlob(); - dataAsBlob.setBytes(1L, underlying); - stmt.setBlob(6, dataAsBlob); -*/ - ByteArrayInputStream bis = new ByteArrayInputStream(underlying); - stmt.setBinaryStream(6,bis,underlying.length); + private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException + { + Connection conn = newConnection(); - stmt.setInt(7, mmd.getContentChunkCount()); + TransactionLogRecoveryHandler.QueueEntryRecoveryHandler queueEntryHandler = recoveryHandler.begin(this); - stmt.executeUpdate(); - connWrapper.requiresCommit(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY); - if(localTx) - { - commitTran(context); - } - } - catch (SQLException e) + + while(rs.next()) { - if(localTx) - { - abortTran(context); - } - throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e); + String queueName = rs.getString(1); + long messageId = rs.getLong(2); + queueEntryHandler.queueEntry(queueName,messageId); } + + queueEntryHandler.completeQueueEntryRecovery(); + } - public MessageMetaData getMessageMetaData(Long messageId) throws AMQException + StorableMessageMetaData getMetaData(long messageId) throws SQLException { - StoreContext context = new StoreContext(); - boolean localTx = getOrCreateTransaction(context); - Connection conn = getConnection(context); - + Connection conn = newConnection(); try { - - PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_META_DATA); + PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_META_DATA); stmt.setLong(1,messageId); ResultSet rs = stmt.executeQuery(); if(rs.next()) { - final AMQShortString exchange = new AMQShortString(rs.getString(1)); - final AMQShortString routingKey = rs.getString(2) == null ? null : new AMQShortString(rs.getString(2)); - final boolean mandatory = (rs.getShort(3) != (short)0); - final boolean immediate = (rs.getShort(4) != (short)0); - MessagePublishInfo info = new MessagePublishInfo() - { - public AMQShortString getExchange() - { - return exchange; - } + Blob dataAsBlob = rs.getBlob(1); - public void setExchange(AMQShortString exchange) - { + byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length()); + java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes); + buf.position(1); + buf = buf.slice(); + MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; + StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); + + return metaData; + } + else + { + throw new RuntimeException("Meta data not found for message with id " + messageId); + } - } + } + finally + { + conn.close(); + } + } - public boolean isImmediate() - { - return immediate; - } - public boolean isMandatory() - { - return mandatory; - } + private void addContent(Connection conn, long messageId, int offset, ByteBuffer src) + { - public AMQShortString getRoutingKey() - { - return routingKey; - } - } ; - Blob dataAsBlob = rs.getBlob(5); - byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length()); - ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); + try + { + final boolean newConnection = conn == null; - ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(buf, dataAsBytes.length); + if(newConnection) + { + conn = newConnection(); + } - if(localTx) - { - commitTran(context); - } + PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT); + stmt.setLong(1,messageId); + stmt.setInt(2, offset); - return new MessageMetaData(info, chb, rs.getInt(6)); + src = src.slice(); - } - else + byte[] chunkData = new byte[src.limit()]; + src.duplicate().get(chunkData); + /* this would be the Java 6 way of doing things + Blob dataAsBlob = conn.createBlob(); + dataAsBlob.setBytes(1L, chunkData); + stmt.setBlob(3, dataAsBlob); + */ + ByteArrayInputStream bis = new ByteArrayInputStream(chunkData); + stmt.setBinaryStream(3, bis, chunkData.length); + stmt.executeUpdate(); + + if(newConnection) { - if(localTx) - { - abortTran(context); - } - throw new AMQException("Metadata not found for message with id " + messageId); + conn.commit(); + conn.close(); } } catch (SQLException e) { - if(localTx) + if(conn != null) { - abortTran(context); + try + { + conn.close(); + } + catch (SQLException e1) + { + + } } - throw new AMQException("Error reading AMQMessage with id " + messageId + " from database: " + e, e); + throw new RuntimeException("Error reading AMQMessage with id " + messageId + " from database: " + e, e); } } - public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException - { - StoreContext context = new StoreContext(); - boolean localTx = getOrCreateTransaction(context); - Connection conn = getConnection(context); - - try - { - - PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT); - stmt.setLong(1,messageId); - stmt.setInt(2, index); - ResultSet rs = stmt.executeQuery(); + public int getContent(long messageId, int offset, ByteBuffer dst) + { + Connection conn = null; - if(rs.next()) - { - Blob dataAsBlob = rs.getBlob(1); - final int size = (int) dataAsBlob.length(); - byte[] dataAsBytes = dataAsBlob.getBytes(1, size); - final ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); + try + { + conn = newConnection(); - ContentChunk cb = new ContentChunk() - { + PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT); + stmt.setLong(1,messageId); + stmt.setInt(2, offset); + stmt.setInt(3, offset+dst.remaining()); + ResultSet rs = stmt.executeQuery(); - public int getSize() - { - return size; - } + int written = 0; - public ByteBuffer getData() - { - return buf; - } + while(rs.next()) + { + int offsetInMessage = rs.getInt(1); + Blob dataAsBlob = rs.getBlob(2); - public void reduceToFit() - { + final int size = (int) dataAsBlob.length(); + byte[] dataAsBytes = dataAsBlob.getBytes(1, size); - } - }; + int posInArray = offset + written - offsetInMessage; + int count = size - posInArray; + if(count > dst.remaining()) + { + count = dst.remaining(); + } + dst.put(dataAsBytes,posInArray,count); + written+=count; - if(localTx) - { - commitTran(context); - } + if(dst.remaining() == 0) + { + break; + } + } - return cb; + conn.close(); + return written; - } - else - { - if(localTx) - { - abortTran(context); - } - throw new AMQException("Message not found for message with id " + messageId); - } + } + catch (SQLException e) + { + if(conn != null) + { + try + { + conn.close(); } - catch (SQLException e) + catch (SQLException e1) { - if(localTx) - { - abortTran(context); - } - throw new AMQException("Error reading AMQMessage with id " + messageId + " from database: " + e, e); } + } + + throw new RuntimeException("Error reading AMQMessage with id " + messageId + " from database: " + e, e); + } @@ -1376,186 +1308,158 @@ public class DerbyMessageStore extends AbstractMessageStore return true; } - public void storeMessageHeader(Long messageNumber, ServerMessage message) - { - //To change body of implemented methods use File | Settings | File Templates. - } - public void storeContent(Long messageNumber, long offset, java.nio.ByteBuffer body) + private synchronized void stateTransition(State requiredState, State newState) throws AMQException { - //To change body of implemented methods use File | Settings | File Templates. - } + if (_state != requiredState) + { + throw new AMQException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState + + "; currently in state: " + _state); + } - public ServerMessage getMessage(Long messageNumber) - { - return null; //To change body of implemented methods use File | Settings | File Templates. + _state = newState; } - private void checkNotClosed() throws MessageStoreClosedException + + private class DerbyTransaction implements Transaction { - if (_closed.get()) + private final ConnectionWrapper _connWrapper; + + + private DerbyTransaction() { - throw new MessageStoreClosedException(); + try + { + _connWrapper = new ConnectionWrapper(newConnection()); + } + catch (SQLException e) + { + throw new RuntimeException(e); + } } - } + public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, messageId); + } - private static final class ProcessAction - { - private final AMQQueue _queue; - private final StoreContext _context; - private final AMQMessage _message; + public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, messageId); + + } - public ProcessAction(AMQQueue queue, StoreContext context, AMQMessage message) + public void commitTran() throws AMQException { - _queue = queue; - _context = context; - _message = message; + DerbyMessageStore.this.commitTran(_connWrapper); } - public void process() throws AMQException + public StoreFuture commitTranAsync() throws AMQException { - _queue.enqueue(_message); + return DerbyMessageStore.this.commitTranAsync(_connWrapper); } + public void abortTran() throws AMQException + { + DerbyMessageStore.this.abortTran(_connWrapper); + } } - - private void deliverMessages(final StoreContext context, Map<AMQShortString, AMQQueue> queues) - throws SQLException, AMQException + private class StoredDerbyMessage implements StoredMessage { - Map<Long, AMQMessage> msgMap = new HashMap<Long,AMQMessage>(); - List<ProcessAction> actions = new ArrayList<ProcessAction>(); + private final long _messageId; + private volatile WeakReference<StorableMessageMetaData> _metaDataRef; + private Connection _conn; - final boolean inLocaltran = inTran(context); - Connection conn = null; - try + StoredDerbyMessage(long messageId, StorableMessageMetaData metaData) { - if(inLocaltran) - { - conn = getConnection(context); - } - else - { - conn = newConnection(); - } - - MessageHandleFactory messageHandleFactory = new MessageHandleFactory(); - long maxId = 1; + this(messageId, metaData, true); + } - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY); - while (rs.next()) + StoredDerbyMessage(long messageId, + StorableMessageMetaData metaData, boolean persist) + { + try { - AMQShortString queueName = new AMQShortString(rs.getString(1)); + _messageId = messageId; - AMQQueue queue = queues.get(queueName); - if (queue == null) + _metaDataRef = new WeakReference(metaData); + if(persist) { - queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, null, false, _virtualHost, null); - - _virtualHost.getQueueRegistry().registerQueue(queue); - queues.put(queueName, queue); - - //Log Recovery Start - CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1004(String.valueOf(queue.getName()), true)); + _conn = newConnection(); + storeMetaData(_conn, messageId, metaData); } + } + catch (SQLException e) + { + throw new RuntimeException(e); + } - long messageId = rs.getLong(2); - maxId = Math.max(maxId, messageId); - AMQMessage message = msgMap.get(messageId); - - if(message != null) - { -// message.incrementReference(); - } - else - { - message = new AMQMessage(messageId, this, messageHandleFactory); - msgMap.put(messageId,message); - } + } - if (_logger.isDebugEnabled()) + public StorableMessageMetaData getMetaData() + { + StorableMessageMetaData metaData = _metaDataRef.get(); + if(metaData == null) + { + try { - _logger.debug("On recovery, delivering " + message.getMessageId() + " to " + queue.getName()); + metaData = DerbyMessageStore.this.getMetaData(_messageId); } - - Integer count = _queueRecoveries.get(queueName); - if (count == null) + catch (SQLException e) { - count = 0; + throw new RuntimeException(e); } - - _queueRecoveries.put(queueName, ++count); - - actions.add(new ProcessAction(queue, context, message)); + _metaDataRef = new WeakReference(metaData); } - for(ProcessAction action : actions) - { - action.process(); - } - - _messageId.set(maxId + 1); + return metaData; } - catch (SQLException e) + + public long getMessageNumber() { - _logger.error("Error: " + e, e); - throw e; + return _messageId; } - finally + + public void addContent(int offsetInMessage, java.nio.ByteBuffer src) { - if (inLocaltran && conn != null) - { - conn.close(); - } + DerbyMessageStore.this.addContent(_conn, _messageId, offsetInMessage, src); } - if (_logger.isInfoEnabled()) + public int getContent(int offsetInMessage, java.nio.ByteBuffer dst) { - _logger.info("Recovered message counts: " + _queueRecoveries); + return DerbyMessageStore.this.getContent(_messageId, offsetInMessage, dst); } - for(Map.Entry<AMQShortString,Integer> entry : _queueRecoveries.entrySet()) + public StoreFuture flushToStore() { - CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1005(entry.getValue(), String.valueOf(entry.getKey()))); - - CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1006(String.valueOf(entry.getKey()), true)); + try + { + if(_conn != null) + { + _conn.commit(); + _conn.close(); + } + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + finally + { + _conn = null; + } + return IMMEDIATE_FUTURE; } - // Free the memory - _queueRecoveries = null; - - } - - private Connection getConnection(final StoreContext context) - { - return ((ConnectionWrapper)context.getPayload()).getConnection(); - } - - private boolean getOrCreateTransaction(StoreContext context) throws AMQException - { - - ConnectionWrapper tx = (ConnectionWrapper) context.getPayload(); - if (tx == null) + public void remove() { - beginTran(context); - return true; + flushToStore(); + DerbyMessageStore.this.removeMessage(_messageId); } - - return false; } - private synchronized void stateTransition(State requiredState, State newState) throws AMQException - { - if (_state != requiredState) - { - throw new AMQException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState - + "; currently in state: " + _state); - } - _state = newState; - } } 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 index d791905ad9..cfbacd28c8 100755 --- 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 @@ -22,12 +22,29 @@ package org.apache.qpid.server.store; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.commons.configuration.Configuration; public interface DurableConfigurationStore { + + /** + * Called after instantiation in order to configure the message store. A particular implementation can define + * whatever parameters it wants. + * + * @param name The name to be used by this storem + * @param recoveryHandler Handler to be called as the store recovers on start up + * @param config The apache commons configuration object. + * + * @throws Exception If any error occurs that means the store is unable to configure itself. + */ + void configureConfigStore(String name, + ConfigurationRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception; /** * Makes the specified exchange persistent. * 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 ecae3cb794..f43177bfc1 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 @@ -25,13 +25,15 @@ 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.queue.MessageMetaData; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.message.MessageMetaData; 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.LogSubject; +import org.apache.qpid.server.logging.messages.MessageStoreMessages; +import org.apache.qpid.server.logging.messages.ConfigStoreMessages; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.ServerMessage; +import org.apache.commons.configuration.Configuration; import java.util.ArrayList; import java.util.Collections; @@ -43,7 +45,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.nio.ByteBuffer; /** A simple message store that stores the messages in a threadsafe structure in memory. */ -public class MemoryMessageStore extends AbstractMessageStore +public class MemoryMessageStore implements MessageStore { private static final Logger _log = Logger.getLogger(MemoryMessageStore.class); @@ -51,52 +53,74 @@ public class MemoryMessageStore extends AbstractMessageStore private static final String HASHTABLE_CAPACITY_CONFIG = "hashtable-capacity"; - protected ConcurrentMap<Long, MessageMetaData> _metaDataMap; - - protected ConcurrentMap<Long, List<ContentChunk>> _contentBodyMap; private final AtomicLong _messageId = new AtomicLong(1); private AtomicBoolean _closed = new AtomicBoolean(false); private LogSubject _logSubject; - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception + private static final Transaction IN_MEMORY_TRANSACTION = new Transaction() { - super.configure(virtualHost,base,config); + public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + } - int hashtableCapacity = config.getStoreConfiguration().getInt(base + "." + HASHTABLE_CAPACITY_CONFIG, DEFAULT_HASHTABLE_CAPACITY); - _log.info("Using capacity " + hashtableCapacity + " for hash tables"); - _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>(hashtableCapacity); - _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>(hashtableCapacity); - } + public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + } - public void close() throws Exception - { - _closed.getAndSet(true); - if (_metaDataMap != null) + public void commitTran() throws AMQException + { + } + + public StoreFuture commitTranAsync() throws AMQException { - _metaDataMap.clear(); - _metaDataMap = null; + return IMMEDIATE_FUTURE; } - if (_contentBodyMap != null) + + public void abortTran() throws AMQException { - _contentBodyMap.clear(); - _contentBodyMap = null; } - super.close(); + }; + + public void configureConfigStore(String name, ConfigurationRecoveryHandler handler, Configuration configuration, LogSubject logSubject) throws Exception + { + _logSubject = logSubject; + CurrentActor.get().message(_logSubject, ConfigStoreMessages.CFG_1001(this.getClass().getName())); + + } - public void removeMessage(Long messageId) throws AMQException + public void configureMessageStore(String name, + MessageStoreRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception { - checkNotClosed(); - if (_log.isDebugEnabled()) + if(_logSubject == null) { - _log.debug("Removing message with id " + messageId); + _logSubject = logSubject; } - _metaDataMap.remove(messageId); - _contentBodyMap.remove(messageId); + int hashtableCapacity = config.getInt(name + "." + HASHTABLE_CAPACITY_CONFIG, DEFAULT_HASHTABLE_CAPACITY); + _log.info("Using capacity " + hashtableCapacity + " for hash tables"); + CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName())); } + public void close() throws Exception + { + _closed.getAndSet(true); + CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003()); + + } + + public StoredMessage addMessage(StorableMessageMetaData metaData) + { + final long id = _messageId.getAndIncrement(); + StoredMemoryMessage message = new StoredMemoryMessage(id, metaData); + + return message; + } + + public void createExchange(Exchange exchange) throws AMQException { @@ -133,53 +157,19 @@ public class MemoryMessageStore extends AbstractMessageStore // Not required to do anything } - public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception { - // Not required to do anything - } - - public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException - { - // Not required to do anything - } - - public void beginTran(StoreContext context) throws AMQException - { - // Not required to do anything - } - - public void commitTran(StoreContext context) throws AMQException - { - // 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() - { - - } - }; - + //To change body of implemented methods use File | Settings | File Templates. } - public void abortTran(StoreContext context) throws AMQException + public Transaction newTransaction() { - // Not required to do anything + return IN_MEMORY_TRANSACTION; } - public boolean inTran(StoreContext context) - { - return false; - } public List<AMQQueue> createQueues() throws AMQException { @@ -191,72 +181,11 @@ public class MemoryMessageStore extends AbstractMessageStore return _messageId.getAndIncrement(); } - public void storeContentBodyChunk( - Long messageId, - int index, - ContentChunk contentBody, - boolean lastContentBody) - throws AMQException - { - checkNotClosed(); - List<ContentChunk> bodyList = _contentBodyMap.get(messageId); - - if (bodyList == null && lastContentBody) - { - _contentBodyMap.put(messageId, Collections.singletonList(contentBody)); - } - else - { - if (bodyList == null) - { - bodyList = new ArrayList<ContentChunk>(); - _contentBodyMap.put(messageId, bodyList); - } - - bodyList.add(index, contentBody); - } - } - - public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) - throws AMQException - { - checkNotClosed(); - _metaDataMap.put(messageId, messageMetaData); - } - - public MessageMetaData getMessageMetaData(Long messageId) throws AMQException - { - checkNotClosed(); - return _metaDataMap.get(messageId); - } - - public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException - { - checkNotClosed(); - List<ContentChunk> bodyList = _contentBodyMap.get(messageId); - return bodyList.get(index); - } - public boolean isPersistent() { return false; } - public void storeMessageHeader(Long messageNumber, ServerMessage message) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void storeContent(Long messageNumber, long offset, ByteBuffer body) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public ServerMessage getMessage(Long messageNumber) - { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - private void checkNotClosed() throws MessageStoreClosedException { if (_closed.get()) @@ -264,4 +193,6 @@ public class MemoryMessageStore extends AbstractMessageStore throw new MessageStoreClosedException(); } } + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyContentHolder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java index 4ab6278715..428bb1e41b 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BodyContentHolder.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java @@ -18,24 +18,24 @@ * under the License. * */ +package org.apache.qpid.server.store; -package org.apache.qpid.server.queue; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.abstraction.ContentChunk; +import java.nio.ByteBuffer; -public interface BodyContentHolder +public enum MessageMetaDataType { - /** - * @return the number of body frames associated with this message - */ - int getBodyCount() throws AMQException; + META_DATA_0_8 { public Factory<MessageMetaData> getFactory() { return MessageMetaData.FACTORY; } }, + META_DATA_0_10 { public Factory<MessageMetaData_0_10> getFactory() { return MessageMetaData_0_10.FACTORY; } }; + + + public static interface Factory<M extends StorableMessageMetaData> + { + M createMetaData(ByteBuffer buf); + } + + abstract public Factory<? extends StorableMessageMetaData> getFactory(); - /** - * Get a particular content body - * @param index the index of the body to retrieve, must be between 0 and getBodyCount() - 1 - * @return a content body - * @throws IllegalArgumentException if the index is invalid - */ - ContentChunk getContentChunk(int index) throws IllegalArgumentException, AMQException; } 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 a30e6b485c..e2fca2f9c7 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,51 +20,43 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.queue.MessageMetaData; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.message.ServerMessage; - -import java.nio.ByteBuffer; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.commons.configuration.Configuration; /** - * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages, queues - * and exchanges in a transactional manner. - * - * <p/>All message store, remove, enqueue and dequeue operations are carried out against a {@link StoreContext} which - * encapsulates the transactional context they are performed in. Many such operations can be carried out in a single - * transaction. - * - * <p/>The storage and removal of queues and exchanges, are not carried out in a transactional context. + * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages. * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities - * <tr><td> Accept transaction boundary demarcations: Begin, Commit, Abort. - * <tr><td> Store and remove queues. - * <tr><td> Store and remove exchanges. - * <tr><td> Store and remove messages. - * <tr><td> Bind and unbind queues to exchanges. - * <tr><td> Enqueue and dequeue messages to queues. - * <tr><td> Generate message identifiers. - * </table> */ public interface MessageStore extends DurableConfigurationStore, TransactionLog { + StoreFuture IMMEDIATE_FUTURE = new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + + /** * Called after instantiation in order to configure the message store. A particular implementation can define * whatever parameters it wants. * - * @param virtualHost The virtual host using by this store - * @param base The base element identifier from which all configuration items are relative. For example, if - * the base element is "store", the all elements used by concrete classes will be "store.foo" etc. - * @param hostConfig The apache commons configuration object. + * @param name The name to be used by this storem + * @param recoveryHandler Handler to be called as the store recovers on start up + * @param config The apache commons configuration object. * * @throws Exception If any error occurs that means the store is unable to configure itself. */ - void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration hostConfig) throws Exception; + void configureMessageStore(String name, + MessageStoreRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception; /** * Called to close and cleanup any resources used by the message store. @@ -73,68 +65,9 @@ public interface MessageStore extends DurableConfigurationStore, TransactionLog */ void close() throws Exception; - /** - * Removes the specified message from the store in the given transactional store context. - * - * @param messageId Identifies the message to remove. - * - * @throws AMQException If the operation fails for any reason. - */ - void removeMessage(Long messageId) throws AMQException; - - /** - * Return a valid, currently unused message id. - * - * @return A fresh message id. - */ - Long getNewMessageId(); + public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData); - /** - * Stores a chunk of message data. - * - * @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. - * @param lastContentBody Flag to indicate that this is the last such chunk for the message. - * - * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. - */ - void storeContentBodyChunk(Long messageId, int index, ContentChunk contentBody, - boolean lastContentBody) throws AMQException; - - /** - * Stores message meta-data. - * - * @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(Long messageId, MessageMetaData messageMetaData) throws AMQException; - - /** - * Retrieves message meta-data. - * - * @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(Long messageId) throws AMQException; - - /** - * Retrieves a chunk of message data. - * - * @param messageId The message to get the data chunk for. - * @param index The offset index of the data chunk within the message. - * - * @return A chunk of message data. - * - * @throws AMQException If the operation fails for any reason, or if the specified message does not exist. - */ - ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException; /** * Is this store capable of persisting the data @@ -143,9 +76,5 @@ public interface MessageStore extends DurableConfigurationStore, TransactionLog */ boolean isPersistent(); - void storeMessageHeader(Long messageNumber, ServerMessage message); - - void storeContent(Long messageNumber, long offset, ByteBuffer body); - ServerMessage getMessage(Long messageNumber); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java new file mode 100755 index 0000000000..ba65b8e1ec --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java @@ -0,0 +1,33 @@ +/* +* +* 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; + +public interface MessageStoreRecoveryHandler +{ + StoredMessageRecoveryHandler begin(); + + public static interface StoredMessageRecoveryHandler + { + void message(StoredMessage message); + + void completeMessageRecovery(); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java index 434c2bde71..12d2a6a6c7 100644..100755 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java @@ -18,18 +18,19 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.store; -public class MockAMQMessageHandle extends InMemoryMessageHandle +import java.nio.ByteBuffer; + +public interface StorableMessageMetaData { - public MockAMQMessageHandle(final Long messageId) - { - super(messageId); - } + MessageMetaDataType getType(); + + int getStorableSize(); + + int writeToBuffer(int offsetInMetaData, ByteBuffer dest); + + int getContentSize(); - @Override - public long getBodySize() - { - return 0l; - } + boolean isPersistent(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java new file mode 100755 index 0000000000..867fb4f9c7 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java @@ -0,0 +1,80 @@ +/* + * + * 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 java.nio.ByteBuffer; + +public class StoredMemoryMessage implements StoredMessage +{ + private final long _messageNumber; + private final ByteBuffer _content; + private final StorableMessageMetaData _metaData; + + StoredMemoryMessage(long messageNumber, StorableMessageMetaData metaData) + { + _messageNumber = messageNumber; + _metaData = metaData; + _content = ByteBuffer.allocate(metaData.getContentSize()); + + } + + public long getMessageNumber() + { + return _messageNumber; + } + + public void addContent(int offsetInMessage, ByteBuffer src) + { + src = src.duplicate(); + ByteBuffer dst = _content.duplicate(); + dst.position(offsetInMessage); + dst.put(src); + } + + public int getContent(int offset, ByteBuffer dst) + { + ByteBuffer src = _content.duplicate(); + src.position(offset); + src = src.slice(); + if(dst.remaining() < src.limit()) + { + src.limit(dst.remaining()); + } + dst.put(src); + return src.limit(); + } + + public TransactionLog.StoreFuture flushToStore() + { + return MessageStore.IMMEDIATE_FUTURE; + } + + + public StorableMessageMetaData getMetaData() + { + return _metaData; + } + + public void remove() + { + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java new file mode 100755 index 0000000000..0bc45c6718 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java @@ -0,0 +1,38 @@ +/* +* +* 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 java.nio.ByteBuffer; + +public interface StoredMessage<M extends StorableMessageMetaData> +{ + M getMetaData(); + + public long getMessageNumber(); + + void addContent(int offsetInMessage, ByteBuffer src); + + int getContent(int offsetInMessage, ByteBuffer dst); + + TransactionLog.StoreFuture flushToStore(); + + void remove(); +} 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 index acbf95a9d6..e6a33e23d6 100755 --- 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 @@ -21,74 +21,67 @@ package org.apache.qpid.server.store; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.AMQException; +import org.apache.commons.configuration.Configuration; 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 Transaction + { + /** + * Places a message onto a specified queue, in a given transactional context. + * + * @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(TransactionLogResource queue, Long messageId) throws AMQException; + + /** + * Extracts a message from a specified queue, in a given transactional context. + * + * @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(TransactionLogResource queue, Long messageId) throws AMQException; + + + /** + * Commits all operations performed within a given transactional context. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void commitTran() throws AMQException; + + /** + * Commits all operations performed within a given transactional context. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + StoreFuture commitTranAsync() throws AMQException; + + /** + * Abandons all operations performed within a given transactional context. + * + * @throws org.apache.qpid.AMQException If the operation fails for any reason. + */ + void abortTran() throws AMQException; + + + + } + + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception; + + Transaction newTransaction(); + + public static interface StoreFuture { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java new file mode 100755 index 0000000000..7781c52df3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java @@ -0,0 +1,33 @@ +/* +* +* 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; + +public interface TransactionLogRecoveryHandler +{ + QueueEntryRecoveryHandler begin(TransactionLog log); + + public static interface QueueEntryRecoveryHandler + { + void queueEntry(String queuename, long messageId); + + void completeQueueEntryRecovery(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java new file mode 100755 index 0000000000..0d81dd151d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java @@ -0,0 +1,26 @@ +/* +* +* 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; + +public interface TransactionLogResource +{ + public String getResourceName(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java new file mode 100755 index 0000000000..b49b12fb79 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java @@ -0,0 +1,93 @@ +/* + * + * 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.subscription; + +import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.log4j.Logger; + + +class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener +{ + private static final Logger _logger = Logger.getLogger(ExplicitAcceptDispositionChangeListener.class); + + + private final QueueEntry _entry; + private final Subscription_0_10 _sub; + + public ExplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) + { + _entry = entry; + _sub = subscription_0_10; + } + + public void onAccept() + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.getSession().acknowledge(subscription, _entry); + } + else + { + _logger.warn("MessageAccept received for message which has not been acquired (likely client error)"); + } + + } + + public void onRelease() + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.release(_entry); + } + else + { + _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); + } + } + + public void onReject() + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.reject(_entry); + } + else + { + _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); + } + + } + + public boolean acquire() + { + return _entry.acquire(getSubscription()); + } + + + private Subscription_0_10 getSubscription() + { + return _sub; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java new file mode 100755 index 0000000000..b5bb2014b5 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java @@ -0,0 +1,86 @@ +/* + * + * 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.subscription; + +import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.log4j.Logger; + +class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener +{ + private static final Logger _logger = Logger.getLogger(ImplicitAcceptDispositionChangeListener.class); + + + private final QueueEntry _entry; + private Subscription_0_10 _sub; + + public ImplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) + { + _entry = entry; + _sub = subscription_0_10; + } + + public void onAccept() + { + _logger.warn("MessageAccept received for message which is using NONE as the accept mode (likely client error)"); + } + + public void onRelease() + { + if(_entry.isAcquiredBy(_sub)) + { + getSubscription().release(_entry); + } + else + { + _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); + } + } + + public void onReject() + { + if(_entry.isAcquiredBy(_sub)) + { + getSubscription().reject(_entry); + } + else + { + _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); + } + + } + + public boolean acquire() + { + boolean acquired = _entry.acquire(getSubscription()); + //TODO - why acknowledge here??? seems bizarre... + // getSubscription().getSession().acknowledge(getSubscription(), _entry); + return acquired; + + } + + public Subscription_0_10 getSubscription() + { + return _sub; + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java index a980347633..8a2a370236 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java @@ -43,11 +43,15 @@ public class MessageAcceptCompletionListener implements Method.CompletionListene public void onComplete(Method method) { - _session.acknowledge(_sub, _entry); if(_restoreCredit) { _sub.restoreCredit(_entry); } - _session.removeDispositionListener(method); + if(_entry.isAcquiredBy(_sub)) + { + _session.acknowledge(_sub, _entry); + } + + _session.removeDispositionListener(method); } } 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 0d317c449d..4db9c305b2 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 @@ -51,6 +51,8 @@ public interface Subscription void setQueue(AMQQueue queue, boolean exclusive); + void setNoLocal(boolean noLocal); + AMQShortString getConsumerTag(); long getSubscriptionID(); @@ -71,7 +73,7 @@ public interface Subscription void send(QueueEntry msg) throws AMQException; - void queueDeleted(AMQQueue queue); + void queueDeleted(AMQQueue queue); boolean wouldSuspend(QueueEntry msg); @@ -97,5 +99,8 @@ public interface Subscription void confirmAutoClose(); + public void set(String key, Object value); + + public Object get(String key); } 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 e7ace4eb55..bb2e5ae918 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 @@ -25,6 +25,8 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; @@ -33,6 +35,7 @@ import org.apache.qpid.common.ClientProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.SubscriptionActor; @@ -42,7 +45,6 @@ import org.apache.qpid.server.logging.LogSubject; 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.flow.FlowCreditManager; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; @@ -74,6 +76,8 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this); + private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>(); + private final Lock _stateChangeLock; private static final AtomicLong idGenerator = new AtomicLong(0); @@ -254,7 +258,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final AMQShortString _consumerTag; - private final boolean _noLocal; + private boolean _noLocal; private final FlowCreditManager _creditManager; @@ -410,11 +414,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public boolean hasInterest(QueueEntry entry) { - // TODO 0-10 to 0-8 conversion - if(!(entry.getMessage() instanceof AMQMessage)) - { - return false; - } + //check that the message hasn't been rejected @@ -667,5 +667,21 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return !isBrowser(); } + public void set(String key, Object value) + { + _properties.put(key, value); + } + + public Object get(String key) + { + return _properties.get(key); + } + + + public void setNoLocal(boolean noLocal) + { + _noLocal = noLocal; + } + abstract boolean isBrowser(); } 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 2669475a63..fb0a5cf2c7 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 @@ -29,14 +29,18 @@ import org.apache.qpid.server.flow.FlowCreditManager_0_10; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.SubscriptionActor; -import org.apache.qpid.server.logging.messages.SubscriptionMessages; import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; import org.apache.qpid.server.logging.LogSubject; 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.message.AMQMessage; import org.apache.qpid.server.transport.ServerSession; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ContentHeaderProperties; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.AMQTypedValue; import org.apache.qpid.AMQException; import org.apache.qpid.transport.*; @@ -47,6 +51,9 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.nio.ByteBuffer; public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener { @@ -90,6 +97,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private LogSubject _logSubject; private LogActor _logActor; + private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>(); public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode, @@ -111,6 +119,11 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } + public void setNoLocal(boolean noLocal) + { + _noLocal = noLocal; + } + public AMQQueue getQueue() { return _queue; @@ -135,7 +148,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr _queue = queue; _logSubject = new SubscriptionLogSubject(this); _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); - + } public AMQShortString getConsumerTag() @@ -151,11 +164,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr public boolean hasInterest(QueueEntry entry) { - //TODO 0-8/9 to 0-10 conversion - if(!(entry.getMessage() instanceof MessageTransferMessage)) - { - return false; - } + //check that the message hasn't been rejected if (entry.isRejectedBy(this)) @@ -261,70 +270,164 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } + private class AddMessageDispositionListnerAction implements Runnable + { + public MessageTransfer _xfr; + public ServerSession.MessageDispositionChangeListener _action; + + public void run() + { + _session.onMessageDispositionChange(_xfr, _action); + } + } + + private final AddMessageDispositionListnerAction _postIdSettingAction = new AddMessageDispositionListnerAction(); + public void send(final QueueEntry entry) throws AMQException { ServerMessage serverMsg = entry.getMessage(); - MessageTransferMessage msg = (MessageTransferMessage) serverMsg; - + MessageTransfer xfr; - Struct[] headers; - if(msg.getHeader() == null) - { - headers = EMPTY_STRUCT_ARRAY; - } - else + if(serverMsg instanceof MessageTransferMessage) { - headers = msg.getHeader().getStructs(); - } - ArrayList<Struct> newHeaders = new ArrayList<Struct>(headers.length); - DeliveryProperties origDeliveryProps = null; - for(Struct header : headers) - { - if(header instanceof DeliveryProperties) + MessageTransferMessage msg = (MessageTransferMessage) serverMsg; + + + Struct[] headers; + if(msg.getHeader() == null) { - origDeliveryProps = (DeliveryProperties) header; + headers = EMPTY_STRUCT_ARRAY; } else { - newHeaders.add(header); + headers = msg.getHeader().getStructs(); } - } - DeliveryProperties deliveryProps = new DeliveryProperties(); - if(origDeliveryProps != null) - { - if(origDeliveryProps.hasDeliveryMode()) + ArrayList<Struct> newHeaders = new ArrayList<Struct>(headers.length); + DeliveryProperties origDeliveryProps = null; + for(Struct header : headers) { - deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); + if(header instanceof DeliveryProperties) + { + origDeliveryProps = (DeliveryProperties) header; + } + else + { + newHeaders.add(header); + } } - if(origDeliveryProps.hasExchange()) + + DeliveryProperties deliveryProps = new DeliveryProperties(); + if(origDeliveryProps != null) + { + if(origDeliveryProps.hasDeliveryMode()) + { + deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); + } + if(origDeliveryProps.hasExchange()) + { + deliveryProps.setExchange(origDeliveryProps.getExchange()); + } + if(origDeliveryProps.hasExpiration()) + { + deliveryProps.setExpiration(origDeliveryProps.getExpiration()); + } + if(origDeliveryProps.hasPriority()) + { + deliveryProps.setPriority(origDeliveryProps.getPriority()); + } + if(origDeliveryProps.hasRoutingKey()) + { + deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); + } + + } + + deliveryProps.setRedelivered(entry.isRedelivered()); + + newHeaders.add(deliveryProps); + Header header = new Header(newHeaders); + + xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); + } + else + { + AMQMessage message_0_8 = (AMQMessage) serverMsg; + DeliveryProperties deliveryProps = new DeliveryProperties(); + MessageProperties messageProps = new MessageProperties(); + + int size = (int) message_0_8.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + message_0_8.getContent(body, 0); + body.flip(); + + Struct[] headers = new Struct[] { deliveryProps, messageProps }; + + BasicContentHeaderProperties properties = + (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().properties; + final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); + if(exchange != null) { - deliveryProps.setExchange(origDeliveryProps.getExchange()); + deliveryProps.setExchange(exchange.toString()); } - if(origDeliveryProps.hasExpiration()) + deliveryProps.setExpiration(message_0_8.getExpiration()); + deliveryProps.setImmediate(message_0_8.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority())); + deliveryProps.setRedelivered(entry.isRedelivered()); + deliveryProps.setRoutingKey(message_0_8.getRoutingKey()); + deliveryProps.setTimestamp(properties.getTimestamp()); + + messageProps.setContentEncoding(properties.getEncodingAsString()); + messageProps.setContentLength(size); + if(properties.getAppId() != null) { - deliveryProps.setExpiration(origDeliveryProps.getExpiration()); + messageProps.setAppId(properties.getAppId().getBytes()); } - if(origDeliveryProps.hasPriority()) + messageProps.setContentType(properties.getContentTypeAsString()); + if(properties.getCorrelationId() != null) { - deliveryProps.setPriority(origDeliveryProps.getPriority()); + messageProps.setCorrelationId(properties.getCorrelationId().getBytes()); } - if(origDeliveryProps.hasRoutingKey()) + + // TODO - ReplyTo + + if(properties.getUserId() != null) { - deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); + messageProps.setUserId(properties.getUserId().getBytes()); } - } + final Map<String, Object> appHeaders = new HashMap<String, Object>(); + + properties.getHeaders().processOverElements( + new FieldTable.FieldTableElementProcessor() + { - deliveryProps.setRedelivered(entry.isRedelivered()); + public boolean processElement(String propertyName, AMQTypedValue value) + { + Object val = value.getValue(); + if(val instanceof AMQShortString) + { + val = val.toString(); + } + appHeaders.put(propertyName, val); + return true; + } - newHeaders.add(deliveryProps); - Header header = new Header(newHeaders); + public Object getResult() + { + return appHeaders; + } + }); - MessageTransfer xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); + + messageProps.setApplicationHeaders(appHeaders); + + Header header = new Header(headers); + xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + } if(_acceptMode == MessageAcceptMode.NONE) { @@ -342,81 +445,30 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } - - _session.sendMessage(xfr); - + _postIdSettingAction._xfr = xfr; if(_acceptMode == MessageAcceptMode.EXPLICIT) { - // potential race condition if incomming commands on this session can be processed on a different thread - // to this one (i.e. the message is only put in the map *after* it has been sent, theoretically we could get - // acknowledgement back before reaching the next line) - _session.onMessageDispositionChange(xfr, new ServerSession.MessageDispositionChangeListener() - { - public void onAccept() - { - _session.acknowledge(Subscription_0_10.this,entry); - } - - public void onRelease() - { - release(entry); - } - - public void onReject() - { - reject(entry); - } - - public boolean acquire() - { - return entry.acquire(Subscription_0_10.this); - } - }); + _postIdSettingAction._action = new ExplicitAcceptDispositionChangeListener(entry, this); } else { - _session.onMessageDispositionChange(xfr, new ServerSession.MessageDispositionChangeListener() - { - public void onAccept() - { - // TODO : should log error of explicit accept on non-explicit sub - } - - public void onRelease() - { - release(entry); - } - - public void onReject() - { - reject(entry); - } - - 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; - - } - - }); + _postIdSettingAction._action = new ImplicitAcceptDispositionChangeListener(entry, this); } + _session.sendMessage(xfr, _postIdSettingAction); } - private void reject(QueueEntry entry) + void reject(QueueEntry entry) { - entry.setRedelivered(true); + entry.setRedelivered(); entry.routeToAlternate(); } - private void release(QueueEntry entry) + void release(QueueEntry entry) { - entry.setRedelivered(true); + entry.setRedelivered(); entry.release(); } @@ -480,6 +532,16 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr //No such thing in 0-10 } + public void set(String key, Object value) + { + _properties.put(key, value); + } + + public Object get(String key) + { + return _properties.get(key); + } + public FlowCreditManager_0_10 getCreditManager() { @@ -565,8 +627,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr public void acknowledge(QueueEntry entry) { // TODO Fix Store Context / cleanup - - entry.discard(); + if(entry.isAcquiredBy(this)) + { + entry.discard(); + } } public void flush() throws AMQException @@ -585,5 +649,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _logActor; } + ServerSession getSession() + { + return _session; + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index 3a61099386..2a8b99ddac 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.transport; import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; import org.apache.qpid.transport.Method; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -36,7 +35,7 @@ public class ServerConnection extends Connection @Override protected void setState(State state) { - super.setState(state); + super.setState(state); } @Override diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java index 0f65fc10ce..cfc5bb3a72 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java @@ -22,8 +22,6 @@ package org.apache.qpid.server.transport; import org.apache.qpid.transport.*; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; 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 c0db61cf3a..77dfbc0376 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 @@ -25,10 +25,10 @@ import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.ServerTransaction; 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.security.PrincipalHolder; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.AMQException; @@ -46,7 +46,6 @@ public class ServerSession extends Session implements PrincipalHolder { private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); - public static interface MessageDispositionChangeListener { public void onAccept(); @@ -69,7 +68,7 @@ public class ServerSession extends Session implements PrincipalHolder private final SortedMap<Integer, MessageDispositionChangeListener> _messageDispositionListenerMap = new ConcurrentSkipListMap<Integer, MessageDispositionChangeListener>(); - private Transaction _transaction; + private ServerTransaction _transaction; private Principal _principal; @@ -97,10 +96,16 @@ public class ServerSession extends Session implements PrincipalHolder _reference = new WeakReference(this); } + @Override + protected boolean isFull(int id) + { + return isCommandsFull(id); + } + public void enqueue(final ServerMessage message, final ArrayList<AMQQueue> queues) { - _transaction.enqueue(queues,message, new Transaction.Action() + _transaction.enqueue(queues,message, new ServerTransaction.Action() { AMQQueue[] _queues = queues.toArray(new AMQQueue[queues.size()]); @@ -117,6 +122,7 @@ public class ServerSession extends Session implements PrincipalHolder { // TODO e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + throw new RuntimeException(e); } } } @@ -130,10 +136,11 @@ public class ServerSession extends Session implements PrincipalHolder } - - public void sendMessage(MessageTransfer xfr) + + public void sendMessage(MessageTransfer xfr, + Runnable postIdSettingAction) { - invoke(xfr); + invoke(xfr, postIdSettingAction); } public void onMessageDispositionChange(MessageTransfer xfr, MessageDispositionChangeListener acceptListener) @@ -231,12 +238,12 @@ public class ServerSession extends Session implements PrincipalHolder public void dispositionChange(RangeSet ranges, MessageDispositionAction action) { - if(!_messageDispositionListenerMap.isEmpty()) + if(ranges != null && !_messageDispositionListenerMap.isEmpty()) { Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); Iterator<Range> rangeIter = ranges.iterator(); - if(rangeIter.hasNext()) + if(rangeIter.hasNext()) { Range range = rangeIter.next(); @@ -266,7 +273,6 @@ public class ServerSession extends Session implements PrincipalHolder } - } } @@ -287,14 +293,14 @@ public class ServerSession extends Session implements PrincipalHolder for (Task task : _taskList) { task.doTask(this); - } + } } public void acknowledge(final Subscription_0_10 sub, final QueueEntry entry) { _transaction.dequeue(entry.getQueue(), entry.getMessage(), - new Transaction.Action() + new ServerTransaction.Action() { public void postCommit() @@ -307,7 +313,6 @@ public class ServerSession extends Session implements PrincipalHolder entry.release(); } }); - } public Collection<Subscription_0_10> getSubscriptions() 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 1b0ea41e0b..df2754c16b 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 @@ -29,15 +29,19 @@ import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.message.MessageMetaData_0_10; import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.flow.*; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUnknownExchangeType; import org.apache.qpid.framing.*; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; public class ServerSessionDelegate extends SessionDelegate { @@ -205,20 +209,19 @@ public class ServerSessionDelegate extends SessionDelegate } - - - MessageTransferMessage message = new MessageTransferMessage(xfr, ((ServerSession)ssn).getReference()); - final MessageStore store = getVirtualHost(ssn).getMessageStore(); - - store.storeMessageHeader(message.getMessageNumber(),message); - store.storeContent(message.getMessageNumber(), 0, xfr.getBody()); - DeliveryProperties delvProps = null; - if(message.getHeader() != null && (delvProps = message.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration()) + if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration()) { delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); } + MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); + final MessageStore store = getVirtualHost(ssn).getMessageStore(); + StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData); + storeMessage.addContent(0,xfr.getBody()); + storeMessage.flushToStore(); + MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference()); + ArrayList<AMQQueue> queues = exchange.route(message); @@ -267,8 +270,6 @@ public class ServerSessionDelegate extends SessionDelegate ssn.processed(xfr); - - super.messageTransfer(ssn, xfr); //To change body of overridden methods use File | Settings | File Templates. } @Override @@ -397,6 +398,11 @@ public class ServerSessionDelegate extends SessionDelegate exchange.setAlternateExchange(alternate); } + if (exchange.isDurable() && !exchange.isAutoDelete()) + { + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + store.createExchange(exchange); + } exchangeRegistry.registerExchange(exchange); } @@ -407,7 +413,6 @@ public class ServerSessionDelegate extends SessionDelegate catch (AMQException e) { //TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } @@ -431,7 +436,7 @@ public class ServerSessionDelegate extends SessionDelegate ex.setDescription(description); session.invoke(ex); - //session.close(); + } private Exchange getExchange(Session session, String exchangeName) @@ -487,6 +492,13 @@ public class ServerSessionDelegate extends SessionDelegate else { exchangeRegistry.unregisterExchange(method.getExchange(), method.getIfUnused()); + + if (exchange.isDurable() && !exchange.isAutoDelete()) + { + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + store.removeExchange(exchange); + } + } } catch (ExchangeInUseException e) @@ -496,7 +508,6 @@ public class ServerSessionDelegate extends SessionDelegate catch (AMQException e) { // TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } } @@ -585,6 +596,7 @@ public class ServerSessionDelegate extends SessionDelegate if (!exchange.isBound(routingKey, fieldTable, queue)) { queue.bind(exchange, routingKey, fieldTable); + } else { @@ -607,7 +619,7 @@ public class ServerSessionDelegate extends SessionDelegate @Override public void exchangeUnbind(Session session, ExchangeUnbind method) { - VirtualHost virtualHost = getVirtualHost(session); + VirtualHost virtualHost = getVirtualHost(session); ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry(); QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); @@ -643,7 +655,6 @@ public class ServerSessionDelegate extends SessionDelegate } catch (AMQException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } } @@ -761,6 +772,7 @@ public class ServerSessionDelegate extends SessionDelegate { VirtualHost virtualHost = getVirtualHost(session); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); String queueName = method.getQueue(); @@ -818,10 +830,35 @@ public class ServerSessionDelegate extends SessionDelegate queue.setAlternateExchange(alternate); } + if(method.hasArguments() && method.getArguments() != null) + { + if(method.getArguments().containsKey("no-local")) + { + Object no_local = method.getArguments().get("no-local"); + if(no_local instanceof Boolean && ((Boolean)no_local)) + { + queue.setNoLocal(true); + } + } + } + if (queue.isDurable() && !queue.isAutoDelete()) { - //store.createQueue(queue, body.getArguments()); + if(method.hasArguments() && method.getArguments() != null) + { + Map<String,Object> args = method.getArguments(); + FieldTable ftArgs = new FieldTable(); + for(Map.Entry<String, Object> entry : args.entrySet()) + { + ftArgs.put(new AMQShortString(entry.getKey()), entry.getValue()); + } + store.createQueue(queue, ftArgs); + } + else + { + store.createQueue(queue); + } } queueRegistry.registerQueue(queue); boolean autoRegister = ApplicationRegistry.getInstance().getConfiguration().getQueueAutoRegister(); @@ -853,8 +890,7 @@ public class ServerSessionDelegate extends SessionDelegate } catch (AMQException e) { - //TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + throw new RuntimeException(e); } } }; @@ -896,7 +932,6 @@ public class ServerSessionDelegate extends SessionDelegate } catch (AMQException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } } @@ -948,7 +983,6 @@ public class ServerSessionDelegate extends SessionDelegate catch (AMQException e) { //TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } } @@ -1018,19 +1052,19 @@ public class ServerSessionDelegate extends SessionDelegate try { int purged = queue.delete(); + if (queue.isDurable() && !queue.isAutoDelete()) + { + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + store.removeQueue(queue); + } + } catch (AMQException e) { //TODO - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. throw new RuntimeException(e); } - - /* if (queue.isDurable()) - { - store.removeQueue(queue); - }*/ } } 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 4afaa39a0d..7b29106ba6 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 @@ -24,14 +24,13 @@ 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 +public class AutoCommitTransaction implements ServerTransaction { private final TransactionLog _transactionLog; @@ -55,13 +54,11 @@ public class AutoCommitTransaction implements Transaction if(message.isPersistent() && queue.isDurable()) { - StoreContext context = new StoreContext(); - - _transactionLog.beginTran(context); - _transactionLog.dequeueMessage(context, queue, message.getMessageNumber()); + TransactionLog.Transaction txn = _transactionLog.newTransaction(); + txn.dequeueMessage(queue, message.getMessageNumber()); // store.remove enqueue // store.commit - _transactionLog.commitTran(context); + txn.commitTran(); } postCommitAction.postCommit(); } @@ -77,7 +74,7 @@ public class AutoCommitTransaction implements Transaction { try { - StoreContext context = null; + TransactionLog.Transaction txn = null; for(QueueEntry entry : ackedMessages) { ServerMessage message = entry.getMessage(); @@ -85,18 +82,17 @@ public class AutoCommitTransaction implements Transaction if(message.isPersistent() && queue.isDurable()) { - if(context == null) + if(txn == null) { - context = new StoreContext(); - _transactionLog.beginTran(context); + txn = _transactionLog.newTransaction(); } - _transactionLog.dequeueMessage(context, queue, message.getMessageNumber()); + txn.dequeueMessage(queue, message.getMessageNumber()); } } - if(context != null) + if(txn != null) { - _transactionLog.commitTran(context); + txn.commitTran(); } postCommitAction.postCommit(); } @@ -115,11 +111,10 @@ public class AutoCommitTransaction implements Transaction { if(message.isPersistent() && queue.isDurable()) { - StoreContext context = new StoreContext(); - _transactionLog.beginTran(context); - _transactionLog.enqueueMessage(context, queue, message.getMessageNumber()); - _transactionLog.commitTran(context); + TransactionLog.Transaction txn = _transactionLog.newTransaction(); + txn.enqueueMessage(queue, message.getMessageNumber()); + txn.commitTran(); } postCommitAction.postCommit(); } @@ -140,19 +135,16 @@ public class AutoCommitTransaction implements Transaction if(message.isPersistent()) { - StoreContext context = new StoreContext(); - - _transactionLog.beginTran(context); - + TransactionLog.Transaction txn = _transactionLog.newTransaction(); Long id = message.getMessageNumber(); for(AMQQueue q : queues) { if(q.isDurable()) { - _transactionLog.enqueueMessage(context, q, id); + txn.enqueueMessage(q, id); } } - _transactionLog.commitTran(context); + txn.commitTran(); } postCommitAction.postCommit(); 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 380486dde7..9997fbe767 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 @@ -4,7 +4,6 @@ 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; @@ -12,11 +11,11 @@ import java.util.List; import java.util.ArrayList; import java.util.Collection; -public class LocalTransaction implements Transaction +public class LocalTransaction implements ServerTransaction { private final List<Action> _postCommitActions = new ArrayList<Action>(); - private volatile StoreContext _storeContext; + private volatile TransactionLog.Transaction _transaction; private TransactionLog _transactionLog; public LocalTransaction(TransactionLog transactionLog) @@ -37,7 +36,7 @@ public class LocalTransaction implements Transaction { beginTranIfNecessary(); - _transactionLog.dequeueMessage(_storeContext, queue, message.getMessageNumber()); + _transaction.dequeueMessage(queue, message.getMessageNumber()); } catch(AMQException e) @@ -60,7 +59,7 @@ public class LocalTransaction implements Transaction if(message.isPersistent() && queue.isDurable()) { beginTranIfNecessary(); - _transactionLog.dequeueMessage(_storeContext, queue, message.getMessageNumber()); + _transaction.dequeueMessage(queue, message.getMessageNumber()); } } @@ -70,10 +69,10 @@ public class LocalTransaction implements Transaction tidyUpOnError(e); } _postCommitActions.add(postCommitAction); - + } - private void tidyUpOnError(AMQException e) + private void tidyUpOnError(Exception e) { try { @@ -86,13 +85,13 @@ public class LocalTransaction implements Transaction { try { - _transactionLog.abortTran(_storeContext); + _transaction.abortTran(); } - catch (AMQException e1) + catch (Exception e1) { // TODO could try to chain the information to the original error } - _storeContext = null; + _transaction = null; _postCommitActions.clear(); } @@ -101,14 +100,13 @@ public class LocalTransaction implements Transaction private void beginTranIfNecessary() { - if(_storeContext == null) + if(_transaction == null) { - _storeContext = new StoreContext(); try { - _transactionLog.beginTran(_storeContext); + _transaction = _transactionLog.newTransaction(); } - catch (AMQException e) + catch (Exception e) { tidyUpOnError(e); } @@ -122,9 +120,9 @@ public class LocalTransaction implements Transaction beginTranIfNecessary(); try { - _transactionLog.enqueueMessage(_storeContext, queue, message.getMessageNumber()); + _transaction.enqueueMessage(queue, message.getMessageNumber()); } - catch (AMQException e) + catch (Exception e) { tidyUpOnError(e); } @@ -137,10 +135,10 @@ public class LocalTransaction implements Transaction public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction) { - + if(message.isPersistent()) { - if(_storeContext == null) + if(_transaction == null) { for(AMQQueue queue : queues) { @@ -161,12 +159,12 @@ public class LocalTransaction implements Transaction { if(queue.isDurable()) { - _transactionLog.enqueueMessage(_storeContext, queue, message.getMessageNumber()); + _transaction.enqueueMessage(queue, message.getMessageNumber()); } } } - catch (AMQException e) + catch (Exception e) { tidyUpOnError(e); } @@ -180,10 +178,10 @@ public class LocalTransaction implements Transaction { try { - if(_storeContext != null) + if(_transaction != null) { - _transactionLog.commitTran(_storeContext); + _transaction.commitTran(); } for(Action action : _postCommitActions) @@ -191,7 +189,7 @@ public class LocalTransaction implements Transaction action.postCommit(); } } - catch (AMQException e) + catch (Exception e) { for(Action action : _postCommitActions) { @@ -202,7 +200,7 @@ public class LocalTransaction implements Transaction } finally { - _storeContext = null; + _transaction = null; _postCommitActions.clear(); } @@ -214,10 +212,10 @@ public class LocalTransaction implements Transaction try { - if(_storeContext != null) + if(_transaction != null) { - _transactionLog.abortTran(_storeContext); + _transaction.abortTran(); } } catch (AMQException e) @@ -237,7 +235,7 @@ public class LocalTransaction implements Transaction } finally { - _storeContext = null; + _transaction = null; _postCommitActions.clear(); } } 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/ServerTransaction.java index dc91f31130..88bdc363c4 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/ServerTransaction.java @@ -30,7 +30,7 @@ import java.util.List; import java.util.SortedSet; import java.util.Collection; -public interface Transaction +public interface ServerTransaction { void addPostCommitAction(Action postCommitAction); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java deleted file mode 100644 index cf5e71a6e2..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java +++ /dev/null @@ -1,38 +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.util; - -import java.util.concurrent.ConcurrentLinkedQueue; - -public class ConcurrentLinkedQueueNoSize<E> extends ConcurrentLinkedQueue<E> -{ - public int size() - { - if (isEmpty()) - { - return 0; - } - else - { - return 1; - } - } -} 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 eccdce1ebc..e4a382d275 100644..100755 --- 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 @@ -1,576 +1,62 @@ /* - * - * 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. - * - */ +* +* 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.virtualhost; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -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.AMQBrokerManagerMBean; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.VirtualHostMessages; -import org.apache.qpid.server.configuration.ExchangeConfiguration; -import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.connection.ConnectionRegistry; import org.apache.qpid.server.connection.IConnectionRegistry; -import org.apache.qpid.server.exchange.DefaultExchangeFactory; -import org.apache.qpid.server.exchange.DefaultExchangeRegistry; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.DefaultQueueRegistry; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.queue.QueueRegistry; -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.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.access.ACLManager; +import org.apache.qpid.server.management.ManagedObject; -import javax.management.NotCompliantMBeanException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -public class VirtualHost implements Accessable +public interface VirtualHost { - private static final Logger _logger = Logger.getLogger(VirtualHost.class); - - private final String _name; - - private ConnectionRegistry _connectionRegistry; - - private QueueRegistry _queueRegistry; - - private ExchangeRegistry _exchangeRegistry; - - private ExchangeFactory _exchangeFactory; - - private MessageStore _messageStore; - - protected VirtualHostMBean _virtualHostMBean; - - private AMQBrokerManagerMBean _brokerMBean; - - private AuthenticationManager _authenticationManager; - - private ACLManager _accessManager; - - private final Timer _houseKeepingTimer; - private VirtualHostConfiguration _configuration; - private DurableConfigurationStore _durableConfigurationStore; - - public void setAccessableName(String name) - { - _logger.warn("Setting Accessable Name for VirualHost is not allowed. (" - + name + ") ignored remains :" + getAccessableName()); - } - - public String getAccessableName() - { - return _name; - } - - public IConnectionRegistry getConnectionRegistry() - { - return _connectionRegistry; - } - - public VirtualHostConfiguration getConfiguration() - { - return _configuration; - } - - /** - * Abstract MBean class. This has some of the methods implemented from management intrerface for exchanges. Any - * implementaion of an Exchange MBean should extend this class. - */ - public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost - { - public VirtualHostMBean() throws NotCompliantMBeanException - { - super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE, ManagedVirtualHost.VERSION); - } - - public String getObjectInstanceName() - { - return _name.toString(); - } - - public String getName() - { - return _name.toString(); - } - - public VirtualHost getVirtualHost() - { - return VirtualHost.this; - } - - } // End of MBean class - - /** - * Normal Constructor - * - * @param hostConfig - * - * @throws Exception - */ - public VirtualHost(VirtualHostConfiguration hostConfig) throws Exception - { - this(hostConfig, null); - } - - public VirtualHost(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception - { - _configuration = hostConfig; - _name = hostConfig.getName(); - - CurrentActor.get().message(VirtualHostMessages.VHT_1001(_name)); - - if (_name == null || _name.length() == 0) - { - throw new IllegalArgumentException("Illegal name (" + _name + ") for virtualhost."); - } - - _virtualHostMBean = new VirtualHostMBean(); - - _connectionRegistry = new ConnectionRegistry(this); - - _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true); - - _queueRegistry = new DefaultQueueRegistry(this); - - _exchangeFactory = new DefaultExchangeFactory(this); - _exchangeFactory.initialise(hostConfig); - - _exchangeRegistry = new DefaultExchangeRegistry(this); - - //Create a temporary RT to store the durable entries from the config file - // so we can replay them in to the real _RT after it has been loaded. - /// This should be removed after the _RT has been fully split from the the TL - - StartupRoutingTable configFileRT = new StartupRoutingTable(); - - _durableConfigurationStore = configFileRT; - - // This needs to be after the RT has been defined as it creates the default durable exchanges. - _exchangeRegistry.initialise(); - - // We don't need to store the Default queues in the store as we always - // create them first on start up so don't clear them from the startup - // configuration here. This also ensures that we don't attempt to - // perform a createExchange twice with the same details in the - // MessageStore(RoutingTable) as some instances may not like that. - // Derby being one. - // todo this can be removed with the resolution fo QPID-2096 - configFileRT.exchange.clear(); - - initialiseModel(hostConfig); - - //todo REMOVE Work Around for QPID-2096 - // This means that all durable exchanges declared in the configuration - // will not be stored in the MessageStore. - // They will still be created/registered/available on startup for as - // long as they are contained in the configuration. However, when they - // are removed from the configuration they will no longer exist. - // This differs from durable queues as they will be writen to to the - // store. After QPID-2096 has been resolved exchanges will mirror that - // functionality. - configFileRT.exchange.clear(); - - if (store != null) - { - _messageStore = store; - _durableConfigurationStore = store; - } - else - { - if (hostConfig == null) - { - throw new IllegalAccessException("HostConfig and MessageStore cannot be null"); - } - initialiseMessageStore(hostConfig); - } - - //Now that the RT has been initialised loop through the persistent queues/exchanges created from the config - // file and write them in to the new routing Table. - for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue) - { - getDurableConfigurationStore().createQueue(cqt.queue, cqt.arguments); - } - - for (Exchange exchange : configFileRT.exchange) - { - getDurableConfigurationStore().createExchange(exchange); - } - - for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings) - { - getDurableConfigurationStore().bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments); - } - - _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig); - - _accessManager = ApplicationRegistry.getInstance().getAccessManager(); - _accessManager.configureHostPlugins(hostConfig.getSecurityConfiguration()); - - _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean); - _brokerMBean.register(); - initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod()); - } - - private void initialiseHouseKeeping(long period) - { - /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */ - if (period != 0L) - { - class RemoveExpiredMessagesTask extends TimerTask - { - public void run() - { - for (AMQQueue q : _queueRegistry.getQueues()) - { - - try - { - q.checkMessageStatus(); - } - catch (AMQException e) - { - _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e); - throw new RuntimeException(e); - } - } - } - } - - _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(), - period / 2, - period); - - class ForceChannelClosuresTask extends TimerTask - { - public void run() - { - _connectionRegistry.expireClosedChannels(); - } - } - } - } - - private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception - { - String messageStoreClass = hostConfig.getMessageStoreClass(); - - Class clazz = Class.forName(messageStoreClass); - Object o = clazz.newInstance(); - - if (!(o instanceof MessageStore)) - { - throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz + - " does not."); - } - MessageStore messageStore = (MessageStore) o; - messageStore.configure(this, "store", hostConfig); - _messageStore = messageStore; - _durableConfigurationStore = messageStore; - } - - private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException - { - _logger.debug("Loading configuration for virtualhost: " + config.getName()); - - List exchangeNames = config.getExchanges(); - - for (Object exchangeNameObj : exchangeNames) - { - String exchangeName = String.valueOf(exchangeNameObj); - configureExchange(config.getExchangeConfiguration(exchangeName)); - } - - String[] queueNames = config.getQueueNames(); - - for (Object queueNameObj : queueNames) - { - String queueName = String.valueOf(queueNameObj); - configureQueue(config.getQueueConfiguration(queueName)); - } - } - - private void configureExchange(ExchangeConfiguration exchangeConfiguration) throws AMQException - { - AMQShortString exchangeName = new AMQShortString(exchangeConfiguration.getName()); - - Exchange exchange; - exchange = _exchangeRegistry.getExchange(exchangeName); - if (exchange == null) - { - - AMQShortString type = new AMQShortString(exchangeConfiguration.getType()); - boolean durable = exchangeConfiguration.getDurable(); - boolean autodelete = exchangeConfiguration.getAutoDelete(); - - Exchange newExchange = _exchangeFactory.createExchange(exchangeName, type, durable, autodelete, 0); - _exchangeRegistry.registerExchange(newExchange); - } - } - - private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException - { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this); - - if (queue.isDurable()) - { - getDurableConfigurationStore().createQueue(queue); - } - - String exchangeName = queueConfiguration.getExchange(); - - Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName)); - - if (exchange == null) - { - exchange = _exchangeRegistry.getDefaultExchange(); - } - - if (exchange == null) - { - throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName); - } - - List routingKeys = queueConfiguration.getRoutingKeys(); - if (routingKeys == null || routingKeys.isEmpty()) - { - routingKeys = Collections.singletonList(queue.getName()); - } - - for (Object routingKeyNameObj : routingKeys) - { - AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj)); - if (_logger.isInfoEnabled()) - { - _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this); - } - queue.bind(exchange, routingKey, null); - } - - if (exchange != _exchangeRegistry.getDefaultExchange()) - { - queue.bind(_exchangeRegistry.getDefaultExchange(), queue.getName(), null); - } - } - - public String getName() - { - return _name; - } - - public QueueRegistry getQueueRegistry() - { - return _queueRegistry; - } - - public ExchangeRegistry getExchangeRegistry() - { - return _exchangeRegistry; - } - - public ExchangeFactory getExchangeFactory() - { - return _exchangeFactory; - } - - public MessageStore getMessageStore() - { - return _messageStore; - } - - public TransactionLog getTransactionLog() - { - return _messageStore; - } - - public DurableConfigurationStore getDurableConfigurationStore() - { - return _durableConfigurationStore; - } - - public AuthenticationManager getAuthenticationManager() - { - return _authenticationManager; - } - - public ACLManager getAccessManager() - { - return _accessManager; - } - - public void close() throws Exception - { - - //Stop Connections - _connectionRegistry.close(); - - //Stop the Queues processing - if (_queueRegistry != null) - { - for (AMQQueue queue : _queueRegistry.getQueues()) - { - queue.stop(); - } - } - - //Stop Housekeeping - if (_houseKeepingTimer != null) - { - _houseKeepingTimer.cancel(); - } - - //Close MessageStore - if (_messageStore != null) - { - _messageStore.close(); - } - - CurrentActor.get().message(VirtualHostMessages.VHT_1002()); - } - - public ManagedObject getBrokerMBean() - { - return _brokerMBean; - } - - public ManagedObject getManagedObject() - { - return _virtualHostMBean; - } - - /** - * Temporary Startup RT class to record the creation of persistent queues / exchanges. - * - * - * This is so we can replay the creation of queues/exchanges in to the real _RT after it has been loaded. - * This should be removed after the _RT has been fully split from the the TL - */ - private class StartupRoutingTable implements DurableConfigurationStore - { - public List<Exchange> exchange = new LinkedList<Exchange>(); - public List<CreateQueueTuple> queue = new LinkedList<CreateQueueTuple>(); - public List<CreateBindingTuple> bindings = new LinkedList<CreateBindingTuple>(); - - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception - { - } - - public void close() throws Exception - { - } - - public void removeMessage(Long messageId) throws AMQException - { - //To change body of implemented methods use File | Settings | File Templates. - } + IConnectionRegistry getConnectionRegistry(); - public void createExchange(Exchange exchange) throws AMQException - { - if (exchange.isDurable()) - { - this.exchange.add(exchange); - } - } + VirtualHostConfiguration getConfiguration(); - public void removeExchange(Exchange exchange) throws AMQException - { - } + String getName(); - public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - if (exchange.isDurable() && queue.isDurable()) - { - bindings.add(new CreateBindingTuple(exchange, routingKey, queue, args)); - } - } + QueueRegistry getQueueRegistry(); - public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - } + ExchangeRegistry getExchangeRegistry(); - public void createQueue(AMQQueue queue) throws AMQException - { - createQueue(queue, null); - } + ExchangeFactory getExchangeFactory(); - public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException - { - if (queue.isDurable()) - { - this.queue.add(new CreateQueueTuple(queue, arguments)); - } - } + MessageStore getMessageStore(); - public void removeQueue(AMQQueue queue) throws AMQException - { - } + TransactionLog getTransactionLog(); + DurableConfigurationStore getDurableConfigurationStore(); - private class CreateQueueTuple - { - public AMQQueue queue; - public FieldTable arguments; + AuthenticationManager getAuthenticationManager(); - public CreateQueueTuple(AMQQueue queue, FieldTable arguments) - { - this.queue = queue; - this.arguments = arguments; - } - } + ACLManager getAccessManager(); - private class CreateBindingTuple - { - public AMQQueue queue; - public FieldTable arguments; - public Exchange exchange; - public AMQShortString routingKey; + void close() throws Exception; - public CreateBindingTuple(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) - { - this.exchange = exchange; - this.routingKey = routingKey; - this.queue = queue; - arguments = args; - } - } - } + ManagedObject getManagedObject(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java new file mode 100755 index 0000000000..7fa5a26436 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -0,0 +1,340 @@ +/* +* +* 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.virtualhost; + +import org.apache.qpid.server.store.ConfigurationRecoveryHandler; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.store.TransactionLogRecoveryHandler; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.TransactionLogMessages; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.AMQException; + +import org.apache.log4j.Logger; + +import java.nio.ByteBuffer; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.TreeMap; + +public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHandler, + ConfigurationRecoveryHandler.QueueRecoveryHandler, + ConfigurationRecoveryHandler.ExchangeRecoveryHandler, + ConfigurationRecoveryHandler.BindingRecoveryHandler, + MessageStoreRecoveryHandler, + MessageStoreRecoveryHandler.StoredMessageRecoveryHandler, + TransactionLogRecoveryHandler, + TransactionLogRecoveryHandler.QueueEntryRecoveryHandler +{ + private static final Logger _logger = Logger.getLogger(VirtualHostConfigRecoveryHandler.class); + + + private final VirtualHost _virtualHost; + + private MessageStoreLogSubject _logSubject; + private List<ProcessAction> _actions; + + private MessageStore _store; + private TransactionLog _transactionLog; + + private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>(); + private Map<Long, ServerMessage> _recoveredMessages = new HashMap<Long, ServerMessage>(); + private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>(); + + + + public VirtualHostConfigRecoveryHandler(VirtualHost virtualHost) + { + _virtualHost = virtualHost; + } + + public QueueRecoveryHandler begin(MessageStore store) + { + _logSubject = new MessageStoreLogSubject(_virtualHost,store); + _store = store; + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1004(null, false)); + + return this; + } + + public void queue(String queueName, String owner, FieldTable arguments) + { + AMQShortString queueNameShortString = new AMQShortString(queueName); + + AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueNameShortString); + + if (q == null) + { + q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost, + arguments); + _virtualHost.getQueueRegistry().registerQueue(q); + } + + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1004(queueName, true)); + + //Record that we have a queue for recovery + _queueRecoveries.put(queueName, 0); + } + + public ExchangeRecoveryHandler completeQueueRecovery() + { + return this; + } + + public void exchange(String exchangeName, String type, boolean autoDelete) + { + try + { + Exchange exchange; + AMQShortString exchangeNameSS = new AMQShortString(exchangeName); + exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeNameSS); + if (exchange == null) + { + exchange = _virtualHost.getExchangeFactory().createExchange(exchangeNameSS, new AMQShortString(type), true, autoDelete, 0); + _virtualHost.getExchangeRegistry().registerExchange(exchange); + } + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + + } + + public BindingRecoveryHandler completeExchangeRecovery() + { + return this; + } + + public StoredMessageRecoveryHandler begin() + { + // TODO - log begin + return this; + } + + public void message(StoredMessage message) + { + ServerMessage serverMessage; + switch(message.getMetaData().getType()) + { + case META_DATA_0_8: + serverMessage = new AMQMessage(message); + break; + case META_DATA_0_10: + serverMessage = new MessageTransferMessage(message, null); + break; + default: + throw new RuntimeException("Unknown message type retreived from store " + message.getMetaData().getClass()); + } + + + _recoveredMessages.put(message.getMessageNumber(), serverMessage); + _unusedMessages.put(message.getMessageNumber(), message); + } + + public void completeMessageRecovery() + { + //TODO - log end + //To change body of implemented methods use File | Settings | File Templates. + } + + public TransactionLogRecoveryHandler.QueueEntryRecoveryHandler begin(TransactionLog log) + { + _transactionLog = log; + return this; + } + + private static final class ProcessAction + { + private final AMQQueue _queue; + private final AMQMessage _message; + + public ProcessAction(AMQQueue queue, AMQMessage message) + { + _queue = queue; + _message = message; + } + + public void process() + { + try + { + _queue.enqueue(_message); + } + catch(AMQException e) + { + throw new RuntimeException(e); + } + } + + } + + public void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf) + { + _actions = new ArrayList<ProcessAction>(); + try + { + QueueRegistry queueRegistry = _virtualHost.getQueueRegistry(); + Exchange exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeName); + AMQQueue queue = queueRegistry.getQueue(new AMQShortString(queueName)); + if (queue == null) + { + _logger.error("Unkown queue: " + queueName + " cannot be bound to exchange: " + + exchange.getName()); + } + else + { + + + FieldTable argumentsFT = null; + if(buf != null) + { + argumentsFT = new FieldTable(org.apache.mina.common.ByteBuffer.wrap(buf),buf.limit()); + } + + _logger.info("Restoring binding: (Exchange: " + exchange.getName() + ", Queue: " + queueName + + ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")"); + + queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT); + + } + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + + } + + public void completeBindingRecovery() + { + //return this; + } + + public void complete() + { + + + } + + public void queueEntry(final String queueName, long messageId) + { + AMQShortString queueNameShortString = new AMQShortString(queueName); + + AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueNameShortString); + + try + { + if(queue != null) + { + ServerMessage message = _recoveredMessages.get(messageId); + _unusedMessages.remove(messageId); + + if(message != null) + { + + + if (_logger.isDebugEnabled()) + { + _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queue.getName()); + } + + Integer count = _queueRecoveries.get(queueName); + if (count == null) + { + count = 0; + } + + queue.enqueue(message); + + _queueRecoveries.put(queueName, ++count); + } + else + { + _logger.warn("Message id " + messageId + " referenced in log as enqueue in queue " + queue.getName() + " is unknwon, entry will be discarded"); + TransactionLog.Transaction txn = _transactionLog.newTransaction(); + txn.dequeueMessage(queue, messageId); + txn.commitTranAsync(); + } + } + else + { + _logger.warn("Message id " + messageId + " in log references queue " + queueName + " which is not in the configuration, entry will be discarded"); + TransactionLog.Transaction txn = _transactionLog.newTransaction(); + TransactionLogResource mockQueue = + new TransactionLogResource() + { + + public String getResourceName() + { + return queueName; + } + }; + txn.dequeueMessage(mockQueue, messageId); + txn.commitTranAsync(); + } + + } + catch(AMQException e) + { + throw new RuntimeException(e); + } + + + + } + + public void completeQueueEntryRecovery() + { + + for(StoredMessage m : _unusedMessages.values()) + { + _logger.warn("Message id " + m.getMessageNumber() + " in store, but not in any queue - removing...."); + m.remove(); + } + + for(Map.Entry<String,Integer> entry : _queueRecoveries.entrySet()) + { + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1005(entry.getValue(), entry.getKey())); + + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(entry.getKey(), true)); + } + + CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(null, false)); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java new file mode 100644 index 0000000000..e4e5ba26b4 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -0,0 +1,602 @@ +/* + * + * 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.virtualhost; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.Configuration; +import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.AMQBrokerManagerMBean; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.VirtualHostMessages; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.configuration.ExchangeConfiguration; +import org.apache.qpid.server.configuration.QueueConfiguration; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.connection.ConnectionRegistry; +import org.apache.qpid.server.connection.IConnectionRegistry; +import org.apache.qpid.server.exchange.DefaultExchangeFactory; +import org.apache.qpid.server.exchange.DefaultExchangeRegistry; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeFactory; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.management.AMQManagedObject; +import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.DefaultQueueRegistry; +import org.apache.qpid.server.queue.QueueRegistry; +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.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.DurableConfigurationStore; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler; + +import javax.management.NotCompliantMBeanException; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +public class VirtualHostImpl implements Accessable, VirtualHost +{ + private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class); + + private final String _name; + + private ConnectionRegistry _connectionRegistry; + + private QueueRegistry _queueRegistry; + + private ExchangeRegistry _exchangeRegistry; + + private ExchangeFactory _exchangeFactory; + + private MessageStore _messageStore; + + protected VirtualHostMBean _virtualHostMBean; + + private AMQBrokerManagerMBean _brokerMBean; + + private AuthenticationManager _authenticationManager; + + private ACLManager _accessManager; + + private final Timer _houseKeepingTimer; + private VirtualHostConfiguration _configuration; + private DurableConfigurationStore _durableConfigurationStore; + + public void setAccessableName(String name) + { + _logger.warn("Setting Accessable Name for VirualHost is not allowed. (" + + name + ") ignored remains :" + getAccessableName()); + } + + public String getAccessableName() + { + return _name; + } + + public IConnectionRegistry getConnectionRegistry() + { + return _connectionRegistry; + } + + public VirtualHostConfiguration getConfiguration() + { + return _configuration; + } + + /** + * Abstract MBean class. This has some of the methods implemented from management intrerface for exchanges. Any + * implementaion of an Exchange MBean should extend this class. + */ + public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost + { + public VirtualHostMBean() throws NotCompliantMBeanException + { + super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE, ManagedVirtualHost.VERSION); + } + + public String getObjectInstanceName() + { + return _name.toString(); + } + + public String getName() + { + return _name.toString(); + } + + public VirtualHostImpl getVirtualHost() + { + return VirtualHostImpl.this; + } + + } // End of MBean class + + /** + * Normal Constructor + * + * @param hostConfig + * + * @throws Exception + */ + public VirtualHostImpl(VirtualHostConfiguration hostConfig) throws Exception + { + this(hostConfig, null); + } + + public VirtualHostImpl(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception + { + _configuration = hostConfig; + _name = hostConfig.getName(); + + CurrentActor.get().message(VirtualHostMessages.VHT_1001(_name)); + + if (_name == null || _name.length() == 0) + { + throw new IllegalArgumentException("Illegal name (" + _name + ") for virtualhost."); + } + + _virtualHostMBean = new VirtualHostMBean(); + + _connectionRegistry = new ConnectionRegistry(this); + + _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true); + + _queueRegistry = new DefaultQueueRegistry(this); + + _exchangeFactory = new DefaultExchangeFactory(this); + _exchangeFactory.initialise(hostConfig); + + _exchangeRegistry = new DefaultExchangeRegistry(this); + + //Create a temporary RT to store the durable entries from the config file + // so we can replay them in to the real _RT after it has been loaded. + /// This should be removed after the _RT has been fully split from the the TL + + StartupRoutingTable configFileRT = new StartupRoutingTable(); + + _durableConfigurationStore = configFileRT; + + // This needs to be after the RT has been defined as it creates the default durable exchanges. + _exchangeRegistry.initialise(); + + // We don't need to store the Default queues in the store as we always + // create them first on start up so don't clear them from the startup + // configuration here. This also ensures that we don't attempt to + // perform a createExchange twice with the same details in the + // MessageStore(RoutingTable) as some instances may not like that. + // Derby being one. + // todo this can be removed with the resolution fo QPID-2096 + configFileRT.exchange.clear(); + + initialiseModel(hostConfig); + + //todo REMOVE Work Around for QPID-2096 + // This means that all durable exchanges declared in the configuration + // will not be stored in the MessageStore. + // They will still be created/registered/available on startup for as + // long as they are contained in the configuration. However, when they + // are removed from the configuration they will no longer exist. + // This differs from durable queues as they will be writen to to the + // store. After QPID-2096 has been resolved exchanges will mirror that + // functionality. + configFileRT.exchange.clear(); + + if (store != null) + { + _messageStore = store; + _durableConfigurationStore = store; + } + else + { + if (hostConfig == null) + { + throw new IllegalAccessException("HostConfig and MessageStore cannot be null"); + } + initialiseMessageStore(hostConfig); + } + + //Now that the RT has been initialised loop through the persistent queues/exchanges created from the config + // file and write them in to the new routing Table. + for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue) + { + getDurableConfigurationStore().createQueue(cqt.queue, cqt.arguments); + } + + for (Exchange exchange : configFileRT.exchange) + { + getDurableConfigurationStore().createExchange(exchange); + } + + for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings) + { + getDurableConfigurationStore().bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments); + } + + _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig); + + _accessManager = ApplicationRegistry.getInstance().getAccessManager(); + _accessManager.configureHostPlugins(hostConfig.getSecurityConfiguration()); + + _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean); + _brokerMBean.register(); + initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod()); + } + + private void initialiseHouseKeeping(long period) + { + /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */ + if (period != 0L) + { + class RemoveExpiredMessagesTask extends TimerTask + { + public void run() + { + for (AMQQueue q : _queueRegistry.getQueues()) + { + + try + { + q.checkMessageStatus(); + } + catch (AMQException e) + { + _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e); + throw new RuntimeException(e); + } + } + } + } + + _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(), + period / 2, + period); + + class ForceChannelClosuresTask extends TimerTask + { + public void run() + { + _connectionRegistry.expireClosedChannels(); + } + } + } + } + + private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception + { + String messageStoreClass = hostConfig.getMessageStoreClass(); + + Class clazz = Class.forName(messageStoreClass); + Object o = clazz.newInstance(); + + if (!(o instanceof MessageStore)) + { + throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz + + " does not."); + } + MessageStore messageStore = (MessageStore) o; + VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this); + + MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStore); + + messageStore.configureConfigStore(this.getName(), + recoveryHandler, + hostConfig.getStoreConfiguration(), + storeLogSubject); + + messageStore.configureMessageStore(this.getName(), + recoveryHandler, + hostConfig.getStoreConfiguration(), + storeLogSubject); + messageStore.configureTransactionLog(this.getName(), + recoveryHandler, + hostConfig.getStoreConfiguration(), + storeLogSubject); + + _messageStore = messageStore; + _durableConfigurationStore = messageStore; + } + + private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException + { + _logger.debug("Loading configuration for virtualhost: " + config.getName()); + + List exchangeNames = config.getExchanges(); + + for (Object exchangeNameObj : exchangeNames) + { + String exchangeName = String.valueOf(exchangeNameObj); + configureExchange(config.getExchangeConfiguration(exchangeName)); + } + + String[] queueNames = config.getQueueNames(); + + for (Object queueNameObj : queueNames) + { + String queueName = String.valueOf(queueNameObj); + configureQueue(config.getQueueConfiguration(queueName)); + } + } + + private void configureExchange(ExchangeConfiguration exchangeConfiguration) throws AMQException + { + AMQShortString exchangeName = new AMQShortString(exchangeConfiguration.getName()); + + Exchange exchange; + exchange = _exchangeRegistry.getExchange(exchangeName); + if (exchange == null) + { + + AMQShortString type = new AMQShortString(exchangeConfiguration.getType()); + boolean durable = exchangeConfiguration.getDurable(); + boolean autodelete = exchangeConfiguration.getAutoDelete(); + + Exchange newExchange = _exchangeFactory.createExchange(exchangeName, type, durable, autodelete, 0); + _exchangeRegistry.registerExchange(newExchange); + } + } + + private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException + { + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this); + + if (queue.isDurable()) + { + getDurableConfigurationStore().createQueue(queue); + } + + String exchangeName = queueConfiguration.getExchange(); + + Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName)); + + if (exchange == null) + { + exchange = _exchangeRegistry.getDefaultExchange(); + } + + if (exchange == null) + { + throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName); + } + + List routingKeys = queueConfiguration.getRoutingKeys(); + if (routingKeys == null || routingKeys.isEmpty()) + { + routingKeys = Collections.singletonList(queue.getName()); + } + + for (Object routingKeyNameObj : routingKeys) + { + AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj)); + if (_logger.isInfoEnabled()) + { + _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this); + } + queue.bind(exchange, routingKey, null); + } + + if (exchange != _exchangeRegistry.getDefaultExchange()) + { + queue.bind(_exchangeRegistry.getDefaultExchange(), queue.getName(), null); + } + } + + public String getName() + { + return _name; + } + + public QueueRegistry getQueueRegistry() + { + return _queueRegistry; + } + + public ExchangeRegistry getExchangeRegistry() + { + return _exchangeRegistry; + } + + public ExchangeFactory getExchangeFactory() + { + return _exchangeFactory; + } + + public MessageStore getMessageStore() + { + return _messageStore; + } + + public TransactionLog getTransactionLog() + { + return _messageStore; + } + + public DurableConfigurationStore getDurableConfigurationStore() + { + return _durableConfigurationStore; + } + + public AuthenticationManager getAuthenticationManager() + { + return _authenticationManager; + } + + public ACLManager getAccessManager() + { + return _accessManager; + } + + public void close() throws Exception + { + + //Stop Connections + _connectionRegistry.close(); + + //Stop the Queues processing + if (_queueRegistry != null) + { + for (AMQQueue queue : _queueRegistry.getQueues()) + { + queue.stop(); + } + } + + //Stop Housekeeping + if (_houseKeepingTimer != null) + { + _houseKeepingTimer.cancel(); + } + + //Close MessageStore + if (_messageStore != null) + { + _messageStore.close(); + } + + CurrentActor.get().message(VirtualHostMessages.VHT_1002()); + } + + public ManagedObject getBrokerMBean() + { + return _brokerMBean; + } + + public ManagedObject getManagedObject() + { + return _virtualHostMBean; + } + + /** + * Temporary Startup RT class to record the creation of persistent queues / exchanges. + * + * + * This is so we can replay the creation of queues/exchanges in to the real _RT after it has been loaded. + * This should be removed after the _RT has been fully split from the the TL + */ + private class StartupRoutingTable implements DurableConfigurationStore + { + public List<Exchange> exchange = new LinkedList<Exchange>(); + public List<CreateQueueTuple> queue = new LinkedList<CreateQueueTuple>(); + public List<CreateBindingTuple> bindings = new LinkedList<CreateBindingTuple>(); + + public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception + { + } + + public void close() throws Exception + { + } + + public void removeMessage(Long messageId) throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void configureConfigStore(String name, + ConfigurationRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void createExchange(Exchange exchange) throws AMQException + { + if (exchange.isDurable()) + { + this.exchange.add(exchange); + } + } + + public void removeExchange(Exchange exchange) throws AMQException + { + } + + public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException + { + if (exchange.isDurable() && queue.isDurable()) + { + bindings.add(new CreateBindingTuple(exchange, routingKey, queue, args)); + } + } + + public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException + { + } + + public void createQueue(AMQQueue queue) throws AMQException + { + createQueue(queue, null); + } + + public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException + { + if (queue.isDurable()) + { + this.queue.add(new CreateQueueTuple(queue, arguments)); + } + } + + public void removeQueue(AMQQueue queue) throws AMQException + { + } + + + private class CreateQueueTuple + { + public AMQQueue queue; + public FieldTable arguments; + + public CreateQueueTuple(AMQQueue queue, FieldTable arguments) + { + this.queue = queue; + this.arguments = arguments; + } + } + + private class CreateBindingTuple + { + public AMQQueue queue; + public FieldTable arguments; + public Exchange exchange; + public AMQShortString routingKey; + + public CreateBindingTuple(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) + { + this.exchange = exchange; + this.routingKey = routingKey; + this.queue = queue; + arguments = args; + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java index 5543adbeb5..b86e0d0baf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.virtualhost;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
import java.util.ArrayList;
import java.util.Collection;
@@ -31,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; public class VirtualHostRegistry
{
- private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
+ private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String, VirtualHost>();
private String _defaultVirtualHostName;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java index 0869d9a497..ef3599bdc8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java @@ -14,14 +14,16 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.tools.messagestore.commands; import org.apache.qpid.tools.messagestore.MessageStoreTool; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.LocalTransaction; public class Copy extends Move { @@ -49,7 +51,9 @@ public class Copy extends Move protected void doCommand(AMQQueue fromQueue, long start, long end, AMQQueue toQueue) { - fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getName().toString(), _storeContext); + ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog()); + fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getName().toString(), txn); + txn.commit(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java index 9e83b93129..a7d58dc6dd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java @@ -21,9 +21,6 @@ package org.apache.qpid.tools.messagestore.commands; import org.apache.commons.codec.binary.Hex; -import org.apache.mina.common.ByteBuffer; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.queue.QueueEntryImpl; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.message.ServerMessage; @@ -31,7 +28,6 @@ import org.apache.qpid.tools.messagestore.MessageStoreTool; import org.apache.qpid.tools.utils.Console; import java.io.UnsupportedEncodingException; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -137,114 +133,116 @@ public class Dump extends Show hex.add(Console.ROW_DIVIDER); ascii.add(Console.ROW_DIVIDER); - if(msg instanceof AMQMessage) + + final int messageSize = (int) msg.getSize(); + if (messageSize != 0) { + hex.add("Hex"); + hex.add(Console.ROW_DIVIDER); - Iterator bodies = ((AMQMessage)msg).getContentBodyIterator(); - if (bodies.hasNext()) - { - hex.add("Hex"); - hex.add(Console.ROW_DIVIDER); + ascii.add("ASCII"); + ascii.add(Console.ROW_DIVIDER); + java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(64 * 1024); - ascii.add("ASCII"); - ascii.add(Console.ROW_DIVIDER); + int position = 0; - while (bodies.hasNext()) - { - ContentChunk chunk = (ContentChunk) bodies.next(); + while(position < messageSize) + { + + position += msg.getContent(buf, position); + buf.flip(); + //Duplicate so we don't destroy original data :) + java.nio.ByteBuffer hexBuffer = buf; - //Duplicate so we don't destroy original data :) - ByteBuffer hexBuffer = chunk.getData().duplicate(); + java.nio.ByteBuffer charBuffer = hexBuffer.duplicate(); - ByteBuffer charBuffer = hexBuffer.duplicate(); + Hex hexencoder = new Hex(); - Hex hexencoder = new Hex(); + while (hexBuffer.hasRemaining()) + { + byte[] line = new byte[LINE_SIZE]; - while (hexBuffer.hasRemaining()) + int bufsize = hexBuffer.remaining(); + if (bufsize < LINE_SIZE) + { + hexBuffer.get(line, 0, bufsize); + } + else { - byte[] line = new byte[LINE_SIZE]; + bufsize = line.length; + hexBuffer.get(line); + } - int bufsize = hexBuffer.remaining(); - if (bufsize < LINE_SIZE) - { - hexBuffer.get(line, 0, bufsize); - } - else - { - bufsize = line.length; - hexBuffer.get(line); - } + byte[] encoded = hexencoder.encode(line); - byte[] encoded = hexencoder.encode(line); + try + { + String encStr = new String(encoded, 0, bufsize * 2, DEFAULT_ENCODING); + String hexLine = ""; - try + int strKength = encStr.length(); + for (int c = 0; c < strKength; c++) { - String encStr = new String(encoded, 0, bufsize * 2, DEFAULT_ENCODING); - String hexLine = ""; + hexLine += encStr.charAt(c); - int strKength = encStr.length(); - for (int c = 0; c < strKength; c++) + if (c % 2 == 1 && SPACE_BYTES) { - hexLine += encStr.charAt(c); - - if (c % 2 == 1 && SPACE_BYTES) - { - hexLine += BYTE_SPACER; - } + hexLine += BYTE_SPACER; } - - hex.add(hexLine); } - catch (UnsupportedEncodingException e) - { - _console.println(e.getMessage()); - return null; - } - } - while (charBuffer.hasRemaining()) + hex.add(hexLine); + } + catch (UnsupportedEncodingException e) { - String asciiLine = ""; + _console.println(e.getMessage()); + return null; + } + } + + while (charBuffer.hasRemaining()) + { + String asciiLine = ""; - for (int pos = 0; pos < LINE_SIZE; pos++) + for (int pos = 0; pos < LINE_SIZE; pos++) + { + if (charBuffer.hasRemaining()) { - if (charBuffer.hasRemaining()) + byte ch = charBuffer.get(); + + if (isPrintable(ch)) { - byte ch = charBuffer.get(); - - if (isPrintable(ch)) - { - asciiLine += (char) ch; - } - else - { - asciiLine += NON_PRINTING_ASCII_CHAR; - } - - if (SPACE_BYTES) - { - asciiLine += BYTE_SPACER; - } + asciiLine += (char) ch; } else { - break; + asciiLine += NON_PRINTING_ASCII_CHAR; } - } - ascii.add(asciiLine); + if (SPACE_BYTES) + { + asciiLine += BYTE_SPACER; + } + } + else + { + break; + } } + + ascii.add(asciiLine); } + buf.clear(); } - else - { - List<String> result = new LinkedList<String>(); + } + else + { + List<String> result = new LinkedList<String>(); - display.add(result); - result.add("No ContentBodies"); - } + display.add(result); + result.add("No ContentBodies"); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java index df8b59ec19..ab8e781df5 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java @@ -14,9 +14,9 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.tools.messagestore.commands; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java index b3ff1d43e1..6a5e2a6025 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java @@ -14,17 +14,17 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.tools.messagestore.commands; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.queue.QueueEntryImpl; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.StoreContext; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.tools.messagestore.MessageStoreTool; import java.util.LinkedList; @@ -33,12 +33,6 @@ import java.util.List; public class Move extends AbstractCommand { - /** - * Since the Coopy command is not associated with a real channel we can safely create our own store context - * for use in the few methods that require one. - */ - protected StoreContext _storeContext = new StoreContext(); - public Move(MessageStoreTool tool) { super(tool); @@ -201,6 +195,8 @@ public class Move extends AbstractCommand protected void doCommand(AMQQueue fromQueue, long start, long id, AMQQueue toQueue) { - fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getName().toString(), _storeContext); + ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog()); + fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getName().toString(), txn); + txn.commit(); } } 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 6acea07719..4fd4999b19 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 @@ -25,7 +25,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.queue.AMQMessage; +import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.message.ServerMessage; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java index e3889162ad..3cdb9c0c2d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java @@ -27,6 +27,7 @@ import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHost; public class AMQBrokerManagerMBeanTest extends TestCase @@ -46,7 +47,7 @@ public class AMQBrokerManagerMBeanTest extends TestCase assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null); - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHost.VirtualHostMBean) _vHost.getManagedObject()); + ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); mbean.createNewExchange(exchange1, "direct", false); mbean.createNewExchange(exchange2, "topic", false); mbean.createNewExchange(exchange3, "headers", false); @@ -68,7 +69,7 @@ public class AMQBrokerManagerMBeanTest extends TestCase { String queueName = "testQueue_" + System.currentTimeMillis(); - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHost.VirtualHostMBean) _vHost.getManagedObject()); + ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null); 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 f39f94a1b6..d2408ba21f 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 @@ -27,7 +27,7 @@ import org.apache.qpid.server.queue.SimpleQueueEntryList; import org.apache.qpid.server.queue.MockAMQMessage; 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.message.AMQMessage; import org.apache.qpid.server.queue.QueueEntryIterator; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.MockSubscription; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index 5d3b4e681a..b65020395c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -14,21 +14,20 @@ * "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. - * + * under the License. + * */ package org.apache.qpid.server.configuration; import junit.framework.TestCase; -import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; public class VirtualHostConfigurationTest extends TestCase { @@ -55,50 +54,50 @@ public class VirtualHostConfigurationTest extends TestCase super.tearDown(); } - + public void testQueuePriority() throws Exception { // Set up queue with 5 priorities - configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", + configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", "atest"); - configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange", + configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange", "amq.direct"); - configXml.addProperty("virtualhost.test.queues.queue.atest.priorities", + configXml.addProperty("virtualhost.test.queues.queue.atest.priorities", "5"); // Set up queue with JMS style priorities - configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", + configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", "ptest"); - configXml.addProperty("virtualhost.test.queues.queue.ptest(-1).exchange", + configXml.addProperty("virtualhost.test.queues.queue.ptest(-1).exchange", "amq.direct"); - configXml.addProperty("virtualhost.test.queues.queue.ptest.priority", + configXml.addProperty("virtualhost.test.queues.queue.ptest.priority", "true"); - + // Set up queue with no priorities - configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", + configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", "ntest"); - configXml.addProperty("virtualhost.test.queues.queue.ntest(-1).exchange", + configXml.addProperty("virtualhost.test.queues.queue.ntest(-1).exchange", "amq.direct"); - configXml.addProperty("virtualhost.test.queues.queue.ntest.priority", + configXml.addProperty("virtualhost.test.queues.queue.ntest.priority", "false"); - - VirtualHost vhost = new VirtualHost(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test"))); - + + VirtualHost vhost = new VirtualHostImpl(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test"))); + // Check that atest was a priority queue with 5 priorities AMQQueue atest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); assertTrue(atest instanceof AMQPriorityQueue); assertEquals(5, ((AMQPriorityQueue) atest).getPriorities()); - + // Check that ptest was a priority queue with 10 priorities AMQQueue ptest = vhost.getQueueRegistry().getQueue(new AMQShortString("ptest")); assertTrue(ptest instanceof AMQPriorityQueue); assertEquals(10, ((AMQPriorityQueue) ptest).getPriorities()); - + // Check that ntest wasn't a priority queue AMQQueue ntest = vhost.getQueueRegistry().getQueue(new AMQShortString("ntest")); assertFalse(ntest instanceof AMQPriorityQueue); } - + public void testQueueAlerts() throws Exception { // Set up queue with 5 priorities @@ -106,7 +105,7 @@ public class VirtualHostConfigurationTest extends TestCase configXml.addProperty("virtualhost.test.queues.maximumQueueDepth", "1"); configXml.addProperty("virtualhost.test.queues.maximumMessageSize", "2"); configXml.addProperty("virtualhost.test.queues.maximumMessageAge", "3"); - + configXml.addProperty("virtualhost.test.queues(-1).queue(1).name(1)", "atest"); configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange", "amq.direct"); configXml.addProperty("virtualhost.test.queues.queue.atest(-1).maximumQueueDepth", "4"); @@ -114,21 +113,21 @@ public class VirtualHostConfigurationTest extends TestCase configXml.addProperty("virtualhost.test.queues.queue.atest(-1).maximumMessageAge", "6"); configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", "btest"); - - VirtualHost vhost = new VirtualHost(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test"))); - + + VirtualHost vhost = new VirtualHostImpl(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test"))); + // Check specifically configured values AMQQueue aTest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); assertEquals(4, aTest.getMaximumQueueDepth()); assertEquals(5, aTest.getMaximumMessageSize()); assertEquals(6, aTest.getMaximumMessageAge()); - - // Check default values + + // Check default values AMQQueue bTest = vhost.getQueueRegistry().getQueue(new AMQShortString("btest")); assertEquals(1, bTest.getMaximumQueueDepth()); assertEquals(2, bTest.getMaximumMessageSize()); assertEquals(3, bTest.getMaximumMessageAge()); - + } - + } 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 268451c74a..e26b5b048c 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 @@ -27,15 +27,18 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.queue.*; 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.StoredMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.log4j.Logger; import java.util.*; +import java.util.concurrent.atomic.AtomicLong; public class AbstractHeadersExchangeTestBase extends TestCase { @@ -49,8 +52,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase */ private MessageStore _store = new MemoryMessageStore(); - private MessageHandleFactory _handleFactory = new MessageHandleFactory(); - private int count; public void testDoNothing() @@ -88,8 +89,8 @@ public class AbstractHeadersExchangeTestBase extends TestCase protected int route(Message m) throws AMQException { + m.getIncomingMessage().headersReceived(); m.route(exchange); - m.getIncomingMessage().routingComplete(_store, _handleFactory); if(m.getIncomingMessage().allContentReceived()) { for(AMQQueue q : m.getIncomingMessage().getDestinationQueues()) @@ -343,7 +344,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase return false; //To change body of implemented methods use File | Settings | File Templates. } - public void setRedelivered(boolean b) + public void setRedelivered() { //To change body of implemented methods use File | Settings | File Templates. } @@ -452,6 +453,8 @@ public class AbstractHeadersExchangeTestBase extends TestCase */ static class Message extends AMQMessage { + private static AtomicLong _messageId = new AtomicLong(); + private class TestIncomingMessage extends IncomingMessage { @@ -459,7 +462,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase final MessagePublishInfo info, final AMQProtocolSession publisher) { - super(messageId, info, publisher); + super(info); } @@ -484,7 +487,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase private IncomingMessage _incoming; - private static MessageStore _messageStore = new SkeletonMessageStore(); Message(AMQProtocolSession protocolSession, String id, String... headers) throws AMQException { @@ -493,7 +495,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase Message(AMQProtocolSession protocolSession, String id, FieldTable headers) throws AMQException { - this(protocolSession, _messageStore.getNewMessageId(),getPublishRequest(id), getContentHeader(headers), null); + this(protocolSession, _messageId.incrementAndGet(),getPublishRequest(id), getContentHeader(headers), Collections.EMPTY_LIST); } public IncomingMessage getIncomingMessage() @@ -506,32 +508,27 @@ public class AbstractHeadersExchangeTestBase extends TestCase ContentHeaderBody header, List<ContentBody> bodies) throws AMQException { - super(createMessageHandle(messageId, publish, header), header, header.bodySize, publish); + super(new MockStoredMessage(messageId, publish, header)); + + StoredMessage<MessageMetaData> storedMessage = getStoredMessage(); + int pos = 0; + for(ContentBody body : bodies) + { + storedMessage.addContent(pos, body.payload.duplicate().buf()); + pos += body.payload.limit(); + } - _incoming = new TestIncomingMessage(getMessageId(),publish, protocolsession); _incoming.setContentHeaderBody(header); } - private static AMQMessageHandle createMessageHandle(final long messageId, - final MessagePublishInfo publish, - final ContentHeaderBody header) - { - - final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, - _messageStore, - true); - - amqMessageHandle.setPublishAndContentHeaderBody(publish,header); - return amqMessageHandle; - } private Message(AMQMessage msg) throws AMQException { - super(msg); + super(msg.getStoredMessage()); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java index ac12e050b4..016f7eacbe 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java @@ -29,6 +29,7 @@ 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.management.ManagedObject; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java index 7c027880b4..dc47951548 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java @@ -53,6 +53,16 @@ public class HeadersBindingTest extends TestCase return null; } + public String getMimeType() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public String getEncoding() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + public byte getPriority() { return 0; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java index 750a1cd081..580bc78b8d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.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 @@ -35,7 +35,8 @@ public class HeadersExchangeTest extends AbstractHeadersExchangeTestBase super.setUp(); // AR will use the NullAR by default // Just use the first vhost. - VirtualHost virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); + VirtualHost + virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); _protocolSession = new InternalTestProtocolSession(virtualHost); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index f093e42874..9d7a323b6d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -14,9 +14,9 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.exchange; @@ -28,9 +28,12 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.abstraction.MessagePublishInfo; public class TopicExchangeTest extends TestCase @@ -54,19 +57,19 @@ public class TopicExchangeTest extends TestCase public void tearDown() { - ApplicationRegistry.remove(); + ApplicationRegistry.remove(); } public void testNoRoute() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, _vhost, null); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, _vhost, null); _exchange.registerQueue(new AMQShortString("a.*.#.b"), queue, null); MessagePublishInfo info = new PublishInfo(new AMQShortString("a.b")); - IncomingMessage message = new IncomingMessage(0L, info, _protocolSession); + IncomingMessage message = new IncomingMessage(info); message.enqueue(_exchange.route(message)); @@ -349,9 +352,11 @@ public class TopicExchangeTest extends TestCase private int routeMessage(final IncomingMessage message) throws AMQException { + MessageMetaData mmd = message.headersReceived(); + message.setStoredMessage(_store.addMessage(mmd)); + message.enqueue(_exchange.route(message)); - message.routingComplete(_store, new MessageHandleFactory()); - AMQMessage msg = new AMQMessage(message.getMessageHandle(), message.getContentHeader(), message.getSize(), message.getMessagePublishInfo()); + AMQMessage msg = new AMQMessage(message.getStoredMessage()); for(AMQQueue q : message.getDestinationQueues()) { q.enqueue(msg); @@ -393,8 +398,11 @@ public class TopicExchangeTest extends TestCase { MessagePublishInfo info = new PublishInfo(new AMQShortString(s)); - IncomingMessage message = new IncomingMessage(0L, info, _protocolSession); - message.setContentHeaderBody( new ContentHeaderBody()); + IncomingMessage message = new IncomingMessage(info); + final ContentHeaderBody chb = new ContentHeaderBody(); + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + chb.properties = props; + message.setContentHeaderBody(chb); return message; @@ -417,7 +425,7 @@ public class TopicExchangeTest extends TestCase public void setExchange(AMQShortString exchange) { - + } public boolean isImmediate() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java index fb3c96a5d3..b9779eff2e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java @@ -119,7 +119,7 @@ public class AMQPChannelActorTest extends TestCase // Verify that the message has the correct type assertTrue("Message contains the [con: prefix", logs.get(0).toString().contains("[con:")); - + // Verify that all the values were presented to the MessageFormatter // so we will not end up with '{n}' entries in the log. diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java index 0700fd3c1a..be72c31452 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java @@ -73,7 +73,7 @@ public class AMQPConnectionActorTest extends TestCase // Correctly Close the AR we created ApplicationRegistry.remove(); - super.tearDown(); + super.tearDown(); } private void setUpWithConfig(ServerConfiguration serverConfig) throws AMQException diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java index e02993b840..fe9242d98e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java @@ -59,7 +59,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages validateLogMessage(log, "MST-1003", expected); } - public void testMessage1004() + /* public void testMessage1004() { _logMessage = MessageStoreMessages.MST_1004(null,false); List<Object> log = performLog(); @@ -91,7 +91,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages // Here we use MessageFormat to ensure the messasgeCount of 2000 is // reformated for display as '2,000' - String[] expected = {"Recovered ", + String[] expected = {"Recovered ", MessageFormat.format("{0,number}", messasgeCount), "messages for queue", queueName}; @@ -119,5 +119,5 @@ public class MessageStoreMessagesTest extends AbstractTestMessages validateLogMessage(log, "MST-1006", expected); } - + */ } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java index bc36c61382..e6561a06b9 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java @@ -23,19 +23,16 @@ package org.apache.qpid.server.protocol; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.AMQChannel; 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.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.SkeletonMessageStore; import javax.management.JMException; -import java.security.Principal; /** Test class to test MBean operations for AMQMinaProtocolSession. */ public class AMQProtocolSessionMBeanTest extends TestCase 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 f6bd946bff..681e513ecb 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 @@ -27,13 +27,13 @@ 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.message.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.server.message.MessageContentSource; import org.apache.qpid.transport.TestNetworkDriver; public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter @@ -68,7 +68,17 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr public byte getProtocolMajorVersion() { return (byte) 8; - } + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, + ContentHeaderBody header, + MessageContentSource msgContent, + int channelId, + int replyCode, + AMQShortString replyText) throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } public byte getProtocolMinorVersion() { @@ -82,12 +92,12 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr synchronized (_channelDelivers) { List<DeliveryPair> all =_channelDelivers.get(channelId).get(consumerTag); - + if (all == null) { return new ArrayList<DeliveryPair>(0); } - + List<DeliveryPair> msgs = all.subList(0, count); List<DeliveryPair> response = new ArrayList<DeliveryPair>(msgs); @@ -99,15 +109,6 @@ 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 { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java index e37492bcb0..13e712dbac 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java @@ -22,17 +22,10 @@ package org.apache.qpid.server.protocol; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.AMQException; -import org.apache.qpid.protocol.AMQConstant; - -import java.security.Principal; /** Test class to test MBean operations for AMQMinaProtocolSession. */ public class MaxChannelsTest extends TestCase @@ -66,14 +59,14 @@ public class MaxChannelsTest extends TestCase } assertEquals("Maximum number of channels not set.", new Long(maxChannels), new Long(_session.getChannels().size())); } - + @Override public void setUp() { //Highlight that this test will cause a new AR to be created ApplicationRegistry.getInstance(); } - + @Override public void tearDown() throws Exception { @@ -87,7 +80,7 @@ public class MaxChannelsTest extends TestCase { // Correctly Close the AR we created ApplicationRegistry.remove(); - } + } } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index 768024498a..dd013e6ad5 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.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,21 +8,22 @@ 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. - * + * */ import java.util.ArrayList; import org.apache.qpid.AMQException; +import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; import junit.framework.AssertionFailedError; @@ -45,21 +46,21 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest _queue.enqueue(createMessage(1L, (byte) 10)); _queue.enqueue(createMessage(2L, (byte) 4)); _queue.enqueue(createMessage(3L, (byte) 0)); - + // Enqueue messages in reverse order _queue.enqueue(createMessage(4L, (byte) 0)); _queue.enqueue(createMessage(5L, (byte) 4)); _queue.enqueue(createMessage(6L, (byte) 10)); - + // Enqueue messages out of order _queue.enqueue(createMessage(7L, (byte) 4)); _queue.enqueue(createMessage(8L, (byte) 10)); _queue.enqueue(createMessage(9L, (byte) 0)); - + // Register subscriber _queue.registerSubscription(_subscription, false); Thread.sleep(150); - + ArrayList<QueueEntry> msgs = _subscription.getMessages(); try { @@ -98,10 +99,10 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest msg.getContentHeaderBody().properties = props; return msg; } - + protected AMQMessage createMessage(Long id) throws AMQException { return createMessage(id, (byte) 0); } - + } 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 8e5d833a93..5f0d77afea 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 @@ -25,9 +25,12 @@ import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; 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.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.protocol.AMQProtocolEngine; import org.apache.qpid.server.protocol.InternalTestProtocolSession; @@ -44,7 +47,7 @@ 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 -{ +{ private final static long MAX_MESSAGE_COUNT = 50; private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB @@ -232,7 +235,7 @@ public class AMQQueueAlertTest extends TestCase _queue.registerSubscription( subscription2, false); - + while (_queue.getUndeliveredMessageCount()!= 0) { Thread.sleep(100); @@ -251,7 +254,7 @@ public class AMQQueueAlertTest extends TestCase _queueMBean.clearQueue(); assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth())); } - + protected IncomingMessage message(final boolean immediate, long size) throws AMQException { MessagePublishInfo publish = new MessagePublishInfo() @@ -284,8 +287,10 @@ public class AMQQueueAlertTest extends TestCase }; ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + contentHeaderBody.properties = props; contentHeaderBody.bodySize = size; // in bytes - IncomingMessage message = new IncomingMessage(_messageStore.getNewMessageId(), publish, _protocolSession); + IncomingMessage message = new IncomingMessage(publish); message.setContentHeaderBody(contentHeaderBody); return message; @@ -312,13 +317,16 @@ public class AMQQueueAlertTest extends TestCase private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException { IncomingMessage[] messages = new IncomingMessage[(int) messageCount]; + MessageMetaData[] metaData = new MessageMetaData[(int) messageCount]; for (int i = 0; i < messages.length; i++) { messages[i] = message(false, size); ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); qs.add(_queue); + metaData[i] = messages[i].headersReceived(); + messages[i].setStoredMessage(_messageStore.addMessage(metaData[i])); + messages[i].enqueue(qs); - messages[i].routingComplete(_messageStore, new MessageHandleFactory()); } @@ -328,6 +336,10 @@ public class AMQQueueAlertTest extends TestCase ByteBuffer _data = ByteBuffer.allocate((int)size); + { + _data.limit((int)size); + } + public int getSize() { return (int) size; @@ -340,13 +352,11 @@ public class AMQQueueAlertTest extends TestCase public void reduceToFit() { - + } }); - _queue.enqueue(new AMQMessage(messages[i].getMessageHandle(), - messages[i].getContentHeader(), - messages[i].getSize(), - messages[i].getMessagePublishInfo())); + + _queue.enqueue(new AMQMessage(messages[i].getStoredMessage())); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index e692069663..97f061fdd1 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -25,7 +25,6 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.AMQException; public class AMQQueueFactoryTest extends TestCase { @@ -55,31 +54,18 @@ public class AMQQueueFactoryTest extends TestCase FieldTable fieldTable = new FieldTable(); fieldTable.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 5); - try - { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false, - _virtualHost, fieldTable); - assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass()); - } - catch (AMQException e) - { - fail(e.getMessage()); - } + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false, + _virtualHost, fieldTable); + + assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass()); } public void testSimpleQueueRegistration() { - try - { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("owner"), false, - _virtualHost, null); - assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass()); - } - catch (AMQException e) - { - fail(e.getMessage()); - } + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("owner"), false, + _virtualHost, null); + assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass()); } } 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 b135567029..3bb8d397be 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,6 +29,10 @@ 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.configuration.ServerConfiguration; +import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactory; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; @@ -41,6 +45,7 @@ import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.mina.common.ByteBuffer; +import org.apache.commons.configuration.PropertiesConfiguration; import javax.management.JMException; @@ -151,13 +156,11 @@ public class AMQQueueMBeanTest extends TestCase private void verifyBrokerState() { - TestableMemoryMessageStore store = new TestableMemoryMessageStore((MemoryMessageStore) _virtualHost.getMessageStore()); + TestableMemoryMessageStore store = (TestableMemoryMessageStore)_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()); - 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()); + + assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount()); } public void testConsumerCount() throws AMQException @@ -266,16 +269,22 @@ public class AMQQueueMBeanTest extends TestCase } IncomingMessage msg = message(false, false); - long id = msg.getMessageNumber(); _queue.clearQueue(); ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); qs.add(_queue); msg.enqueue(qs); - msg.routingComplete(_messageStore, new MessageHandleFactory()); + MessageMetaData mmd = msg.headersReceived(); + msg.setStoredMessage(_messageStore.addMessage(mmd)); + long id = msg.getMessageNumber(); + msg.addContentBodyFrame(new ContentChunk() { ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE); + { + _data.limit((int)MESSAGE_SIZE); + } + public int getSize() { return (int) MESSAGE_SIZE; @@ -292,7 +301,7 @@ public class AMQQueueMBeanTest extends TestCase } }); - AMQMessage m = new AMQMessage(msg.getMessageHandle(), msg.getContentHeader(), msg.getSize(), msg.getMessagePublishInfo()); + AMQMessage m = new AMQMessage(msg.getStoredMessage()); for(AMQQueue q : msg.getDestinationQueues()) { q.enqueue(m); @@ -345,7 +354,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, _protocolSession); + IncomingMessage msg = new IncomingMessage(publish); msg.setContentHeaderBody(contentHeaderBody); return msg; @@ -355,7 +364,14 @@ public class AMQQueueMBeanTest extends TestCase protected void setUp() throws Exception { super.setUp(); - IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance(); + + PropertiesConfiguration configuration = new PropertiesConfiguration(); + configuration.setProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName()); + IApplicationRegistry applicationRegistry = new TestApplicationRegistry(new ServerConfiguration(configuration)); + ApplicationRegistry.initialise(applicationRegistry ); + + configuration.setProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName()); + _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test"); _messageStore = _virtualHost.getMessageStore(); @@ -381,7 +397,8 @@ public class AMQQueueMBeanTest extends TestCase currentMessage.enqueue(qs); // route header - currentMessage.routingComplete(_messageStore, new MessageHandleFactory()); + MessageMetaData mmd = currentMessage.headersReceived(); + currentMessage.setStoredMessage(_messageStore.addMessage(mmd)); // Add the body so we have somthing to test later currentMessage.addContentBodyFrame( @@ -391,7 +408,7 @@ public class AMQQueueMBeanTest extends TestCase new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE), MESSAGE_SIZE))); - AMQMessage m = new AMQMessage(currentMessage.getMessageHandle(), currentMessage.getContentHeader(), currentMessage.getSize(), currentMessage.getMessagePublishInfo()); + AMQMessage m = new AMQMessage(currentMessage.getStoredMessage()); 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 0edcc182b0..d64e533f72 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,9 @@ 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.txn.Transaction; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.protocol.InternalTestProtocolSession; @@ -93,7 +95,6 @@ public class AckTest extends TestCase private void publishMessages(int count, boolean persistent) throws AMQException { _queue.registerSubscription(_subscription,false); - MessageHandleFactory factory = new MessageHandleFactory(); for (int i = 1; i <= count; i++) { // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) @@ -126,37 +127,37 @@ public class AckTest extends TestCase return new AMQShortString("rk"); } }; - final IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publishBody, _protocolSession); + final IncomingMessage msg = new IncomingMessage(publishBody); //IncomingMessage msg2 = null; + BasicContentHeaderProperties b = new BasicContentHeaderProperties(); + ContentHeaderBody cb = new ContentHeaderBody(); + cb.properties = b; + if (persistent) { - BasicContentHeaderProperties b = new BasicContentHeaderProperties(); //This is DeliveryMode.PERSISTENT b.setDeliveryMode((byte) 2); - ContentHeaderBody cb = new ContentHeaderBody(); - cb.properties = b; - msg.setContentHeaderBody(cb); - } - else - { - msg.setContentHeaderBody(new ContentHeaderBody()); } + + msg.setContentHeaderBody(cb); + // we increment the reference here since we are not delivering the messaging to any queues, which is where // the reference is normally incremented. The test is easier to construct if we have direct access to the // subscription ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); qs.add(_queue); msg.enqueue(qs); - msg.routingComplete(_messageStore, factory); + MessageMetaData mmd = msg.headersReceived(); + msg.setStoredMessage(_messageStore.addMessage(mmd)); if(msg.allContentReceived()) { - Transaction txn = new AutoCommitTransaction(_messageStore); - txn.enqueue(_queue, msg, new Transaction.Action() { + ServerTransaction txn = new AutoCommitTransaction(_messageStore); + txn.enqueue(_queue, msg, new ServerTransaction.Action() { public void postCommit() { try { - _queue.enqueue(new AMQMessage(msg.getMessageHandle(), msg.getContentHeader(), msg.getSize(), msg.getMessagePublishInfo())); + _queue.enqueue(new AMQMessage(msg.getStoredMessage())); } catch (AMQException e) { @@ -213,8 +214,8 @@ public class AckTest extends TestCase UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); assertTrue(map.size() == 0); - assertTrue(_messageStore.getMessageMetaDataMap().size() == 0); - assertTrue(_messageStore.getContentBodyMap().size() == 0); + assertTrue(_messageStore.getMessageCount() == 0); + } @@ -230,8 +231,8 @@ public class AckTest extends TestCase UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); assertTrue(map.size() == 0); - assertTrue(_messageStore.getMessageMetaDataMap().size() == 0); - assertTrue(_messageStore.getContentBodyMap().size() == 0); + assertTrue(_messageStore.getMessageCount() == 0); + } 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 85e8464bff..7000df157e 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 @@ -21,22 +21,17 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.message.AMQMessage; public class MockAMQMessage extends AMQMessage { public MockAMQMessage(long messageId) throws AMQException { - super(new MockAMQMessageHandle(messageId) , - (MessagePublishInfo)new MockMessagePublishInfo()); + super(new MockStoredMessage(messageId)); } - protected MockAMQMessage(AMQMessage msg) - throws AMQException - { - super(msg); - } + @Override @@ -44,4 +39,5 @@ public class MockAMQMessage extends AMQMessage { 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 912233f5cd..7824988e27 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 @@ -25,12 +25,12 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.QueueConfiguration; 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.message.ServerMessage; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.AMQException; import java.util.List; @@ -57,6 +57,11 @@ public class MockAMQQueue implements AMQQueue return _name; } + public void setNoLocal(boolean b) + { + + } + public boolean isDurable() { return false; //To change body of implemented methods use File | Settings | File Templates. @@ -216,18 +221,18 @@ public class MockAMQQueue implements AMQQueue { return null; //To change body of implemented methods use File | Settings | File Templates. } - + public List<QueueEntry> getMessagesRangeOnTheQueue(long fromPosition, long toPosition) { return null; } - public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext) + public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext) { //To change body of implemented methods use File | Settings | File Templates. } - public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext) + public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext) { //To change body of implemented methods use File | Settings | File Templates. } @@ -352,7 +357,7 @@ public class MockAMQQueue implements AMQQueue } public void checkCapacity(AMQChannel channel) - { + { } public ManagedObject getManagedObject() @@ -367,7 +372,7 @@ public class MockAMQQueue implements AMQQueue public void setMinimumAlertRepeatGap(long value) { - + } public long getCapacity() @@ -392,7 +397,7 @@ public class MockAMQQueue implements AMQQueue public void configure(QueueConfiguration config) { - + } public PrincipalHolder getPrincipalHolder() @@ -416,4 +421,8 @@ public class MockAMQQueue implements AMQQueue } + public String getResourceName() + { + return _name.toString(); + } } 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 d1a43bc5b6..3f74cb973b 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 @@ -23,6 +23,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AMQMessage; public class MockQueueEntry implements QueueEntry { @@ -71,7 +72,7 @@ public class MockQueueEntry implements QueueEntry public void routeToAlternate() { - + } public void dispose() @@ -124,35 +125,35 @@ public class MockQueueEntry implements QueueEntry return false; } - + public boolean isQueueDeleted() { return false; } - + public boolean isRejectedBy(Subscription subscription) { return false; } - + public void reject() { } - + public void reject(Subscription subscription) { } - + public void release() { @@ -171,7 +172,7 @@ public class MockQueueEntry implements QueueEntry return false; } - + public void requeue() { @@ -190,8 +191,8 @@ public class MockQueueEntry implements QueueEntry } - - public void setRedelivered(boolean b) + + public void setRedelivered() { @@ -209,7 +210,7 @@ public class MockQueueEntry implements QueueEntry public boolean isRedelivered() { - return false; + return false; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java new file mode 100755 index 0000000000..7dc491de4d --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java @@ -0,0 +1,92 @@ +/* +* +* 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.queue; + +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; + +import java.nio.ByteBuffer; + +public class MockStoredMessage implements StoredMessage<MessageMetaData> +{ + private long _messageId; + private MessageMetaData _metaData; + private final ByteBuffer _content; + + + public MockStoredMessage(long messageId) + { + this(messageId, new MockMessagePublishInfo(), new ContentHeaderBody(new BasicContentHeaderProperties(), 60)); + } + + public MockStoredMessage(long messageId, MessagePublishInfo info, ContentHeaderBody chb) + { + _messageId = messageId; + _metaData = new MessageMetaData(info, chb, 0); + _content = ByteBuffer.allocate(_metaData.getContentSize()); + + } + + public MessageMetaData getMetaData() + { + return _metaData; + } + + public long getMessageNumber() + { + return _messageId; + } + + public void addContent(int offsetInMessage, ByteBuffer src) + { + src = src.duplicate(); + ByteBuffer dst = _content.duplicate(); + dst.position(offsetInMessage); + dst.put(src); + } + + public int getContent(int offset, ByteBuffer dst) + { + ByteBuffer src = _content.duplicate(); + src.position(offset); + src = src.slice(); + if(dst.remaining() < src.limit()) + { + src.limit(dst.remaining()); + } + dst.put(src); + return src.limit(); + } + + public TransactionLog.StoreFuture flushToStore() + { + return MessageStore.IMMEDIATE_FUTURE; + } + + public void remove() + { + } +} 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 6fa0fdef8a..8c6574095b 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 @@ -36,13 +36,16 @@ 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.registry.ApplicationRegistry; -import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; public class SimpleAMQQueueTest extends TestCase { @@ -94,7 +97,7 @@ public class SimpleAMQQueueTest extends TestCase ApplicationRegistry applicationRegistry = (ApplicationRegistry)ApplicationRegistry.getInstance(); PropertiesConfiguration env = new PropertiesConfiguration(); - _virtualHost = new VirtualHost(new VirtualHostConfiguration(getClass().getName(), env), _store); + _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration(getClass().getName(), env), _store); applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost); _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, _virtualHost, _arguments); @@ -271,7 +274,7 @@ public class SimpleAMQQueueTest extends TestCase AMQMessage message = createMessage(id); _queue.enqueue(message); QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry(); - entry.setRedelivered(true); + entry.setRedelivered(); _queue.resend(entry, _subscription); } @@ -399,23 +402,25 @@ public class SimpleAMQQueueTest extends TestCase public void testEnqueueDequeueOfPersistentMessageToNonDurableQueue() throws AMQException { // Create IncomingMessage and nondurable queue - final IncomingMessage msg = new IncomingMessage(1L, info, null); + final IncomingMessage msg = new IncomingMessage(info); ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); contentHeaderBody.properties = new BasicContentHeaderProperties(); ((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) 2); msg.setContentHeaderBody(contentHeaderBody); + final ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); // Send persistent message qs.add(_queue); - msg.routingComplete(_store, new MessageHandleFactory()); - _store.storeMessageMetaData(new Long(1L), new MessageMetaData(info, contentHeaderBody, 1)); + MessageMetaData metaData = msg.headersReceived(); + StoredMessage handle = _store.addMessage(metaData); + msg.setStoredMessage(handle); - Transaction txn = new AutoCommitTransaction(_store); + ServerTransaction txn = new AutoCommitTransaction(_store); - txn.enqueue(qs, msg, new Transaction.Action() + txn.enqueue(qs, msg, new ServerTransaction.Action() { public void postCommit() { @@ -435,7 +440,7 @@ public class SimpleAMQQueueTest extends TestCase // Dequeue message MockQueueEntry entry = new MockQueueEntry(); - AMQMessage amqmsg = new AMQMessage(1L, _store, new MessageHandleFactory()); + AMQMessage amqmsg = new AMQMessage(handle); entry.setMessage(amqmsg); _queue.dequeue(entry); @@ -446,23 +451,12 @@ public class SimpleAMQQueueTest extends TestCase } - // FIXME: move this to somewhere useful - private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody) - { - final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, - null, - false); - - amqMessageHandle.setPublishAndContentHeaderBody(publishBody, contentHeaderBody); - return amqMessageHandle; - } - public class TestMessage extends AMQMessage { private final long _tag; private int _count; - TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext) + TestMessage(long tag, long messageId, MessagePublishInfo publishBody) throws AMQException { this(tag, messageId, publishBody, new ContentHeaderBody(1, 1, new BasicContentHeaderProperties(), 0)); @@ -471,7 +465,7 @@ public class SimpleAMQQueueTest extends TestCase TestMessage(long tag, long messageId, MessagePublishInfo publishBody, ContentHeaderBody chb) throws AMQException { - super(createMessageHandle(messageId, publishBody, chb), chb, 0, publishBody); + super(new MockStoredMessage(messageId, publishBody, chb)); _tag = tag; } @@ -481,7 +475,7 @@ public class SimpleAMQQueueTest extends TestCase return true; } - public void decrementReference(StoreContext context) + public void decrementReference() { _count--; } @@ -494,7 +488,7 @@ public class SimpleAMQQueueTest extends TestCase protected AMQMessage createMessage(Long id) throws AMQException { - AMQMessage messageA = new TestMessage(id, id, info, new StoreContext()); + AMQMessage messageA = new TestMessage(id, id, info); return messageA; } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java index 02de09c91f..ba94af5936 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java @@ -27,8 +27,6 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.AMQException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SimpleAMQQueueThreadPoolTest extends TestCase { @@ -47,7 +45,7 @@ public class SimpleAMQQueueThreadPoolTest extends TestCase assertFalse("Creation did not start Pool.", ReferenceCountingExecutorService.getInstance().getPool().isShutdown()); assertEquals("References not increased", initialCount + 1, ReferenceCountingExecutorService.getInstance().getReferenceCount()); - + queue.stop(); assertEquals("References not decreased", initialCount , ReferenceCountingExecutorService.getInstance().getReferenceCount()); @@ -55,6 +53,6 @@ public class SimpleAMQQueueThreadPoolTest extends TestCase finally { ApplicationRegistry.remove(); - } + } } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java index 8102360ce0..44f9861e8d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java @@ -57,11 +57,11 @@ public class ACLManagerTest extends TestCase BufferedWriter out = new BufferedWriter(new FileWriter(tmpFile)); out.write("<security><queueDenier>notyet</queueDenier><exchangeDenier>yes</exchangeDenier></security>"); out.close(); - + _conf = new SecurityConfiguration(new XMLConfiguration(tmpFile)); - + // Create ACLManager - + _pluginManager = new MockPluginManager(""); _authzManager = new ACLManager(_conf, _pluginManager); @@ -79,15 +79,15 @@ public class ACLManagerTest extends TestCase // Correctly Close the AR we created ApplicationRegistry.remove(); super.tearDown(); - } - + } + public void testACLManagerConfigurationPluginManager() throws Exception { AMQQueue queue = new MockAMQQueue("notyet"); AMQQueue otherQueue = new MockAMQQueue("other"); - + assertFalse(_authzManager.authoriseDelete(_session, queue)); - + // This should only be denied if the config hasn't been correctly passed in assertTrue(_authzManager.authoriseDelete(_session, otherQueue)); assertTrue(_authzManager.authorisePurge(_session, queue)); @@ -96,11 +96,11 @@ public class ACLManagerTest extends TestCase public void testACLManagerConfigurationPluginManagerACLPlugin() throws ConfigurationException { _authzManager = new ACLManager(_conf, _pluginManager, ExchangeDenier.FACTORY); - + Exchange exchange = null; assertFalse(_authzManager.authoriseDelete(_session, exchange)); } - + public void testConfigurePlugins() throws ConfigurationException { Configuration hostConfig = new PropertiesConfiguration(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java index 0e754e2c87..37a0fd7fc3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java @@ -14,17 +14,16 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.security.access; import org.apache.commons.configuration.Configuration; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.security.access.plugins.AllowAll; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; public class ExchangeDenier extends AllowAll { @@ -41,7 +40,7 @@ public class ExchangeDenier extends AllowAll return new ExchangeDenier(); } }; - + @Override public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange) { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java index 69c8ccaa5d..28161a0229 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java @@ -27,14 +27,13 @@ import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.amqp_0_9.ExchangeDeclareBodyImpl; -import org.apache.qpid.framing.amqp_0_9.QueueDeclareBodyImpl; import org.apache.qpid.framing.amqp_8_0.QueueBindBodyImpl; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; -import org.apache.qpid.server.store.SkeletonMessageStore; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.registry.ApplicationRegistry; @@ -43,7 +42,7 @@ public class PrincipalPermissionsTest extends TestCase private String _user = "user"; private PrincipalPermissions _perms; - + // Common things that are passed to frame constructors private AMQShortString _queueName = new AMQShortString(this.getClass().getName()+"queue"); private AMQShortString _exchangeName = new AMQShortString("amq.direct"); @@ -62,21 +61,21 @@ public class PrincipalPermissionsTest extends TestCase private AMQShortString _owner = new AMQShortString(this.getClass().getName()+"owner"); private AMQQueue _queue; private Boolean _temporary = false; - + @Override public void setUp() { //Highlight that this test will cause a new AR to be created - ApplicationRegistry.getInstance(); + ApplicationRegistry.getInstance(); _perms = new PrincipalPermissions(_user); - try + try { PropertiesConfiguration env = new PropertiesConfiguration(); - _virtualHost = new VirtualHost(new VirtualHostConfiguration("test", env)); + _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration("test", env)); _exchange = DirectExchange.TYPE.newInstance(_virtualHost, _exchangeName, _durable, _ticket, _autoDelete); _queue = AMQQueueFactory.createAMQQueueImpl(_queueName, false, _owner , false, _virtualHost, _arguments); - } + } catch (Exception e) { fail(e.getMessage()); @@ -103,7 +102,7 @@ public class PrincipalPermissionsTest extends TestCase { QueueBindBodyImpl bind = new QueueBindBodyImpl(_ticket, _queueName, _exchangeName, _routingKey, _nowait, _arguments); Object[] args = new Object[]{bind, _exchange, _queue, _routingKey}; - + assertEquals(AuthzResult.DENIED, _perms.authorise(Permission.BIND, args)); _perms.grant(Permission.BIND, (Object[]) null); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.BIND, args)); @@ -113,7 +112,7 @@ public class PrincipalPermissionsTest extends TestCase { Object[] grantArgs = new Object[]{_temporary , _queueName, _exchangeName, _routingKey}; Object[] authArgs = new Object[]{_autoDelete, _queueName}; - + assertEquals(AuthzResult.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); _perms.grant(Permission.CREATEQUEUE, grantArgs); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); @@ -128,41 +127,41 @@ public class PrincipalPermissionsTest extends TestCase _perms.grant(Permission.CREATEQUEUE, grantArgs); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); } - + // FIXME disabled, this fails due to grant putting the grant into the wrong map QPID-1598 public void disableTestExchangeCreate() { - ExchangeDeclareBodyImpl exchangeDeclare = + ExchangeDeclareBodyImpl exchangeDeclare = new ExchangeDeclareBodyImpl(_ticket, _exchangeName, _exchangeType, _passive, _durable, _autoDelete, _internal, _nowait, _arguments); Object[] authArgs = new Object[]{exchangeDeclare}; Object[] grantArgs = new Object[]{_exchangeName, _exchangeType}; - + assertEquals(AuthzResult.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs)); _perms.grant(Permission.CREATEEXCHANGE, grantArgs); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs)); } - + public void testConsume() { Object[] authArgs = new Object[]{_queue}; Object[] grantArgs = new Object[]{_queueName, _temporary, _temporary}; - + /* FIXME: This throws a null pointer exception QPID-1599 * assertFalse(_perms.authorise(Permission.CONSUME, authArgs)); */ _perms.grant(Permission.CONSUME, grantArgs); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CONSUME, authArgs)); } - + public void testPublish() { Object[] authArgs = new Object[]{_exchange, _routingKey}; Object[] grantArgs = new Object[]{_exchange.getName(), _routingKey}; - + assertEquals(AuthzResult.DENIED, _perms.authorise(Permission.PUBLISH, authArgs)); _perms.grant(Permission.PUBLISH, grantArgs); assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgs)); } - + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java index a415d56601..5b76bf7532 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java @@ -14,22 +14,20 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.security.access; import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; import org.apache.qpid.server.security.access.plugins.AllowAll; -import org.apache.qpid.server.PrincipalHolder; +import org.apache.qpid.server.security.PrincipalHolder; public class QueueDenier extends AllowAll { - + public static final ACLPluginFactory FACTORY = new ACLPluginFactory() { public boolean supportsTag(String name) @@ -44,18 +42,18 @@ public class QueueDenier extends AllowAll return plugin; } }; - + private String _queueName = ""; - + @Override public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue) { if (!(queue.getName().toString().equals(_queueName))) { return AuthzResult.ALLOWED; - } - else + } + else { return AuthzResult.DENIED; } 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 18ba9c13ed..5169676dae 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,11 +29,13 @@ 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.virtualhost.VirtualHostImpl; import org.apache.qpid.server.queue.*; -import org.apache.qpid.server.txn.Transaction; +import org.apache.qpid.server.txn.ServerTransaction; 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.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.ContentHeaderBody; @@ -97,7 +99,7 @@ public class MessageStoreTest extends TestCase try { - _virtualHost = new VirtualHost(new VirtualHostConfiguration(getClass().getName(), configuration)); + _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration(getClass().getName(), configuration)); ApplicationRegistry.getInstance().getVirtualHostRegistry().registerVirtualHost(_virtualHost); } catch (Exception e) @@ -163,7 +165,7 @@ public class MessageStoreTest extends TestCase Exchange topicExchange = createExchange(TopicExchange.TYPE, topicExchangeName, true); bindAllTopicQueuesToExchange(topicExchange, topicRouting); - //Send Message To NonDurable direct Exchange = persistent + //Send Message To NonDurable direct Exchange = persistent sendMessageOnExchange(nonDurableExchange, directRouting, true); // and non-persistent sendMessageOnExchange(nonDurableExchange, directRouting, false); @@ -340,18 +342,8 @@ public class MessageStoreTest extends TestCase final IncomingMessage currentMessage; - try - { - currentMessage = new IncomingMessage(_virtualHost.getMessageStore().getNewMessageId(), - messageInfo, - new InternalTestProtocolSession(_virtualHost)); - } - catch (AMQException e) - { - fail(e.getMessage()); - //help compiler - next line never reached - throw new RuntimeException(); - } + + currentMessage = new IncomingMessage(messageInfo); currentMessage.setExchange(directExchange); @@ -372,31 +364,25 @@ public class MessageStoreTest extends TestCase currentMessage.setExpiration(); + MessageMetaData mmd = currentMessage.headersReceived(); + currentMessage.setStoredMessage(_virtualHost.getMessageStore().addMessage(mmd)); currentMessage.route(); - try - { - currentMessage.routingComplete(_virtualHost.getMessageStore(), new MessageHandleFactory()); - } - catch (AMQException e) - { - fail(e.getMessage()); - } // check and deliver if header says body length is zero if (currentMessage.allContentReceived()) { // TODO Deliver to queues - Transaction trans = new AutoCommitTransaction(_virtualHost.getMessageStore()); + ServerTransaction trans = new AutoCommitTransaction(_virtualHost.getMessageStore()); final List<AMQQueue> destinationQueues = currentMessage.getDestinationQueues(); - trans.enqueue(currentMessage.getDestinationQueues(), currentMessage, new Transaction.Action() { + trans.enqueue(currentMessage.getDestinationQueues(), currentMessage, new ServerTransaction.Action() { public void postCommit() { try { - AMQMessage message = new AMQMessage(currentMessage.getMessageHandle(), currentMessage.getContentHeader(), currentMessage.getSize() ,currentMessage.getMessagePublishInfo()); + AMQMessage message = new AMQMessage(currentMessage.getStoredMessage()); for(AMQQueue queue : destinationQueues) { @@ -405,7 +391,7 @@ public class MessageStoreTest extends TestCase } catch (AMQException e) { - e.printStackTrace(); + e.printStackTrace(); } } @@ -502,14 +488,7 @@ public class MessageStoreTest extends TestCase fail(e.getMessage()); } - try - { - _virtualHost.getQueueRegistry().registerQueue(queue); - } - catch (AMQException e) - { - fail(e.getMessage()); - } + _virtualHost.getQueueRegistry().registerQueue(queue); } 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 ba04a14e09..9c12242a07 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 @@ -25,12 +25,11 @@ 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.queue.MessageMetaData; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.logging.LogSubject; import java.util.List; import java.util.concurrent.atomic.AtomicLong; @@ -47,8 +46,19 @@ public class SkeletonMessageStore implements MessageStore public void configure(String base, Configuration config) throws Exception { } - - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception + + public void configureConfigStore(String name, + ConfigurationRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void configureMessageStore(String name, + MessageStoreRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception { //To change body of implemented methods use File | Settings | File Templates. } @@ -57,6 +67,11 @@ public class SkeletonMessageStore implements MessageStore { } + public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData) + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + public void removeMessage(Long messageId) { } @@ -87,41 +102,10 @@ public class SkeletonMessageStore implements MessageStore public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException { - } - - public void beginTran(StoreContext s) throws AMQException - { - } - - public boolean inTran(StoreContext sc) - { - return false; - } - - public void commitTran(StoreContext storeContext) throws AMQException - { } - 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 - { - } public List<AMQQueue> createQueues() throws AMQException { @@ -182,13 +166,55 @@ public class SkeletonMessageStore implements MessageStore } - public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception { - + //To change body of implemented methods use File | Settings | File Templates. } - public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + public Transaction newTransaction() { + return new Transaction() + { + + public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void commitTran() throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } + public StoreFuture commitTranAsync() throws AMQException + { + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + } + + public void abortTran() throws AMQException + { + //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/TestMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java index 4e48435962..4dea13d391 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java @@ -20,32 +20,79 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.server.queue.MessageMetaData; -import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.framing.abstraction.ContentChunk; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.List; +import java.nio.ByteBuffer; /** * Adds some extra methods to the memory message store for testing purposes. */ public class TestMemoryMessageStore extends MemoryMessageStore { + private AtomicInteger _messageCount = new AtomicInteger(0); + + public TestMemoryMessageStore() { - _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>(); - _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>(); } - public ConcurrentMap<Long, MessageMetaData> getMessageMetaDataMap() + @Override + public StoredMessage addMessage(StorableMessageMetaData metaData) { - return _metaDataMap; + return new TestableStoredMessage(super.addMessage(metaData)); } - public ConcurrentMap<Long, List<ContentChunk>> getContentBodyMap() + public int getMessageCount() { - return _contentBodyMap; + return _messageCount.get(); + } + + private class TestableStoredMessage implements StoredMessage + { + private final StoredMessage _storedMessage; + + public TestableStoredMessage(StoredMessage storedMessage) + { + _messageCount.incrementAndGet(); + _storedMessage = storedMessage; + } + + public StorableMessageMetaData getMetaData() + { + return _storedMessage.getMetaData(); + } + + public long getMessageNumber() + { + return _storedMessage.getMessageNumber(); + } + + public void addContent(int offsetInMessage, ByteBuffer src) + { + _storedMessage.addContent(offsetInMessage, src); + } + + public int getContent(int offsetInMessage, ByteBuffer dst) + { + return _storedMessage.getContent(offsetInMessage, dst); + } + + public StoreFuture flushToStore() + { + return _storedMessage.flushToStore(); + } + + public void remove() + { + _storedMessage.remove(); + _messageCount.decrementAndGet(); + } + } + } 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 f44330d00c..c5b1ba7868 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 @@ -26,10 +26,8 @@ import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.AMQShortString; 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; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; /** * Tests that reference counting works correctly with AMQMessage and the message store @@ -83,15 +81,12 @@ public class TestReferenceCounting extends TestCase }; - final long messageId = _store.getNewMessageId(); - AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true); - MessageMetaData mmd = messageHandle.setPublishAndContentHeaderBody(info, chb); - _store.storeMessageMetaData(messageId, mmd); + MessageMetaData mmd = new MessageMetaData(info, chb, 0); + StoredMessage storedMessage = _store.addMessage(mmd); - AMQMessage message = new AMQMessage(messageHandle, - chb, chb.bodySize,info); + AMQMessage message = new AMQMessage(storedMessage); message = message.takeReference(); @@ -99,9 +94,9 @@ public class TestReferenceCounting extends TestCase // message.routingComplete(_store, _storeContext, new MessageHandleFactory()); - assertEquals(1, _store.getMessageMetaDataMap().size()); + assertEquals(1, _store.getMessageCount()); message.decrementReference(); - assertEquals(1, _store.getMessageMetaDataMap().size()); + assertEquals(1, _store.getMessageCount()); } private ContentHeaderBody createPersistentContentHeader() @@ -145,28 +140,24 @@ public class TestReferenceCounting extends TestCase } }; - final Long messageId = _store.getNewMessageId(); final ContentHeaderBody chb = createPersistentContentHeader(); - AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true); - MessageMetaData mmd = messageHandle.setPublishAndContentHeaderBody(info, chb); - _store.storeMessageMetaData(messageId, mmd); + MessageMetaData mmd = new MessageMetaData(info, chb, 0); + StoredMessage storedMessage = _store.addMessage(mmd); + + AMQMessage message = new AMQMessage(storedMessage); + - AMQMessage message = new AMQMessage(messageHandle, - chb, chb.bodySize, - info); - - message = message.takeReference(); // we call routing complete to set up the handle // message.routingComplete(_store, _storeContext, new MessageHandleFactory()); - assertEquals(1, _store.getMessageMetaDataMap().size()); + assertEquals(1, _store.getMessageCount()); message = message.takeReference(); message.decrementReference(); - assertEquals(1, _store.getMessageMetaDataMap().size()); + assertEquals(1, _store.getMessageCount()); } public static junit.framework.Test suite() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java index 9146fe88ae..ab8c1e7c9c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java @@ -22,14 +22,15 @@ package org.apache.qpid.server.store; import org.apache.qpid.AMQException; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.MessageMetaData; -import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.framing.abstraction.ContentChunk; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; import java.util.List; +import java.nio.ByteBuffer; /** * Adds some extra methods to the memory message store for testing purposes. @@ -39,6 +40,7 @@ public class TestableMemoryMessageStore extends MemoryMessageStore MemoryMessageStore _mms = null; private HashMap<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>(); + private AtomicInteger _messageCount = new AtomicInteger(0); public TestableMemoryMessageStore(MemoryMessageStore mms) { @@ -47,46 +49,111 @@ public class TestableMemoryMessageStore extends MemoryMessageStore public TestableMemoryMessageStore() { - _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>(); - _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>(); + + } + + + + + @Override + public StoredMessage addMessage(StorableMessageMetaData metaData) + { + return new TestableStoredMessage(super.addMessage(metaData)); + } + + public int getMessageCount() + { + return _messageCount.get(); } - public ConcurrentMap<Long, MessageMetaData> getMessageMetaDataMap() + private class TestableTransaction implements Transaction { - if (_mms != null) + public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException { - return _mms._metaDataMap; + getMessages().put(messageId, (AMQQueue)queue); } - else + + public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException { - return _metaDataMap; + getMessages().remove(messageId); } - } - public ConcurrentMap<Long, List<ContentChunk>> getContentBodyMap() - { - if (_mms != null) + public void commitTran() throws AMQException { - return _mms._contentBodyMap; } - else + + public StoreFuture commitTranAsync() throws AMQException + { + return new StoreFuture() + { + public boolean isComplete() + { + return true; + } + + public void waitForCompletion() + { + + } + }; + } + + public void abortTran() throws AMQException { - return _contentBodyMap; } - } - - public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException - { - getMessages().put(messageId, queue); } - public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException + + @Override + public Transaction newTransaction() { - getMessages().remove(messageId); + return new TestableTransaction(); } public HashMap<Long, AMQQueue> getMessages() { return _messages; } + + private class TestableStoredMessage implements StoredMessage + { + private final StoredMessage _storedMessage; + + public TestableStoredMessage(StoredMessage storedMessage) + { + _messageCount.incrementAndGet(); + _storedMessage = storedMessage; + } + + public StorableMessageMetaData getMetaData() + { + return _storedMessage.getMetaData(); + } + + public long getMessageNumber() + { + return _storedMessage.getMessageNumber(); + } + + public void addContent(int offsetInMessage, ByteBuffer src) + { + _storedMessage.addContent(offsetInMessage, src); + } + + public int getContent(int offsetInMessage, ByteBuffer dst) + { + return _storedMessage.getContent(offsetInMessage, dst); + } + + public StoreFuture flushToStore() + { + return _storedMessage.flushToStore(); + } + + public void remove() + { + _storedMessage.remove(); + _messageCount.decrementAndGet(); + } + } } 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 deb97bc8b0..97ba143bdf 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 @@ -127,7 +127,17 @@ public class MockSubscription implements Subscription public void confirmAutoClose() { - + + } + + public void set(String key, Object value) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public Object get(String key) + { + return null; //To change body of implemented methods use File | Settings | File Templates. } public boolean isAutoClose() @@ -197,6 +207,10 @@ public class MockSubscription implements Subscription this.queue = queue; } + public void setNoLocal(boolean noLocal) + { + } + public void setStateListener(StateListener listener) { this._listener = listener; 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 c9f36d45c3..906c769f9c 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 @@ -31,7 +31,6 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.ConsumerTagNotUniqueException; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.exchange.Exchange; @@ -94,7 +93,7 @@ public class InternalBrokerBaseCase extends TestCase protected void checkStoreContents(int messageCount) { - assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageMetaDataMap().size()); + assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageCount()); //The above publish message is sufficiently small not to fit in the header so no Body is required. //assertEquals("Message body count incorrect in the ContentBodyMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getContentBodyMap().size()); @@ -111,11 +110,7 @@ public class InternalBrokerBaseCase extends TestCase e.printStackTrace(); fail(e.getMessage()); } - catch (ConsumerTagNotUniqueException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } + //Keep the compiler happy return null; } @@ -134,11 +129,7 @@ public class InternalBrokerBaseCase extends TestCase e.printStackTrace(); fail(e.getMessage()); } - catch (ConsumerTagNotUniqueException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } + //Keep the compiler happy return null; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java index 705e7d2ad7..4e78b5b413 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.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 @@ -35,8 +35,9 @@ import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.access.plugins.AllowAll; import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; -import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Arrays; import java.util.Collection; @@ -75,7 +76,7 @@ public class NullApplicationRegistry extends ApplicationRegistry _virtualHostRegistry = new VirtualHostRegistry(this); PropertiesConfiguration vhostProps = new PropertiesConfiguration(); VirtualHostConfiguration hostConfig = new VirtualHostConfiguration("test", vhostProps); - VirtualHost dummyHost = new VirtualHost(hostConfig); + VirtualHost dummyHost = new VirtualHostImpl(hostConfig); _virtualHostRegistry.registerVirtualHost(dummyHost); _virtualHostRegistry.setDefaultVirtualHostName("test"); _pluginManager = new PluginManager(""); @@ -94,7 +95,7 @@ public class NullApplicationRegistry extends ApplicationRegistry { try { - super.close(); + super.close(); } finally { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java index 7b7c86bb80..bb338458f1 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.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 @@ -35,8 +35,9 @@ import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.logging.RootMessageLoggerImpl; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; @@ -60,7 +61,7 @@ public class TestApplicationRegistry extends ApplicationRegistry private ServerConfiguration _config; - + public TestApplicationRegistry() throws ConfigurationException { super(new ServerConfiguration(new PropertiesConfiguration())); @@ -96,10 +97,10 @@ public class TestApplicationRegistry extends ApplicationRegistry _messageStore = new TestableMemoryMessageStore(); _virtualHostRegistry = new VirtualHostRegistry(this); - + PropertiesConfiguration vhostProps = new PropertiesConfiguration(); VirtualHostConfiguration hostConfig = new VirtualHostConfiguration("test", vhostProps); - _vHost = new VirtualHost(hostConfig, _messageStore); + _vHost = new VirtualHostImpl(hostConfig, _messageStore); _virtualHostRegistry.registerVirtualHost(_vHost); @@ -152,7 +153,7 @@ public class TestApplicationRegistry extends ApplicationRegistry CurrentActor.remove(); } } - + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java b/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java index 447d09429d..9bd1e7c5e1 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java @@ -35,9 +35,6 @@ public class MockChannel extends AMQChannel super(session, channelId, messageStore); } - public Subscription getSubscription(AMQShortString subscription) - { - return _tag2SubscriptionMap.get(subscription); - } - + + } diff --git a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java index ea0946f6d6..2efb22610f 100644 --- a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java +++ b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java @@ -108,6 +108,8 @@ public class GenerateLogMessages createMessageClass("ManagementConsole", "MNG"); createMessageClass("VirtualHost", "VHT"); createMessageClass("MessageStore", "MST"); + createMessageClass("ConfigStore", "CFG"); + createMessageClass("TransactionLog", "TXN"); createMessageClass("Connection", "CON"); createMessageClass("Channel", "CHN"); createMessageClass("Queue", "QUE"); @@ -465,4 +467,4 @@ public class GenerateLogMessages super(message); } } -}
\ No newline at end of file +} diff --git a/qpid/java/build.deps b/qpid/java/build.deps index 709f2a478e..464afdc136 100644 --- a/qpid/java/build.deps +++ b/qpid/java/build.deps @@ -82,7 +82,7 @@ tools.libs=${client.libs} broker.libs=${common.libs} ${commons-cli} ${commons-logging} ${log4j} \ ${slf4j-log4j} ${xalan} ${felix.libs} ${derby-db} -broker-plugins.libs=${common.libs} ${felix.libs} +broker-plugins.libs=${common.libs} ${felix.libs} ${log4j} management-client.libs=${jsp.libs} ${log4j} ${slf4j-log4j} ${slf4j-api} ${commons-pool} ${geronimo-servlet} ${muse.libs} ${javassist} ${xalan} ${mina-core} ${mina-filter-ssl} management-agent.libs=${client.libs} ${commons-logging} ${geronimo-jms} diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 1587d6a6bf..2324d441cc 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -468,7 +468,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic public boolean isQueueBound(final AMQShortString exchangeName, final AMQShortString queueName, final AMQShortString routingKey,AMQShortString[] bindingKeys) throws JMSException { - String rk = ""; + String rk = null; boolean res; if (bindingKeys != null && bindingKeys.length>0) { diff --git a/qpid/java/common/Composite.tpl b/qpid/java/common/Composite.tpl index c46d0a12cc..97b7d01f3c 100644 --- a/qpid/java/common/Composite.tpl +++ b/qpid/java/common/Composite.tpl @@ -127,7 +127,12 @@ if fields: ${ for f in fields: if f.option: continue - out(" $(f.set)($(f.name));\n") + if f.ref_type != f.type: + out(" $(f.set)($(f.name));\n") + else: + out(" if($(f.name) != null) {\n") + out(" $(f.set)($(f.name));\n") + out(" }\n") if segments: out(" setHeader(header);\n") diff --git a/qpid/java/common/genutil.py b/qpid/java/common/genutil.py index 5a75c2e48c..57a461ed40 100644 --- a/qpid/java/common/genutil.py +++ b/qpid/java/common/genutil.py @@ -198,6 +198,7 @@ class Field: self.read = "dec.read%s()" % self.coder self.write = "enc.write%s(check(struct).%s)" % (self.coder, self.name) self.type = jtype(self.type_node) + self.ref_type = jref(self.type) self.default = DEFAULTS.get(self.type, "null") self.has = camel(1, "has", self.name) self.get = camel(1, "get", self.name) diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java index 0a1cedc4e6..7544d9b7e7 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java @@ -23,10 +23,14 @@ package org.apache.qpid.framing.abstraction; import org.apache.qpid.framing.AMQBody; +import java.nio.ByteBuffer; + public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter { AMQBody convertToBody(ContentChunk contentBody); ContentChunk convertToContentChunk(AMQBody body); void configure(); + + AMQBody convertToBody(ByteBuffer buf); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java index a5c5e5f22d..1c4a29b106 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java @@ -72,6 +72,11 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot } + public AMQBody convertToBody(java.nio.ByteBuffer buf) + { + return new ContentBody(ByteBuffer.wrap(buf)); + } + public MessagePublishInfo convertToInfo(AMQMethodBody methodBody) { final BasicPublishBody publishBody = ((BasicPublishBody) methodBody); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java index 1b0be2b9cc..c87820b9b2 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java @@ -80,6 +80,11 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID; } + + public AMQBody convertToBody(java.nio.ByteBuffer buf) + { + return new ContentBody(ByteBuffer.wrap(buf)); + } public MessagePublishInfo convertToInfo(AMQMethodBody methodBody) { diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java index 1c732d31e6..818bb19c08 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java @@ -493,13 +493,28 @@ public class Session extends SessionInvoker } } - final private boolean isFull(int id) + protected boolean isFull(int id) { - return id - maxComplete >= commands.length || commandBytes >= byteLimit; + return isCommandsFull(id) || isBytesFull(); + } + + protected boolean isBytesFull() + { + return commandBytes >= byteLimit; + } + + protected boolean isCommandsFull(int id) + { + return id - maxComplete >= commands.length; } public void invoke(Method m) { + invoke(m,(Runnable)null); + } + + public void invoke(Method m, Runnable postIdSettingAction) + { if (m.getEncodedTrack() == Frame.L4) { if (m.hasPayload()) @@ -563,6 +578,10 @@ public class Session extends SessionInvoker int next; next = commandsOut++; m.setId(next); + if(postIdSettingAction != null) + { + postIdSettingAction.run(); + } if (isFull(next)) { @@ -625,6 +644,7 @@ public class Session extends SessionInvoker m.setSync(true); } needSync = !m.isSync(); + try { send(m); @@ -649,7 +669,7 @@ public class Session extends SessionInvoker // flush every 64K commands to avoid ambiguity on // wraparound - if ((next % 65536) == 0) + if (shouldIssueFlush(next)) { try { @@ -677,6 +697,11 @@ public class Session extends SessionInvoker } } + protected boolean shouldIssueFlush(int next) + { + return (next % 65536) == 0; + } + public void sync() { sync(timeout); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index b0d1c46572..3838bf76be 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -229,7 +229,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver if (_socketConnector instanceof SocketConnector) { ((SocketConnector) _socketConnector).setWorkerTimeout(0); - } + } ConnectFuture future = _socketConnector.connect(new InetSocketAddress(destination, port), this, cfg); future.join(); @@ -279,7 +279,10 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver public void send(ByteBuffer msg) { - _lastWriteFuture = _ioSession.write(org.apache.mina.common.ByteBuffer.wrap(msg)); + org.apache.mina.common.ByteBuffer minaBuf = org.apache.mina.common.ByteBuffer.allocate(msg.capacity()); + minaBuf.put(msg); + minaBuf.flip(); + _lastWriteFuture = _ioSession.write(minaBuf); } public void setIdleTimeout(long l) diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java index 784943b404..b2fdf48267 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java @@ -113,12 +113,12 @@ public class MessageListenerMultiConsumerTest extends QpidTestCase for (int loops = 0; (msg < MSG_COUNT) || (loops < MAX_LOOPS); loops++) { - if (_consumer1.receive(100) != null) + if (_consumer1.receive(1000) != null) { msg++; } - if (_consumer2.receive(100) != null) + if (_consumer2.receive(1000) != null) { msg++; } 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 14dfe448ae..fe25bf07f0 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 @@ -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 @@ -60,6 +60,11 @@ public class SubscriptionTestHelper implements Subscription public void setQueue(AMQQueue queue, boolean exclusive) { + + } + + public void setNoLocal(boolean noLocal) + { } @@ -117,7 +122,7 @@ public class SubscriptionTestHelper implements Subscription { //To change body of implemented methods use File | Settings | File Templates. } - + public State getState() { return null; //To change body of implemented methods use File | Settings | File Templates. @@ -142,7 +147,7 @@ public class SubscriptionTestHelper implements Subscription { return null; } - + public void start() { //no-op @@ -168,6 +173,16 @@ public class SubscriptionTestHelper implements Subscription //To change body of implemented methods use File | Settings | File Templates. } + public void set(String key, Object value) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public Object get(String key) + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + public LogActor getLogActor() { return null; //To change body of implemented methods use File | Settings | File Templates. 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 bbb889107c..b41aa661ea 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 @@ -25,13 +25,10 @@ import org.apache.log4j.Logger; 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.virtualhost.VirtualHost; -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.queue.MessageMetaData; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.logging.LogSubject; import java.util.HashMap; import java.util.Iterator; @@ -49,14 +46,21 @@ public class SlowMessageStore implements MessageStore private static final String POST = "post"; private String DEFAULT_DELAY = "default"; - public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception + // ***** MessageStore Interface. + + public void configureConfigStore(String name, + ConfigurationRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception { - _logger.info("Starting SlowMessageStore on Virtualhost:" + virtualHost.getName()); - Configuration delays = config.getStoreConfiguration().subset(DELAYS); + //To change body of implemented methods use File | Settings | File Templates. + + _logger.info("Starting SlowMessageStore on Virtualhost:" + name); + Configuration delays = config.subset(DELAYS); configureDelays(delays); - String messageStoreClass = config.getStoreConfiguration().getString("realStore"); + String messageStoreClass = config.getString("realStore"); if (delays.containsKey(DEFAULT_DELAY)) { @@ -75,11 +79,11 @@ public class SlowMessageStore implements MessageStore " does not."); } _realStore = (MessageStore) o; - _realStore.configure(virtualHost, base + ".store", config); + _realStore.configureConfigStore(name, recoveryHandler, config, logSubject); } else { - _realStore.configure(virtualHost, base + ".store", config); + _realStore.configureConfigStore(name, recoveryHandler, config, logSubject); } } @@ -135,7 +139,7 @@ public class SlowMessageStore implements MessageStore } long slept = (System.nanoTime() - start) / 1000000; - + if (slept >= delay) { _logger.info("Done sleep for:" + slept+":"+delay); @@ -148,7 +152,14 @@ public class SlowMessageStore implements MessageStore } } - // ***** MessageStore Interface. + + public void configureMessageStore(String name, + MessageStoreRecoveryHandler recoveryHandler, + Configuration config, + LogSubject logSubject) throws Exception + { + _realStore.configureMessageStore(name, recoveryHandler, config, logSubject); + } public void close() throws Exception { @@ -157,13 +168,12 @@ public class SlowMessageStore implements MessageStore doPostDelay("close"); } - public void removeMessage(Long messageId) throws AMQException + public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData) { - doPreDelay("removeMessage"); - _realStore.removeMessage(messageId); - doPostDelay("removeMessage"); + return _realStore.addMessage(metaData); } + public void createExchange(Exchange exchange) throws AMQException { doPreDelay("createExchange"); @@ -211,127 +221,93 @@ public class SlowMessageStore implements MessageStore doPostDelay("removeQueue"); } - public void enqueueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, LogSubject logSubject) + throws Exception { - doPreDelay("enqueueMessage"); - _realStore.enqueueMessage(context, queue, messageId); - doPostDelay("enqueueMessage"); + _realStore.configureTransactionLog(name, recoveryHandler, storeConfiguration, logSubject); } - public void dequeueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException - { - doPreDelay("dequeueMessage"); - _realStore.dequeueMessage(context, queue, messageId); - doPostDelay("dequeueMessage"); - } - - public void beginTran(StoreContext context) throws AMQException + public Transaction newTransaction() { doPreDelay("beginTran"); - _realStore.beginTran(context); + Transaction txn = new SlowTransaction(_realStore.newTransaction()); doPostDelay("beginTran"); + return txn; } - public void commitTran(StoreContext context) throws AMQException - { - doPreDelay("commitTran"); - _realStore.commitTran(context); - doPostDelay("commitTran"); - } - public StoreFuture commitTranAsync(StoreContext context) throws AMQException + public boolean isPersistent() { - commitTran(context); - return new StoreFuture() - { - public boolean isComplete() - { - return true; - } - - public void waitForCompletion() - { - - } - }; - + return _realStore.isPersistent(); } - public void abortTran(StoreContext context) throws AMQException + public void storeMessageHeader(Long messageNumber, ServerMessage message) { - doPreDelay("abortTran"); - _realStore.abortTran(context); - doPostDelay("abortTran"); + //To change body of implemented methods use File | Settings | File Templates. } - public boolean inTran(StoreContext context) + public void storeContent(Long messageNumber, long offset, ByteBuffer body) { - doPreDelay("inTran"); - boolean b = _realStore.inTran(context); - doPostDelay("inTran"); - return b; + //To change body of implemented methods use File | Settings | File Templates. } - public Long getNewMessageId() + public ServerMessage getMessage(Long messageNumber) { - doPreDelay("getNewMessageId"); - Long l = _realStore.getNewMessageId(); - doPostDelay("getNewMessageId"); - return l; + return null; //To change body of implemented methods use File | Settings | File Templates. } - public void storeContentBodyChunk( - Long messageId, - int index, - ContentChunk contentBody, - boolean lastContentBody) throws AMQException + private class SlowTransaction implements Transaction { - doPreDelay("storeContentBodyChunk"); - _realStore.storeContentBodyChunk(messageId, index, contentBody, lastContentBody); - doPostDelay("storeContentBodyChunk"); - } + private final Transaction _underlying; - public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException - { - doPreDelay("storeMessageMetaData"); - _realStore.storeMessageMetaData(messageId, messageMetaData); - doPostDelay("storeMessageMetaData"); - } + private SlowTransaction(Transaction underlying) + { + _underlying = underlying; + } - public MessageMetaData getMessageMetaData(Long messageId) throws AMQException - { - doPreDelay("getMessageMetaData"); - MessageMetaData mmd = _realStore.getMessageMetaData(messageId); - doPostDelay("getMessageMetaData"); - return mmd; - } + public void enqueueMessage(TransactionLogResource queue, Long messageId) + throws AMQException + { + doPreDelay("enqueueMessage"); + _underlying.enqueueMessage(queue, messageId); + doPostDelay("enqueueMessage"); + } - public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException - { - doPreDelay("getContentBodyChunk"); - ContentChunk c = _realStore.getContentBodyChunk(messageId, index); - doPostDelay("getContentBodyChunk"); - return c; - } + public void dequeueMessage(TransactionLogResource queue, Long messageId) + throws AMQException + { + doPreDelay("dequeueMessage"); + _underlying.dequeueMessage(queue, messageId); + doPostDelay("dequeueMessage"); + } - public boolean isPersistent() - { - return _realStore.isPersistent(); - } + public void commitTran() + throws AMQException + { + doPreDelay("commitTran"); + _underlying.commitTran(); + doPostDelay("commitTran"); + } - public void storeMessageHeader(Long messageNumber, ServerMessage message) - { - //To change body of implemented methods use File | Settings | File Templates. - } + public StoreFuture commitTranAsync() + throws AMQException + { + doPreDelay("commitTran"); + StoreFuture future = _underlying.commitTranAsync(); + doPostDelay("commitTran"); + return future; + } - public void storeContent(Long messageNumber, long offset, ByteBuffer body) - { - //To change body of implemented methods use File | Settings | File Templates. + public void abortTran() + throws AMQException + { + doPreDelay("abortTran"); + _underlying.abortTran(); + doPostDelay("abortTran"); + } } - public ServerMessage getMessage(Long messageNumber) - { - return null; //To change body of implemented methods use File | Settings | File Templates. - } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java index 25b9b0ba14..5ea203bda3 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java @@ -81,9 +81,14 @@ public class CancelTest extends QpidTestCase assertTrue(e.hasMoreElements()); + int i = 0; while (e.hasMoreElements()) { e.nextElement(); + if(++i > 1) + { + fail("Two many elemnts to browse!"); + } } browser.close(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java index d1bcaa1bb8..eb0c539a6e 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java @@ -79,7 +79,7 @@ public class DupsOkTest extends QpidTestCase * This test sends x messages and receives them with an async consumer. * Waits for all messages to be received or for 60 s * and checks whether the queue is empty. - * + * * @throws Exception */ public void testDupsOK() throws Exception @@ -93,7 +93,7 @@ public class DupsOkTest extends QpidTestCase assertEquals("The queue should have msgs at start", MSG_COUNT, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue)); - clientConnection.start(); + clientConnection.start(); consumer.setMessageListener(new MessageListener() { @@ -110,7 +110,7 @@ public class DupsOkTest extends QpidTestCase if (message instanceof TextMessage) { try - { + { if (message.getIntProperty("count") == MSG_COUNT) { try @@ -156,7 +156,11 @@ public class DupsOkTest extends QpidTestCase // before the dispatcher has sent the ack back to the broker. consumer.close(); - assertEquals("The queue should have 0 msgs left", 0, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue)); + clientSession.close(); + + final Session clientSession2 = clientConnection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE); + + assertEquals("The queue should have 0 msgs left", 0, ((AMQSession) clientSession2).getQueueDepth((AMQDestination) _queue)); clientConnection.close(); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java index e9aed4de01..9558f23b89 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java @@ -79,16 +79,22 @@ public class LargeMessageTest extends QpidTestCase } // Test boundary of 1 packet to 2 packets - public void test64kminus1() + public void test64kminus9() { - checkLargeMessage((64 * 1024) - 1); + checkLargeMessage((64 * 1024) - 9); } - public void test64k() + public void test64kminus8() { - checkLargeMessage(64 * 1024); + checkLargeMessage((64 * 1024)-8); } + public void test64kminus7() + { + checkLargeMessage((64 * 1024)-7); + } + + public void test64kplus1() { checkLargeMessage((64 * 1024) + 1); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java index ec23256f38..f1cac22f08 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java @@ -50,7 +50,8 @@ public class MessageRequeueTest extends QpidTestCase protected final String queue = "direct://amq.direct//message-requeue-test-queue"; protected String payload = "Message:"; - protected final String BROKER = "vm://:1"; + //protected final String BROKER = "vm://:1"; + protected final String BROKER = "tcp://127.0.0.1:5672"; private boolean testReception = true; private long[] receieved = new long[numTestMessages + 1]; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java index 19b73fcc7c..f50f3e9332 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java @@ -34,7 +34,7 @@ public class DurableSubscriberTest extends QpidTestCase * create and register a durable subscriber then close it * create a publisher and send a persistant message followed by a non persistant message * crash and restart the broker - * recreate the durable subscriber and check that only the first message is received + * recreate the durable subscriber and check that only the first message is received white st */ public void testDurSubRestoredAfterNonPersistentMessageSent() throws Exception { diff --git a/qpid/java/test-profiles/java.0.10.testprofile b/qpid/java/test-profiles/java.0.10.testprofile new file mode 100755 index 0000000000..35e3530cab --- /dev/null +++ b/qpid/java/test-profiles/java.0.10.testprofile @@ -0,0 +1,8 @@ +broker.language=java +broker.version=0-10 +broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml +broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work/derbyDB +broker.ready=BRK-1004 +broker.stopped=Exception + +profile.excludes=08TransientExcludes 08StandaloneExcludes 010Excludes 010TransientExcludes |