diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2011-12-28 13:02:41 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2011-12-28 13:02:41 +0000 |
commit | 6d4226a532443ab1fe33c7d486877dbb11e154de (patch) | |
tree | 98b300c1fa6885cdabdc18ad18c7587627d6dc32 | |
parent | 2f1ced0ba4334901984de39134c0e0b9337fa5ad (diff) | |
download | qpid-python-6d4226a532443ab1fe33c7d486877dbb11e154de.tar.gz |
QPID-3714 : [Java] Performance Improvements
Persistence:
Store message in same transaction as enqueue if possible
Memory:
Remove unnecessary (un)boxing
Reduce unnecessary copying of message data
Cache short strings
Cache queues for a given routing key on an Exchange
(0-9) Use a fixed size buffer for preparing frames to write out
Other:
Reduce calls to System.currentTimeMillis
(0-10) Special case immutable RangeSets, in particular RangeSets of a single range/point
(0-10) Special case delivery properties and message properties in headers
(0-9) send commit-ok as soon as data committed to store
Cache publishing access control queries
(0-9) Optimised long and int typed values for FieldTables
(0-9) Retain FieldTable encoded form
(0-9) Cache queue and topic destinations
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1225178 13f79535-47bb-0310-9956-ffa450edef68
156 files changed, 5123 insertions, 3308 deletions
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java index f900159808..1d8187401d 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.store.berkeleydb; import java.io.File; import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.LinkedList; @@ -32,6 +33,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import com.sleepycat.bind.tuple.LongBinding; +import com.sleepycat.je.*; import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; import org.apache.qpid.AMQStoreException; @@ -43,6 +46,7 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.ConfigurationRecoveryHandler; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -70,17 +74,6 @@ import org.apache.qpid.server.store.berkeleydb.tuples.QueueTupleBindingFactory; import com.sleepycat.bind.EntryBinding; import com.sleepycat.bind.tuple.ByteBinding; import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.je.CheckpointConfig; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.TransactionConfig; /** * BDBMessageStore implements a persistent {@link MessageStore} using the BDB high performance log. @@ -91,7 +84,7 @@ import com.sleepycat.je.TransactionConfig; * dequeue messages to queues. <tr><td> Generate message identifiers. </table> */ @SuppressWarnings({"unchecked"}) -public class BDBMessageStore implements MessageStore +public class BDBMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger _log = Logger.getLogger(BDBMessageStore.class); @@ -205,18 +198,15 @@ public class BDBMessageStore implements MessageStore Configuration storeConfiguration, LogSubject logSubject) throws Exception { - _logSubject = logSubject; - CurrentActor.get().message(_logSubject, ConfigStoreMessages.CREATED(this.getClass().getName())); + CurrentActor.get().message(logSubject, ConfigStoreMessages.CREATED(this.getClass().getName())); - if(_configured) + if(!_configured) { - throw new Exception("ConfigStore already configured"); + _logSubject = logSubject; + configure(name,storeConfiguration); + _configured = true; + stateTransition(State.CONFIGURING, State.CONFIGURED); } - - configure(name,storeConfiguration); - - _configured = true; - stateTransition(State.CONFIGURING, State.CONFIGURED); recover(recoveryHandler); stateTransition(State.RECOVERING, State.STARTED); @@ -227,24 +217,31 @@ public class BDBMessageStore implements MessageStore Configuration storeConfiguration, LogSubject logSubject) throws Exception { - CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName())); + CurrentActor.get().message(logSubject, MessageStoreMessages.CREATED(this.getClass().getName())); if(!_configured) { - throw new Exception("ConfigStore not configured"); + _logSubject = logSubject; + configure(name,storeConfiguration); + _configured = true; + stateTransition(State.CONFIGURING, State.CONFIGURED); } - + recoverMessages(recoveryHandler); } public void configureTransactionLog(String name, TransactionLogRecoveryHandler recoveryHandler, Configuration storeConfiguration, LogSubject logSubject) throws Exception { - CurrentActor.get().message(_logSubject, TransactionLogMessages.CREATED(this.getClass().getName())); + CurrentActor.get().message(logSubject, TransactionLogMessages.CREATED(this.getClass().getName())); + if(!_configured) { - throw new Exception("ConfigStore not configured"); + _logSubject = logSubject; + configure(name,storeConfiguration); + _configured = true; + stateTransition(State.CONFIGURING, State.CONFIGURED); } recoverQueueEntries(recoveryHandler); @@ -252,7 +249,7 @@ public class BDBMessageStore implements MessageStore } - public org.apache.qpid.server.store.TransactionLog.Transaction newTransaction() + public org.apache.qpid.server.store.MessageStore.Transaction newTransaction() { return new BDBTransaction(); } @@ -686,8 +683,6 @@ public class BDBMessageStore implements MessageStore { cursor = _messageMetaDataDb.openCursor(null, null); DatabaseEntry key = new DatabaseEntry(); - EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class);; - DatabaseEntry value = new DatabaseEntry(); EntryBinding valueBinding = _metaDataTupleBindingFactory.getInstance(); @@ -695,7 +690,7 @@ public class BDBMessageStore implements MessageStore while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) { - long messageId = (Long) keyBinding.entryToObject(key); + long messageId = LongBinding.entryToLong(key); StorableMessageMetaData metaData = (StorableMessageMetaData) valueBinding.entryToObject(value); StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, false); @@ -781,10 +776,15 @@ public class BDBMessageStore implements MessageStore * * @param messageId Identifies the message to remove. * - * @throws AMQInternalException If the operation fails for any reason. + * @throws AMQStoreException If the operation fails for any reason. */ - public void removeMessage(Long messageId) throws AMQStoreException + public void removeMessage(long messageId) throws AMQStoreException + { + removeMessage(messageId, true); + } + public void removeMessage(long messageId, boolean sync) throws AMQStoreException { + // _log.debug("public void removeMessage(Long messageId = " + messageId): called"); com.sleepycat.je.Transaction tx = null; @@ -796,8 +796,7 @@ public class BDBMessageStore implements MessageStore //remove the message meta data from the store DatabaseEntry key = new DatabaseEntry(); - EntryBinding metaKeyBindingTuple = TupleBinding.getPrimitiveBinding(Long.class); - metaKeyBindingTuple.objectToEntry(messageId, key); + LongBinding.longToEntry(messageId, key); if (_log.isDebugEnabled()) { @@ -808,9 +807,8 @@ public class BDBMessageStore implements MessageStore OperationStatus status = _messageMetaDataDb.delete(tx, key); if (status == OperationStatus.NOTFOUND) { - tx.abort(); - - throw new AMQStoreException("Message metadata not found for message id " + messageId); + _log.info("Message not found (attempt to remove failed - probably application initiated rollback) " + + messageId); } if (_log.isDebugEnabled()) @@ -868,7 +866,7 @@ public class BDBMessageStore implements MessageStore cursor.close(); cursor = null; - commit(tx, true); + commit(tx, sync); } catch (DatabaseException e) { @@ -1174,11 +1172,12 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason. */ - public void enqueueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, + long messageId) throws AMQStoreException { // _log.debug("public void enqueueMessage(Transaction tx = " + tx + ", AMQShortString name = " + name + ", Long messageId): called"); - AMQShortString name = new AMQShortString(queue.getResourceName()); + AMQShortString name = AMQShortString.valueOf(queue.getResourceName()); DatabaseEntry key = new DatabaseEntry(); EntryBinding keyBinding = new QueueEntryTB(); @@ -1212,7 +1211,8 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. */ - public void dequeueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, + long messageId) throws AMQStoreException { AMQShortString name = new AMQShortString(queue.getResourceName()); @@ -1383,7 +1383,7 @@ public class BDBMessageStore implements MessageStore * * @return A fresh message id. */ - public Long getNewMessageId() + public long getNewMessageId() { return _messageId.incrementAndGet(); } @@ -1398,7 +1398,7 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. */ - protected void addContent(final com.sleepycat.je.Transaction tx, Long messageId, int offset, + protected void addContent(final com.sleepycat.je.Transaction tx, long messageId, int offset, ByteBuffer contentBody) throws AMQStoreException { DatabaseEntry key = new DatabaseEntry(); @@ -1436,7 +1436,8 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. */ - private void storeMetaData(final com.sleepycat.je.Transaction tx, Long messageId, StorableMessageMetaData messageMetaData) + private void storeMetaData(final com.sleepycat.je.Transaction tx, long messageId, + StorableMessageMetaData messageMetaData) throws AMQStoreException { if (_log.isDebugEnabled()) @@ -1446,8 +1447,7 @@ public class BDBMessageStore implements MessageStore } DatabaseEntry key = new DatabaseEntry(); - EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class); - keyBinding.objectToEntry(messageId, key); + LongBinding.longToEntry(messageId, key); DatabaseEntry value = new DatabaseEntry(); TupleBinding messageBinding = _metaDataTupleBindingFactory.getInstance(); @@ -1475,7 +1475,7 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. */ - public StorableMessageMetaData getMessageMetaData(Long messageId) throws AMQStoreException + public StorableMessageMetaData getMessageMetaData(long messageId) throws AMQStoreException { if (_log.isDebugEnabled()) { @@ -1484,8 +1484,7 @@ public class BDBMessageStore implements MessageStore } DatabaseEntry key = new DatabaseEntry(); - EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class); - keyBinding.objectToEntry(messageId, key); + LongBinding.longToEntry(messageId, key); DatabaseEntry value = new DatabaseEntry(); TupleBinding messageBinding = _metaDataTupleBindingFactory.getInstance(); @@ -1519,7 +1518,7 @@ public class BDBMessageStore implements MessageStore * * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. */ - public int getContent(Long messageId, int offset, ByteBuffer dst) throws AMQStoreException + public int getContent(long messageId, int offset, ByteBuffer dst) throws AMQStoreException { DatabaseEntry contentKeyEntry = new DatabaseEntry(); @@ -1778,7 +1777,6 @@ public class BDBMessageStore implements MessageStore { _log.debug("public synchronized void complete(): called (Transaction = " + _tx + ")"); } - _complete = true; notifyAll(); @@ -1799,7 +1797,7 @@ public class BDBMessageStore implements MessageStore { //_log.debug("public void commit(): called"); - _commitThread.addJob(this); + _commitThread.addJob(this, _syncCommit); if(!_syncCommit) { @@ -1807,28 +1805,14 @@ public class BDBMessageStore implements MessageStore return; } - synchronized (BDBCommitFuture.this) - { - while (!_complete) - { - try - { - wait(250); - } - catch (InterruptedException e) - { - // _log.error("Unexpected thread interruption: " + e, e); - throw new RuntimeException(e); - } - } + waitForCompletion(); + // _log.debug("Commit completed, _databaseException = " + _databaseException); - // _log.debug("Commit completed, _databaseException = " + _databaseException); - - if (_databaseException != null) - { - throw _databaseException; - } + if (_databaseException != null) + { + throw _databaseException; } + } public synchronized boolean isComplete() @@ -1836,10 +1820,11 @@ public class BDBMessageStore implements MessageStore return _complete; } - public void waitForCompletion() + public synchronized void waitForCompletion() { while (!isComplete()) { + _commitThread.explicitNotify(); try { wait(250); @@ -1866,7 +1851,7 @@ public class BDBMessageStore implements MessageStore // private final Logger _log = Logger.getLogger(CommitThread.class); private final AtomicBoolean _stopped = new AtomicBoolean(false); - private final AtomicReference<Queue<BDBCommitFuture>> _jobQueue = new AtomicReference<Queue<BDBCommitFuture>>(new ConcurrentLinkedQueue<BDBCommitFuture>()); + private final Queue<BDBCommitFuture> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFuture>(); private final CheckpointConfig _config = new CheckpointConfig(); private final Object _lock = new Object(); @@ -1877,6 +1862,14 @@ public class BDBMessageStore implements MessageStore } + public void explicitNotify() + { + synchronized (_lock) + { + _lock.notify(); + } + } + public void run() { while (!_stopped.get()) @@ -1905,24 +1898,25 @@ public class BDBMessageStore implements MessageStore { // _log.debug("private void processJobs(): called"); - // we replace the old queue atomically with a new one and this avoids any need to - // copy elements out of the queue - Queue<BDBCommitFuture> jobs = _jobQueue.getAndSet(new ConcurrentLinkedQueue<BDBCommitFuture>()); + int size = _jobQueue.size(); try { - // _environment.checkpoint(_config); + //TODO - upgrade to BDB 5.0, then use: _environment.flushLog(true); _environment.sync(); - for (BDBCommitFuture commit : jobs) + for(int i = 0; i < size; i++) { + BDBCommitFuture commit = _jobQueue.poll(); commit.complete(); } + } catch (DatabaseException e) { - for (BDBCommitFuture commit : jobs) + for(int i = 0; i < size; i++) { + BDBCommitFuture commit = _jobQueue.poll(); commit.abort(e); } } @@ -1931,15 +1925,19 @@ public class BDBMessageStore implements MessageStore private boolean hasJobs() { - return !_jobQueue.get().isEmpty(); + return !_jobQueue.isEmpty(); } - public void addJob(BDBCommitFuture commit) + public void addJob(BDBCommitFuture commit, final boolean sync) { - synchronized (_lock) + + _jobQueue.add(commit); + if(sync) { - _jobQueue.get().add(commit); - _lock.notifyAll(); + synchronized (_lock) + { + _lock.notifyAll(); + } } } @@ -1959,7 +1957,10 @@ public class BDBMessageStore implements MessageStore private final long _messageId; private volatile SoftReference<StorableMessageMetaData> _metaDataRef; - private com.sleepycat.je.Transaction _txn; + + private StorableMessageMetaData _metaData; + private volatile SoftReference<byte[]> _dataRef; + private byte[] _data; StoredBDBMessage(long messageId, StorableMessageMetaData metaData) { @@ -1973,22 +1974,15 @@ public class BDBMessageStore implements MessageStore try { _messageId = messageId; + _metaData = metaData; _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); - if(persist) - { - _txn = _environment.beginTransaction(null, null); - storeMetaData(_txn, messageId, metaData); - } + } catch (DatabaseException e) { throw new RuntimeException(e); } - catch (AMQStoreException e) - { - throw new RuntimeException(e); - } } @@ -2018,58 +2012,114 @@ public class BDBMessageStore implements MessageStore public void addContent(int offsetInMessage, java.nio.ByteBuffer src) { - try + src = src.slice(); + + if(_data == null) { - BDBMessageStore.this.addContent(_txn, _messageId, offsetInMessage, src); + _data = new byte[src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + src.duplicate().get(_data); } - catch (AMQStoreException e) + else { - throw new RuntimeException(e); + byte[] oldData = _data; + _data = new byte[oldData.length + src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + + System.arraycopy(oldData,0,_data,0,oldData.length); + src.duplicate().get(_data, oldData.length, src.remaining()); } + } public int getContent(int offsetInMessage, java.nio.ByteBuffer dst) { - try + byte[] data = _dataRef == null ? null : _dataRef.get(); + if(data != null) { - return BDBMessageStore.this.getContent(_messageId, offsetInMessage, dst); + int length = Math.min(dst.remaining(), data.length - offsetInMessage); + dst.put(data, offsetInMessage, length); + return length; } - catch (AMQStoreException e) + else { - throw new RuntimeException(e); + try + { + return BDBMessageStore.this.getContent(_messageId, offsetInMessage, dst); + } + catch (AMQStoreException e) + { + throw new RuntimeException(e); + } } } - public StoreFuture flushToStore() + public ByteBuffer getContent(int offsetInMessage, int size) { - try + byte[] data = _dataRef == null ? null : _dataRef.get(); + if(data != null) { - if(_txn != null) - { - //if(_log.isDebugEnabled()) - //{ - // _log.debug("Flushing message " + _messageId + " to store"); - //} - BDBMessageStore.this.commitTranImpl(_txn, true); - } + return ByteBuffer.wrap(data,offsetInMessage,size); } - catch (AMQStoreException e) + else { - throw new RuntimeException(e); + ByteBuffer buf = ByteBuffer.allocate(size); + getContent(offsetInMessage, buf); + buf.position(0); + return buf; } - finally + } + + synchronized void store(com.sleepycat.je.Transaction txn) + { + + if(_metaData != null) { - _txn = null; + try + { + _dataRef = new SoftReference<byte[]>(_data); + BDBMessageStore.this.storeMetaData(txn, _messageId, _metaData); + BDBMessageStore.this.addContent(txn, _messageId, 0, + _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data)); + } + catch(DatabaseException e) + { + throw new RuntimeException(e); + } + catch (AMQStoreException e) + { + throw new RuntimeException(e); + } + catch (RuntimeException e) + { + e.printStackTrace(); + throw e; + } + finally + { + _metaData = null; + _data = null; + } + } + } + + public synchronized StoreFuture flushToStore() + { + if(_metaData != null) + { + com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); + store(txn); + BDBMessageStore.this.commit(txn,true); + } return IMMEDIATE_FUTURE; } public void remove() { - flushToStore(); try { - BDBMessageStore.this.removeMessage(_messageId); + BDBMessageStore.this.removeMessage(_messageId, false); } catch (AMQStoreException e) { @@ -2094,12 +2144,27 @@ public class BDBMessageStore implements MessageStore } } - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException + { + if(message.getStoredMessage() instanceof StoredBDBMessage) + { + ((StoredBDBMessage)message.getStoredMessage()).store(_txn); + } + + BDBMessageStore.this.enqueueMessage(_txn, queue, message.getMessageNumber()); + } + + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException + { + BDBMessageStore.this.dequeueMessage(_txn, queue, message.getMessageNumber()); + } + + public void enqueueMessage(TransactionLogResource queue, long messageId) throws AMQStoreException { BDBMessageStore.this.enqueueMessage(_txn, queue, messageId); } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, long messageId) throws AMQStoreException { BDBMessageStore.this.dequeueMessage(_txn, queue, messageId); diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java index 975e558874..68f1e7ce6f 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java @@ -33,7 +33,7 @@ public class QueueEntryTB extends TupleBinding<QueueEntryKey> public QueueEntryKey entryToObject(TupleInput tupleInput) { AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput); - Long messageId = tupleInput.readLong(); + long messageId = tupleInput.readLong(); return new QueueEntryKey(queueName, messageId); } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java index ef31b78cfe..6c890daaca 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java @@ -32,13 +32,11 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageMetaData_0_10; +import org.apache.qpid.server.message.*; import org.apache.qpid.server.store.MessageMetaDataType; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.store.TransactionLog; import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.transport.DeliveryProperties; import org.apache.qpid.transport.Header; @@ -100,7 +98,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto */ MessageProperties msgProps_0_10 = createMessageProperties_0_10(bodySize); DeliveryProperties delProps_0_10 = createDeliveryProperties_0_10(); - Header header_0_10 = new Header(msgProps_0_10, delProps_0_10); + Header header_0_10 = new Header(delProps_0_10, msgProps_0_10); MessageTransfer xfr_0_10 = new MessageTransfer("destination", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED, header_0_10, completeContentBody_0_10); @@ -162,7 +160,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto assertEquals("Message arrival time has changed", origArrivalTime_0_10, returnedMMD_0_10.getArrivalTime()); - DeliveryProperties returnedDelProps_0_10 = returnedMMD_0_10.getHeader().get(DeliveryProperties.class); + DeliveryProperties returnedDelProps_0_10 = returnedMMD_0_10.getHeader().getDeliveryProperties(); assertNotNull("DeliveryProperties were not returned", returnedDelProps_0_10); assertEquals("Immediate flag has changed", delProps_0_10.getImmediate(), returnedDelProps_0_10.getImmediate()); assertEquals("Routing key has changed", delProps_0_10.getRoutingKey(), returnedDelProps_0_10.getRoutingKey()); @@ -170,7 +168,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto assertEquals("Message expiration has changed", delProps_0_10.getExpiration(), returnedDelProps_0_10.getExpiration()); assertEquals("Message delivery priority has changed", delProps_0_10.getPriority(), returnedDelProps_0_10.getPriority()); - MessageProperties returnedMsgProps = returnedMMD_0_10.getHeader().get(MessageProperties.class); + MessageProperties returnedMsgProps = returnedMMD_0_10.getHeader().getMessageProperties(); assertNotNull("MessageProperties were not returned", returnedMsgProps); assertTrue("Message correlationID has changed", Arrays.equals(msgProps_0_10.getCorrelationId(), returnedMsgProps.getCorrelationId())); assertEquals("Message content length has changed", msgProps_0_10.getContentLength(), returnedMsgProps.getContentLength()); @@ -352,7 +350,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto */ public void testTranCommit() throws Exception { - TransactionLog log = getVirtualHost().getTransactionLog(); + MessageStore log = getVirtualHost().getMessageStore(); BDBMessageStore bdbStore = assertBDBStore(log); @@ -366,10 +364,10 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto } }; - TransactionLog.Transaction txn = log.newTransaction(); + MessageStore.Transaction txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 1L); - txn.enqueueMessage(mockQueue, 5L); + txn.enqueueMessage(mockQueue, new MockMessage(1L)); + txn.enqueueMessage(mockQueue, new MockMessage(5L)); txn.commitTran(); List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName); @@ -390,7 +388,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto */ public void testTranRollbackBeforeCommit() throws Exception { - TransactionLog log = getVirtualHost().getTransactionLog(); + MessageStore log = getVirtualHost().getMessageStore(); BDBMessageStore bdbStore = assertBDBStore(log); @@ -404,14 +402,14 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto } }; - TransactionLog.Transaction txn = log.newTransaction(); + MessageStore.Transaction txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 21L); + txn.enqueueMessage(mockQueue, new MockMessage(21L)); txn.abortTran(); txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 22L); - txn.enqueueMessage(mockQueue, 23L); + txn.enqueueMessage(mockQueue, new MockMessage(22L)); + txn.enqueueMessage(mockQueue, new MockMessage(23L)); txn.commitTran(); List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName); @@ -431,7 +429,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto */ public void testTranRollbackAfterCommit() throws Exception { - TransactionLog log = getVirtualHost().getTransactionLog(); + MessageStore log = getVirtualHost().getMessageStore(); BDBMessageStore bdbStore = assertBDBStore(log); @@ -445,17 +443,17 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto } }; - TransactionLog.Transaction txn = log.newTransaction(); + MessageStore.Transaction txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 30L); + txn.enqueueMessage(mockQueue, new MockMessage(30L)); txn.commitTran(); txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 31L); + txn.enqueueMessage(mockQueue, new MockMessage(31L)); txn.abortTran(); txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, 32L); + txn.enqueueMessage(mockQueue, new MockMessage(32L)); txn.commitTran(); List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName); @@ -467,4 +465,73 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto assertEquals("Second Message is incorrect", 32L, val.longValue()); } + private static class MockMessage implements ServerMessage, EnqueableMessage + { + private long _messageId; + + public MockMessage(long messageId) + { + _messageId = messageId; + } + + public String getRoutingKey() + { + return null; + } + + public AMQMessageHeader getMessageHeader() + { + return null; + } + + public StoredMessage getStoredMessage() + { + return null; + } + + public boolean isPersistent() + { + return true; + } + + public long getSize() + { + return 0; + } + + public boolean isImmediate() + { + return false; + } + + public long getExpiration() + { + return 0; + } + + public MessageReference newReference() + { + return null; + } + + public long getMessageNumber() + { + return _messageId; + } + + public long getArrivalTime() + { + return 0; + } + + public int getContent(ByteBuffer buf, int offset) + { + return 0; + } + + public ByteBuffer getContent(int offset, int length) + { + return null; + } + } } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java index 8e55e79e01..6d7cca59cf 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java @@ -52,7 +52,9 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_4; import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTupleBindingFactory; @@ -415,7 +417,7 @@ public class BDBUpgradeTest extends QpidBrokerTestCase ContentHeaderBody contentHeaderBody = new ContentHeaderBody(classForBasic, 1, props, bodySize); // add content entry to database - long messageId = store.getNewMessageId(); + final long messageId = store.getNewMessageId(); TupleBinding<MessageContentKey> contentKeyTB = new MessageContentKeyTupleBindingFactory(storeVersion).getInstance(); MessageContentKey contentKey = null; if (storeVersion == VERSION_4) @@ -451,9 +453,29 @@ public class BDBUpgradeTest extends QpidBrokerTestCase return queueName.asString(); } }; - TransactionLog log = (TransactionLog) store; - TransactionLog.Transaction txn = log.newTransaction(); - txn.enqueueMessage(mockQueue, messageId); + + EnqueableMessage mockMessage = new EnqueableMessage() + { + + public long getMessageNumber() + { + return messageId; + } + + public boolean isPersistent() + { + return true; + } + + public StoredMessage getStoredMessage() + { + return null; + } + }; + + MessageStore log = (MessageStore) store; + MessageStore.Transaction txn = log.newTransaction(); + txn.enqueueMessage(mockQueue, mockMessage); txn.commitTran(); } finally diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java index 593c1616fb..b898e85aa2 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java @@ -111,6 +111,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener } + public void enqueue(ServerMessage message, boolean sync, PostEnqueueAction action) throws AMQException + { + enqueue(message); + } + public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException { enqueue(message); diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java index b98daf7cb1..9ee8b923fc 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java @@ -32,6 +32,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.management.common.mbeans.ManagedConnection; import java.util.ArrayList; +import java.util.List; public class QMFBrokerRequestCommand extends QMFCommand { @@ -57,7 +58,7 @@ public class QMFBrokerRequestCommand extends QMFCommand QMFMessage responseMessage = new QMFMessage(queueName, cmd); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java index 26a27cfa19..5d2717a9fb 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java @@ -31,6 +31,7 @@ import org.apache.qpid.AMQException; import java.util.ArrayList; import java.util.Collection; +import java.util.List; public class QMFClassQueryCommand extends QMFCommand { @@ -71,7 +72,7 @@ public class QMFClassQueryCommand extends QMFCommand Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) { diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java index 8e8cb55a0d..ff927a1de9 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java @@ -163,7 +163,7 @@ public class QMFGetQueryCommand extends QMFCommand Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) { diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java index 895ff643a2..8208525b08 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java @@ -21,8 +21,11 @@ package org.apache.qpid.qmf; +import org.apache.commons.lang.NotImplementedException; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.configuration.SessionConfig; import org.apache.qpid.server.message.*; +import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.transport.codec.BBEncoder; import java.nio.ByteBuffer; @@ -59,11 +62,21 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead return _routingKey; } + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(_routingKey); + } + public AMQMessageHeader getMessageHeader() { return this; } + public StoredMessage getStoredMessage() + { + throw new NotImplementedException(); + } + public boolean isPersistent() { return false; @@ -159,9 +172,9 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead return new QMFMessageReference(this); } - public Long getMessageNumber() + public long getMessageNumber() { - return null; + return 0l; } public long getArrivalTime() @@ -172,9 +185,9 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead public int getContent(ByteBuffer buf, int offset) { ByteBuffer src = _content.duplicate(); - _content.position(offset); - _content = _content.slice(); - int len = _content.remaining(); + src.position(offset); + src = src.slice(); + int len = src.remaining(); if(len > buf.remaining()) { len = buf.remaining(); @@ -185,6 +198,16 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead return len; } + + public ByteBuffer getContent(int offset, int size) + { + ByteBuffer src = _content.duplicate(); + src.position(offset); + src = src.slice(); + src.limit(size); + return src; + } + private static class QMFMessageReference extends MessageReference<QMFMessage> { public QMFMessageReference(QMFMessage message) diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java index cf27e4b970..37c16efec5 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java @@ -27,6 +27,7 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.AMQException; +import java.util.List; import java.util.UUID; import java.util.ArrayList; @@ -68,7 +69,7 @@ public class QMFMethodRequestCommand extends QMFCommand QMFMessage responseMessage = new QMFMessage(queueName, cmd); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java index 6defd088de..ed07457a23 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java @@ -31,6 +31,7 @@ import org.apache.qpid.AMQException; import java.util.ArrayList; import java.util.Collection; +import java.util.List; public class QMFPackageQueryCommand extends QMFCommand { @@ -67,7 +68,7 @@ public class QMFPackageQueryCommand extends QMFCommand Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java index 3141676f10..850ffa8610 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java @@ -31,6 +31,7 @@ import org.apache.qpid.AMQException; import java.util.Collection; import java.util.ArrayList; +import java.util.List; public class QMFSchemaRequestCommand extends QMFCommand { @@ -70,7 +71,7 @@ public class QMFSchemaRequestCommand extends QMFCommand QMFMessage responseMessage = new QMFMessage(routingKey, cmd); - ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + List<? extends BaseQueue> queues = exchange.route(responseMessage); for(BaseQueue q : queues) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index a4fd997568..82ac01cea8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -95,7 +95,7 @@ import java.util.concurrent.atomic.AtomicLong; public class AMQChannel implements SessionConfig, AMQSessionModel { - public static final int DEFAULT_PREFETCH = 5000; + public static final int DEFAULT_PREFETCH = 4096; private static final Logger _logger = Logger.getLogger(AMQChannel.class); @@ -166,6 +166,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel private final UUID _id; private long _createTime = System.currentTimeMillis(); + private final ClientDeliveryMethod _clientDeliveryMethod; + public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) throws AMQException { @@ -183,6 +185,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel // by default the session is non-transactional _transaction = new AutoCommitTransaction(_messageStore); + + _clientDeliveryMethod = session.createDeliveryMethod(_channelId); } public ConfigStore getConfigStore() @@ -205,6 +209,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel return !(_transaction instanceof AutoCommitTransaction); } + public void receivedComplete() + { + } + + public boolean inTransaction() { return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0; @@ -284,7 +293,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel _currentMessage.setExpiration(); - MessageMetaData mmd = _currentMessage.headersReceived(); + MessageMetaData mmd = _currentMessage.headersReceived(getProtocolSession().getLastReceivedTime()); final StoredMessage<MessageMetaData> handle = _messageStore.addMessage(mmd); _currentMessage.setStoredMessage(handle); @@ -316,8 +325,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel { try { - _currentMessage.getStoredMessage().flushToStore(); - final ArrayList<? extends BaseQueue> destinationQueues = _currentMessage.getDestinationQueues(); + final List<? extends BaseQueue> destinationQueues = _currentMessage.getDestinationQueues(); if(!checkMessageUserId(_currentMessage.getContentHeader())) { @@ -339,11 +347,13 @@ public class AMQChannel implements SessionConfig, AMQSessionModel } else { - _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues, isTransactional())); + _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues), getProtocolSession().getLastReceivedTime()); incrementOutstandingTxnsIfNecessary(); updateTransactionalActivity(); } } + _currentMessage.getStoredMessage().flushToStore(); + } finally { @@ -857,10 +867,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple) { - Map<Long, QueueEntry> ackedMessageMap = new LinkedHashMap<Long,QueueEntry>(); - _unacknowledgedMessageMap.collect(deliveryTag, multiple, ackedMessageMap); - _unacknowledgedMessageMap.remove(ackedMessageMap); - return ackedMessageMap.values(); + return _unacknowledgedMessageMap.acknowledge(deliveryTag, multiple); + } /** @@ -949,12 +957,17 @@ public class AMQChannel implements SessionConfig, AMQSessionModel public void commit() throws AMQException { + commit(null); + } + public void commit(Runnable immediateAction) throws AMQException + { + if (!isTransactional()) { throw new AMQException("Fatal error: commit called on non-transactional channel"); } - _transaction.commit(); + _transaction.commit(immediateAction); _txnCommits.incrementAndGet(); _txnStarts.incrementAndGet(); @@ -1033,7 +1046,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel { if (isTransactional()) { - _txnUpdateTime.set(System.currentTimeMillis()); + _txnUpdateTime.set(getProtocolSession().getLastReceivedTime()); } } @@ -1079,20 +1092,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel return _messageStore; } - private final ClientDeliveryMethod _clientDeliveryMethod = new ClientDeliveryMethod() - { - - public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) - throws AMQException - { - _session.registerMessageDelivered(entry.getMessage().getSize()); - getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(), - deliveryTag, sub.getConsumerTag()); - entry.incrementDeliveryCount(); - } - - }; - public ClientDeliveryMethod getClientDeliveryMethod() { return _clientDeliveryMethod; @@ -1158,11 +1157,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel private class MessageDeliveryAction implements ServerTransaction.Action { private IncomingMessage _incommingMessage; - private ArrayList<? extends BaseQueue> _destinationQueues; + private List<? extends BaseQueue> _destinationQueues; public MessageDeliveryAction(IncomingMessage currentMessage, - ArrayList<? extends BaseQueue> destinationQueues, - boolean transactional) + List<? extends BaseQueue> destinationQueues) { _incommingMessage = currentMessage; _destinationQueues = destinationQueues; @@ -1177,8 +1175,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel final AMQMessage amqMessage = createAMQMessage(_incommingMessage); MessageReference ref = amqMessage.newReference(); - for(final BaseQueue queue : _destinationQueues) + for(int i = 0; i < _destinationQueues.size(); i++) { + BaseQueue queue = _destinationQueues.get(i); + BaseQueue.PostEnqueueAction action; if(immediate) @@ -1190,7 +1190,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel action = null; } - queue.enqueue(amqMessage, action); + queue.enqueue(amqMessage, isTransactional(), action); if(queue instanceof AMQQueue) { @@ -1198,6 +1198,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel } } + + _incommingMessage.getStoredMessage().flushToStore(); ref.release(); } catch (AMQException e) @@ -1539,7 +1541,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel final InboundMessage m = new InboundMessageAdapter(rejectedQueueEntry); - final ArrayList<? extends BaseQueue> destinationQueues = altExchange.route(m); + final List<? extends BaseQueue> destinationQueues = altExchange.route(m); if (destinationQueues == null || destinationQueues.isEmpty()) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java b/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java index 9da02e0600..9765636c25 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java @@ -22,8 +22,8 @@ package org.apache.qpid.server; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.store.TransactionLog; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.AMQException; @@ -39,13 +39,13 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor private final Map<Long, QueueEntry> _msgToResend; private final boolean _requeueIfUnabletoResend; private final UnacknowledgedMessageMap _unacknowledgedMessageMap; - private final TransactionLog _transactionLog; + private final MessageStore _transactionLog; public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap, Map<Long, QueueEntry> msgToRequeue, Map<Long, QueueEntry> msgToResend, boolean requeueIfUnabletoResend, - TransactionLog txnLog) + MessageStore txnLog) { _unacknowledgedMessageMap = unacknowledgedMessageMap; _msgToRequeue = msgToRequeue; diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java index 3bad73d86d..f4b4932744 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java +++ b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java @@ -46,10 +46,6 @@ public interface UnacknowledgedMessageMap void add(long deliveryTag, QueueEntry message); - void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs); - - void remove(Map<Long,QueueEntry> msgs); - QueueEntry remove(long deliveryTag); Collection<QueueEntry> cancelAllMessages(); @@ -67,6 +63,8 @@ public interface UnacknowledgedMessageMap */ Set<Long> getDeliveryTags(); + Collection<QueueEntry> acknowledge(long deliveryTag, boolean multiple); + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java index d920d97c1a..6a5d863526 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java @@ -157,6 +157,14 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap } } + public Collection<QueueEntry> acknowledge(long deliveryTag, boolean multiple) + { + Map<Long, QueueEntry> ackedMessageMap = new LinkedHashMap<Long,QueueEntry>(); + collect(deliveryTag, multiple, ackedMessageMap); + remove(ackedMessageMap); + return ackedMessageMap.values(); + } + private void collect(long key, Map<Long, QueueEntry> msgs) { synchronized (_lock) diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java index 60c9a86b76..48f85d9bc9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java @@ -115,4 +115,9 @@ public class Binding return result; } + public String toString() + { + return "Binding{bindingKey="+_bindingKey+", exchange="+_exchange+", queue="+_queue+"}"; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index d693c6962b..5ff90b3499 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -351,11 +351,11 @@ public abstract class AbstractExchange implements Exchange, Managable - public final ArrayList<? extends BaseQueue> route(final InboundMessage message) + public final List<? extends BaseQueue> route(final InboundMessage message) { _receivedMessageCount.incrementAndGet(); _receivedMessageSize.addAndGet(message.getSize()); - final ArrayList<? extends BaseQueue> queues = doRoute(message); + final List<? extends BaseQueue> queues = doRoute(message); if(!queues.isEmpty()) { _routedMessageCount.incrementAndGet(); @@ -364,7 +364,7 @@ public abstract class AbstractExchange implements Exchange, Managable return queues; } - protected abstract ArrayList<? extends BaseQueue> doRoute(final InboundMessage message); + protected abstract List<? extends BaseQueue> doRoute(final InboundMessage message); public long getMsgReceives() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index cb0d8ecf8f..8c0a5001db 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -34,6 +34,8 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import javax.management.JMException; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; @@ -41,8 +43,52 @@ public class DirectExchange extends AbstractExchange { private static final Logger _logger = Logger.getLogger(DirectExchange.class); - private final ConcurrentHashMap<String, CopyOnWriteArraySet<Binding>> _bindingsByKey = - new ConcurrentHashMap<String, CopyOnWriteArraySet<Binding>>(); + private static final class BindingSet + { + private CopyOnWriteArraySet<Binding> _bindings = new CopyOnWriteArraySet<Binding>(); + private List<BaseQueue> _queues = new ArrayList<BaseQueue>(); + + public synchronized void addBinding(Binding binding) + { + _bindings.add(binding); + recalculateQueues(); + } + + + public synchronized void removeBinding(Binding binding) + { + _bindings.remove(binding); + recalculateQueues(); + } + + private void recalculateQueues() + { + List<BaseQueue> queues = new ArrayList<BaseQueue>(_bindings.size()); + + for(Binding b : _bindings) + { + if(!queues.contains(b.getQueue())) + { + queues.add(b.getQueue()); + } + } + _queues = queues; + } + + + public List<BaseQueue> getQueues() + { + return _queues; + } + + public CopyOnWriteArraySet<Binding> getBindings() + { + return _bindings; + } + } + + private final ConcurrentHashMap<String, BindingSet> _bindingsByKey = + new ConcurrentHashMap<String, BindingSet>(); public static final ExchangeType<DirectExchange> TYPE = new ExchangeType<DirectExchange>() { @@ -91,33 +137,20 @@ public class DirectExchange extends AbstractExchange } - public ArrayList<? extends BaseQueue> doRoute(InboundMessage payload) + public List<? extends BaseQueue> doRoute(InboundMessage payload) { final String routingKey = payload.getRoutingKey(); - CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(routingKey == null ? "" : routingKey); + BindingSet bindings = _bindingsByKey.get(routingKey == null ? "" : routingKey); if(bindings != null) { - final ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(bindings.size()); - - for(Binding binding : bindings) - { - queues.add(binding.getQueue()); - binding.incrementMatches(); - } - - if (_logger.isDebugEnabled()) - { - _logger.debug("Publishing message to queue " + queues); - } - - return queues; + return bindings.getQueues(); } else { - return new ArrayList<BaseQueue>(0); + return Collections.emptyList(); } @@ -132,16 +165,10 @@ public class DirectExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey, AMQQueue queue) { String bindingKey = (routingKey == null) ? "" : routingKey.toString(); - CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); + BindingSet bindings = _bindingsByKey.get(bindingKey); if(bindings != null) { - for(Binding binding : bindings) - { - if(binding.getQueue().equals(queue)) - { - return true; - } - } + return bindings.getQueues().contains(queue); } return false; @@ -150,22 +177,20 @@ public class DirectExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey) { String bindingKey = (routingKey == null) ? "" : routingKey.toString(); - CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); - return bindings != null && !bindings.isEmpty(); + BindingSet bindings = _bindingsByKey.get(bindingKey); + return bindings != null && !bindings.getQueues().isEmpty(); } public boolean isBound(AMQQueue queue) { - for (CopyOnWriteArraySet<Binding> bindings : _bindingsByKey.values()) + for (BindingSet bindings : _bindingsByKey.values()) { - for(Binding binding : bindings) + if(bindings.getQueues().contains(queue)) { - if(binding.getQueue().equals(queue)) - { - return true; - } + return true; } + } return false; } @@ -184,19 +209,19 @@ public class DirectExchange extends AbstractExchange assert queue != null; assert routingKey != null; - CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); + BindingSet bindings = _bindingsByKey.get(bindingKey); if(bindings == null) { - bindings = new CopyOnWriteArraySet<Binding>(); - CopyOnWriteArraySet<Binding> newBindings; + bindings = new BindingSet(); + BindingSet newBindings; if((newBindings = _bindingsByKey.putIfAbsent(bindingKey, bindings)) != null) { bindings = newBindings; } } - bindings.add(binding); + bindings.addBinding(binding); } @@ -204,10 +229,10 @@ public class DirectExchange extends AbstractExchange { assert binding != null; - CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(binding.getBindingKey()); + BindingSet bindings = _bindingsByKey.get(binding.getBindingKey()); if(bindings != null) { - bindings.remove(binding); + bindings.removeBinding(binding); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 29a3611709..29c354feae 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -36,6 +36,7 @@ import org.apache.qpid.server.configuration.ExchangeConfig; import javax.management.JMException; import java.util.ArrayList; import java.util.Collection; +import java.util.List; public interface Exchange extends ExchangeReferrer, ExchangeConfig { @@ -70,7 +71,7 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig * * @return list of queues to which to route the message. */ - ArrayList<? extends BaseQueue> route(InboundMessage message); + List<? extends BaseQueue> route(InboundMessage message); /** diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index e523eb24fb..3a8a86e654 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -37,8 +37,11 @@ import org.apache.qpid.server.filter.JMSSelectorFilter; import org.apache.qpid.server.message.InboundMessage; import javax.management.JMException; +import java.sql.Array; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + import java.lang.ref.WeakReference; public class TopicExchange extends AbstractExchange @@ -77,8 +80,6 @@ public class TopicExchange extends AbstractExchange private static final Logger _logger = Logger.getLogger(TopicExchange.class); - - private final TopicParser _parser = new TopicParser(); private final Map<AMQShortString, TopicExchangeResult> _topicExchangeResults = @@ -175,7 +176,6 @@ public class TopicExchange extends AbstractExchange _bindings.put(binding, args); } - } private JMSSelectorFilter createSelectorFilter(final FieldTable args) throws AMQInvalidArgumentException @@ -201,14 +201,23 @@ public class TopicExchange extends AbstractExchange public ArrayList<BaseQueue> doRoute(InboundMessage payload) { - final AMQShortString routingKey = payload.getRoutingKey() == null + final AMQShortString routingKey = payload.getRoutingKeyShortString() == null ? AMQShortString.EMPTY_STRING - : new AMQShortString(payload.getRoutingKey()); + : payload.getRoutingKeyShortString(); + + final Collection<AMQQueue> matchedQueues = getMatchedQueues(payload, routingKey); - // The copy here is unfortunate, but not too bad relevant to the amount of - // things created and copied in getMatchedQueues - ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(); - queues.addAll(getMatchedQueues(payload, routingKey)); + ArrayList<BaseQueue> queues; + + if(matchedQueues.getClass() == ArrayList.class) + { + queues = (ArrayList) matchedQueues; + } + else + { + queues = new ArrayList<BaseQueue>(); + queues.addAll(matchedQueues); + } if(queues == null || queues.isEmpty()) { @@ -325,25 +334,28 @@ public class TopicExchange extends AbstractExchange { Collection<TopicMatcherResult> results = _parser.parse(routingKey); - if(results.isEmpty()) + switch(results.size()) { - return Collections.EMPTY_SET; - } - else - { - Collection<AMQQueue> queues = results.size() == 1 ? null : new HashSet<AMQQueue>(); - for(TopicMatcherResult result : results) - { - TopicExchangeResult res = (TopicExchangeResult)result; - - for(Binding b : res.getBindings()) + case 0: + return Collections.EMPTY_SET; + case 1: + TopicMatcherResult[] resultQueues = new TopicMatcherResult[1]; + results.toArray(resultQueues); + return ((TopicExchangeResult)resultQueues[0]).processMessage(message, null); + default: + Collection<AMQQueue> queues = new HashSet<AMQQueue>(); + for(TopicMatcherResult result : results) { - b.incrementMatches(); + TopicExchangeResult res = (TopicExchangeResult)result; + + for(Binding b : res.getBindings()) + { + b.incrementMatches(); + } + + queues = res.processMessage(message, queues); } - - queues = res.processMessage(message, queues); - } - return queues; + return queues; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java index 41dc0d749a..d8b09a7841 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java @@ -39,6 +39,7 @@ public final class TopicExchangeResult implements TopicMatcherResult private final List<Binding> _bindings = new CopyOnWriteArrayList<Binding>(); private final Map<AMQQueue, Integer> _unfilteredQueues = new ConcurrentHashMap<AMQQueue, Integer>(); private final ConcurrentHashMap<AMQQueue, Map<MessageFilter,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter, Integer>>(); + private volatile ArrayList<AMQQueue> _unfilteredQueueList = new ArrayList<AMQQueue>(0); public void addUnfilteredQueue(AMQQueue queue) { @@ -46,6 +47,9 @@ public final class TopicExchangeResult implements TopicMatcherResult if(instances == null) { _unfilteredQueues.put(queue, 1); + ArrayList<AMQQueue> newList = new ArrayList<AMQQueue>(_unfilteredQueueList); + newList.add(queue); + _unfilteredQueueList = newList; } else { @@ -59,6 +63,10 @@ public final class TopicExchangeResult implements TopicMatcherResult if(instances == 1) { _unfilteredQueues.remove(queue); + ArrayList<AMQQueue> newList = new ArrayList<AMQQueue>(_unfilteredQueueList); + newList.remove(queue); + _unfilteredQueueList = newList; + } else { @@ -166,7 +174,7 @@ public final class TopicExchangeResult implements TopicMatcherResult { if(_filteredQueues.isEmpty()) { - return new ArrayList<AMQQueue>(_unfilteredQueues.keySet()); + return _unfilteredQueueList; } else { diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java index 36076cf75b..4446536d4c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java @@ -77,7 +77,7 @@ public class TopicMatcherDFAState } if(nextState == null) { - return Collections.EMPTY_SET; + return Collections.EMPTY_LIST; } // Shortcut if we are at a looping terminal state if((nextState == this) && (_nextStateMap.size() == 1) && _nextStateMap.containsKey(TopicWord.ANY_WORD)) diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java index 2dff45c326..1c1527aa31 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java +++ b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java @@ -44,27 +44,9 @@ import org.apache.qpid.server.transport.ServerSession; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageCreditUnit; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.MessageReject; -import org.apache.qpid.transport.MessageRejectCode; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.RangeSet; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.SessionException; -import org.apache.qpid.transport.SessionListener; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import org.apache.qpid.transport.*; + +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -365,7 +347,8 @@ public class Bridge implements BridgeConfig // TODO - deal with exchange not existing DeliveryProperties delvProps = null; - if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration()) + if(xfr.getHeader() != null && (delvProps = xfr.getHeader().getDeliveryProperties()) != null && delvProps.hasTtl() && + !delvProps.hasExpiration()) { delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); } @@ -377,7 +360,7 @@ public class Bridge implements BridgeConfig storeMessage.flushToStore(); MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)_session).getReference()); - ArrayList<? extends BaseQueue> queues = exchange.route(message); + List<? extends BaseQueue> queues = exchange.route(message); @@ -391,7 +374,7 @@ public class Bridge implements BridgeConfig { if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) { - RangeSet rejects = new RangeSet(); + RangeSet rejects = RangeSetFactory.createRangeSet(); rejects.add(xfr.getId()); MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); ssn.invoke(reject); @@ -428,7 +411,7 @@ public class Bridge implements BridgeConfig } - private void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues) + private void enqueue(final ServerMessage message, final List<? extends BaseQueue> queues) { _transaction.enqueue(queues,message, new ServerTransaction.Action() { @@ -456,8 +439,7 @@ public class Bridge implements BridgeConfig { // NO-OP } - }); - + }, 0L); } public void exception(final Session session, final SessionException exception) diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java index cfe5aedd61..a77ed5700a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.flow; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.Set; import java.util.HashSet; @@ -27,13 +28,16 @@ import java.util.HashSet; public abstract class AbstractFlowCreditManager implements FlowCreditManager { protected final AtomicBoolean _suspended = new AtomicBoolean(false); - private final Set<FlowCreditManagerListener> _listeners = new HashSet<FlowCreditManagerListener>(); + private final ArrayList<FlowCreditManagerListener> _listeners = new ArrayList<FlowCreditManagerListener>(); public final void addStateListener(FlowCreditManagerListener listener) { synchronized(_listeners) { - _listeners.add(listener); + if(!_listeners.contains(listener)) + { + _listeners.add(listener); + } } } @@ -49,9 +53,10 @@ public abstract class AbstractFlowCreditManager implements FlowCreditManager { synchronized(_listeners) { - for(FlowCreditManagerListener listener : _listeners) + final int size = _listeners.size(); + for(int i = 0; i<size; i++) { - listener.creditStateChanged(!suspended); + _listeners.get(i).creditStateChanged(!suspended); } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java index 765dee2878..8875f21d0b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java @@ -52,7 +52,6 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); AMQChannel channel = protocolConnection.getChannel(channelId); - VirtualHost vHost = protocolConnection.getVirtualHost(); if (channel == null) diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java index 9133cce6b7..32aa99534b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java @@ -65,7 +65,6 @@ public class ChannelCloseHandler implements StateAwareMethodListener<ChannelClos { throw body.getConnectionException(AMQConstant.CHANNEL_ERROR, "Trying to close unknown channel"); } - session.closeChannel(channelId); // Client requested closure so we don't wait for ok we send it stateManager.getProtocolSession().closeChannelOk(channelId); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java index 696ca8a63b..5ccaa49de8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java @@ -55,7 +55,6 @@ public class ChannelFlowHandler implements StateAwareMethodListener<ChannelFlowB { throw body.getChannelNotFoundException(channelId); } - channel.setSuspended(!body.getActive()); _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive()); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java index f8e4eab0b6..6eaba87b79 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java @@ -49,7 +49,6 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co public void methodReceived(AMQStateManager stateManager, ConnectionCloseBody body, int channelId) throws AMQException { AMQProtocolSession session = stateManager.getProtocolSession(); - if (_logger.isInfoEnabled()) { _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" + diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java index ccd42204d9..21aea1510b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java @@ -65,7 +65,6 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo public void methodReceived(AMQStateManager stateManager, ExchangeBoundBody body, int channelId) throws AMQException { AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); MethodRegistry methodRegistry = session.getMethodRegistry(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java index 0cfed77f2e..693b316607 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java @@ -85,6 +85,13 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar //TODO: do we need to check that the queue already exists with exactly the same "configuration"? + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + synchronized (queueRegistry) { queue = queueRegistry.getQueue(queueName); @@ -183,12 +190,6 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar } - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } //set this as the default queue on the channel: channel.setDefaultQueue(queue); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java index da52268e52..902e3ade85 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java @@ -64,15 +64,17 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + AMQQueue queue; if (body.getQueue() == null) { - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } //get the default queue on the channel: queue = channel.getDefaultQueue(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java index 759eec0129..6c3e11be5b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java @@ -63,17 +63,14 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); AMQChannel channel = protocolConnection.getChannel(channelId); - - + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } AMQQueue queue; if(body.getQueue() == null) { - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - //get the default queue on the channel: queue = channel.getDefaultQueue(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java index f2119f7faa..3849c5af19 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java @@ -66,14 +66,15 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB final AMQQueue queue; final AMQShortString routingKey; - if (body.getQueue() == null) + + AMQChannel channel = session.getChannel(channelId); + if (channel == null) { - AMQChannel channel = session.getChannel(channelId); + throw body.getChannelNotFoundException(channelId); + } - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } + if (body.getQueue() == null) + { queue = channel.getDefaultQueue(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java index 32bf8aa17d..b284514186 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java @@ -37,7 +37,7 @@ import java.nio.ByteBuffer; /** * A deliverable message. */ -public class AMQMessage extends AbstractServerMessageImpl +public class AMQMessage extends AbstractServerMessageImpl<MessageMetaData> { /** Used for debugging purposes. */ private static final Logger _log = Logger.getLogger(AMQMessage.class); @@ -62,10 +62,6 @@ public class AMQMessage extends AbstractServerMessageImpl private Object _sessionIdentifier; private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER); - private final StoredMessage<MessageMetaData> _handle; - - WeakReference<AMQChannel> _channelRef; - public AMQMessage(StoredMessage<MessageMetaData> handle) { this(handle, null); @@ -75,7 +71,7 @@ public class AMQMessage extends AbstractServerMessageImpl { super(handle); - _handle = handle; + final MessageMetaData metaData = handle.getMetaData(); _size = metaData.getContentSize(); final MessagePublishInfo messagePublishInfo = metaData.getMessagePublishInfo(); @@ -84,8 +80,6 @@ public class AMQMessage extends AbstractServerMessageImpl { _flags |= IMMEDIATE; } - - _channelRef = channelRef; } public void setExpiration(final long expiration) @@ -97,7 +91,7 @@ public class AMQMessage extends AbstractServerMessageImpl public MessageMetaData getMessageMetaData() { - return _handle.getMetaData(); + return getStoredMessage().getMetaData(); } public ContentHeaderBody getContentHeaderBody() throws AMQException @@ -107,7 +101,7 @@ public class AMQMessage extends AbstractServerMessageImpl public Long getMessageId() { - return _handle.getMessageNumber(); + return getStoredMessage().getMessageNumber(); } /** @@ -219,9 +213,9 @@ public class AMQMessage extends AbstractServerMessageImpl return new AMQMessageReference(this); } - public Long getMessageNumber() + public long getMessageNumber() { - return getMessageId(); + return getStoredMessage().getMessageNumber(); } @@ -248,16 +242,13 @@ public class AMQMessage extends AbstractServerMessageImpl public int getContent(ByteBuffer buf, int offset) { - return _handle.getContent(offset, buf); + return getStoredMessage().getContent(offset, buf); } - public StoredMessage<MessageMetaData> getStoredMessage() + + public ByteBuffer getContent(int offset, int size) { - return _handle; + return getStoredMessage().getContent(offset, size); } - public SessionConfig getSessionConfig() - { - return _channelRef == null ? null : ((SessionConfig) _channelRef.get()); - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/AbstractServerMessageImpl.java b/java/broker/src/main/java/org/apache/qpid/server/message/AbstractServerMessageImpl.java index 80c28332c0..b1d43f0b50 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/AbstractServerMessageImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/AbstractServerMessageImpl.java @@ -21,19 +21,30 @@ package org.apache.qpid.server.message; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.store.StoredMessage; -public abstract class AbstractServerMessageImpl implements ServerMessage +public abstract class AbstractServerMessageImpl<T extends StorableMessageMetaData> implements ServerMessage<T> { - private final AtomicInteger _referenceCount = new AtomicInteger(0); - private final StoredMessage<?> _handle; - public AbstractServerMessageImpl(StoredMessage<?> handle) + private static final AtomicIntegerFieldUpdater<AbstractServerMessageImpl> _refCountUpdater = + AtomicIntegerFieldUpdater.newUpdater(AbstractServerMessageImpl.class, "_referenceCount"); + + private volatile int _referenceCount = 0; + private final StoredMessage<T> _handle; + + public AbstractServerMessageImpl(StoredMessage<T> handle) { _handle = handle; } + public StoredMessage<T> getStoredMessage() + { + return _handle; + } + public boolean incrementReference() { return incrementReference(1); @@ -41,9 +52,9 @@ public abstract class AbstractServerMessageImpl implements ServerMessage public boolean incrementReference(int count) { - if(_referenceCount.addAndGet(count) <= 0) + if(_refCountUpdater.addAndGet(this, count) <= 0) { - _referenceCount.addAndGet(-count); + _refCountUpdater.addAndGet(this, -count); return false; } else @@ -62,7 +73,7 @@ public abstract class AbstractServerMessageImpl implements ServerMessage */ public void decrementReference() { - int count = _referenceCount.decrementAndGet(); + int count = _refCountUpdater.decrementAndGet(this); // note that the operation of decrementing the reference count and then removing the message does not // have to be atomic since the ref count starts at 1 and the exchange itself decrements that after @@ -73,7 +84,7 @@ public abstract class AbstractServerMessageImpl implements ServerMessage // set the reference count way below 0 so that we can detect that the message has been deleted // this is to guard against the message being spontaneously recreated (from the mgmt console) // by copying from other queues at the same time as it is being removed. - _referenceCount.set(Integer.MIN_VALUE/2); + _refCountUpdater.set(this,Integer.MIN_VALUE/2); // 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 @@ -99,6 +110,6 @@ public abstract class AbstractServerMessageImpl implements ServerMessage protected int getReferenceCount() { - return _referenceCount.get(); + return _referenceCount; } }
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java index c32f80fc5b..7be91ad0ca 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java @@ -20,8 +20,11 @@ */ package org.apache.qpid.server.message; +import org.apache.qpid.server.store.StoredMessage; + public interface EnqueableMessage { - Long getMessageNumber(); + long getMessageNumber(); boolean isPersistent(); + StoredMessage getStoredMessage(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java index 1b3fdb1870..79d5574a91 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java @@ -22,10 +22,12 @@ package org.apache.qpid.server.message; import org.apache.qpid.server.queue.Filterable; +import org.apache.qpid.framing.AMQShortString; public interface InboundMessage extends Filterable { String getRoutingKey(); + AMQShortString getRoutingKeyShortString(); AMQMessageHeader getMessageHeader(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java index 08a09c4a85..44741f57bd 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java @@ -26,6 +26,7 @@ import java.nio.ByteBuffer; public interface MessageContentSource { public int getContent(ByteBuffer buf, int offset); + public ByteBuffer getContent(int offset, int size); long getSize(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java index f9863f4945..17ebb6ee07 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java @@ -30,9 +30,12 @@ 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 org.apache.qpid.framing.AMQShortString; import java.nio.ByteBuffer; import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.List; public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMessage { @@ -42,7 +45,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes private MessageTransferHeader _messageHeader; private long _arrivalTime; private int _bodySize; - private volatile SoftReference<ByteBuffer> _body; private static final int ENCODER_SIZE = 1 << 10; @@ -53,21 +55,16 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes public MessageMetaData_0_10(MessageTransfer xfr) { - this(xfr.getHeader(), xfr.getBodySize(), xfr.getBody(), System.currentTimeMillis()); + this(xfr.getHeader(), xfr.getBodySize(), 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); + _deliveryProps = _header.getDeliveryProperties(); + _messageProps = _header.getMessageProperties(); } else { @@ -78,21 +75,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes _arrivalTime = arrivalTime; _bodySize = bodySize; - - - if(xfrBody == null) - { - _body = null; - } - else - { - ByteBuffer body = ByteBuffer.allocate(_bodySize); - body.put(xfrBody); - body.flip(); - _body = new SoftReference<ByteBuffer>(body); - } - - } @@ -122,16 +104,39 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes encoder.writeInt64(_arrivalTime); encoder.writeInt32(_bodySize); - Struct[] headers = _header == null ? new Struct[0] : _header.getStructs(); - encoder.writeInt32(headers.length); + int headersLength = 0; + if(_header.getDeliveryProperties() != null) + { + headersLength++; + } + if(_header.getMessageProperties() != null) + { + headersLength++; + } + if(_header.getNonStandardProperties() != null) + { + headersLength += _header.getNonStandardProperties().size(); + } + encoder.writeInt32(headersLength); - for(Struct header : headers) + if(_header.getDeliveryProperties() != null) { - encoder.writeStruct32(header); - + encoder.writeStruct32(_header.getDeliveryProperties()); + } + if(_header.getMessageProperties() != null) + { + encoder.writeStruct32(_header.getMessageProperties()); } + if(_header.getNonStandardProperties() != null) + { + for(Struct header : _header.getNonStandardProperties()) + { + encoder.writeStruct32(header); + } + + } ByteBuffer buf = encoder.buffer(); return buf; } @@ -173,6 +178,11 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); } + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(getRoutingKey()); + } + public AMQMessageHeader getMessageHeader() { return _messageHeader; @@ -210,17 +220,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes return _header; } - public ByteBuffer getBody() - { - ByteBuffer body = _body == null ? null : _body.get(); - return body; - } - - public void setBody(ByteBuffer body) - { - _body = new SoftReference<ByteBuffer>(body); - } - private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_0_10> { public MessageMetaData_0_10 createMetaData(ByteBuffer buf) @@ -232,14 +231,32 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes int bodySize = decoder.readInt32(); int headerCount = decoder.readInt32(); - Struct[] headers = new Struct[headerCount]; + DeliveryProperties deliveryProperties = null; + MessageProperties messageProperties = null; + List<Struct> otherProps = null; for(int i = 0 ; i < headerCount; i++) { - headers[i] = decoder.readStruct32(); + Struct struct = decoder.readStruct32(); + if(struct instanceof DeliveryProperties && deliveryProperties == null) + { + deliveryProperties = (DeliveryProperties) struct; + } + else if(struct instanceof MessageProperties && messageProperties == null) + { + messageProperties = (MessageProperties) struct; + } + else + { + if(otherProps == null) + { + otherProps = new ArrayList<Struct>(); + + } + otherProps.add(struct); + } } - - Header header = new Header(headers); + Header header = new Header(deliveryProperties,messageProperties,otherProps); return new MessageMetaData_0_10(header, bodySize, arrivalTime); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java index 51841e6dd0..30934ae014 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java @@ -24,32 +24,35 @@ import org.apache.qpid.transport.*; import org.apache.qpid.server.configuration.SessionConfig; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.framing.AMQShortString; import java.nio.ByteBuffer; -import java.lang.ref.WeakReference; -public class MessageTransferMessage extends AbstractServerMessageImpl implements InboundMessage +public class MessageTransferMessage extends AbstractServerMessageImpl<MessageMetaData_0_10> implements InboundMessage { - private StoredMessage<MessageMetaData_0_10> _storeMessage; - private WeakReference<Session> _sessionRef; - public MessageTransferMessage(StoredMessage<MessageMetaData_0_10> storeMessage, WeakReference<Session> sessionRef) + private Object _connectionRef; + + public MessageTransferMessage(StoredMessage<MessageMetaData_0_10> storeMessage, Object connectionRef) { super(storeMessage); - _storeMessage = storeMessage; - _sessionRef = sessionRef; + _connectionRef = connectionRef; } private MessageMetaData_0_10 getMetaData() { - return _storeMessage.getMetaData(); + return getStoredMessage().getMetaData(); } public String getRoutingKey() { return getMetaData().getRoutingKey(); + } + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(getRoutingKey()); } public AMQMessageHeader getMessageHeader() @@ -91,9 +94,9 @@ public class MessageTransferMessage extends AbstractServerMessageImpl implements return new TransferMessageReference(this); } - public Long getMessageNumber() + public long getMessageNumber() { - return _storeMessage.getMessageNumber(); + return getStoredMessage().getMessageNumber(); } public long getArrivalTime() @@ -103,7 +106,13 @@ public class MessageTransferMessage extends AbstractServerMessageImpl implements public int getContent(ByteBuffer buf, int offset) { - return _storeMessage.getContent(offset, buf); + return getStoredMessage().getContent(offset, buf); + } + + + public ByteBuffer getContent(int offset, int size) + { + return getStoredMessage().getContent(offset,size); } public Header getHeader() @@ -113,32 +122,13 @@ public class MessageTransferMessage extends AbstractServerMessageImpl implements public ByteBuffer getBody() { - ByteBuffer body = getMetaData().getBody(); - if(body == null && getSize() != 0l) - { - 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; + return getContent(0, (int)getSize()); } - public Session getSession() + public Object getConnectionReference() { - return _sessionRef == null ? null : _sessionRef.get(); + return _connectionRef; } - public SessionConfig getSessionConfig() - { - return _sessionRef == null ? null : (ServerSession) _sessionRef.get(); - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java index 2f2d39115f..2d25135326 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java @@ -23,13 +23,17 @@ package org.apache.qpid.server.message; import java.nio.ByteBuffer; import org.apache.qpid.server.configuration.SessionConfig; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.StoredMessage; -public interface ServerMessage extends EnqueableMessage, MessageContentSource +public interface ServerMessage<T extends StorableMessageMetaData> extends EnqueableMessage, MessageContentSource { String getRoutingKey(); AMQMessageHeader getMessageHeader(); + public StoredMessage<T> getStoredMessage(); + boolean isPersistent(); long getSize(); @@ -40,11 +44,12 @@ public interface ServerMessage extends EnqueableMessage, MessageContentSource MessageReference newReference(); - Long getMessageNumber(); + long getMessageNumber(); long getArrivalTime(); public int getContent(ByteBuffer buf, int offset); - SessionConfig getSessionConfig(); + public ByteBuffer getContent(int offset, int size); + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java b/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java index aded3f3d2a..483bca894e 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java @@ -40,8 +40,8 @@ public class HeaderPropertiesConverter BasicContentHeaderProperties props = new BasicContentHeaderProperties(); Header header = messageTransferMessage.getHeader(); - DeliveryProperties deliveryProps = header.get(DeliveryProperties.class); - MessageProperties messageProps = header.get(MessageProperties.class); + DeliveryProperties deliveryProps = header.getDeliveryProperties(); + MessageProperties messageProps = header.getMessageProperties(); if(deliveryProps != null) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java index 3970e5a2d4..efd904f6aa 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java @@ -1,420 +1,420 @@ -/*
- *
- * 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.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output.amqp0_8;
-
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-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.MessagePublishInfo;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.transport.DeliveryProperties;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
-
- private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- 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, org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl.CLASS_ID);
- chb.bodySize = message.getSize();
- return chb;
- }
- }
-
-
- 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
- {
-
-
- int bodySize = (int) message.getSize();
-
- if(bodySize == 0)
- {
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
- writeFrame(compositeBlock);
- }
- else
- {
- int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
-
-
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
-
- int writtenSize = capacity;
-
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
-
- CompositeAMQBodyBlock
- compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
- writeFrame(compositeBlock);
-
- while(writtenSize < bodySize)
- {
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
-
- writeFrame(new AMQFrame(channelId, body));
- }
- }
- }
-
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
- }
-
-
- public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
- AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
- writeMessageDelivery(entry, channelId, deliver);
- }
-
-
- private AMQBody createEncodedDeliverBody(QueueEntry entry,
- final long deliveryTag,
- final AMQShortString consumerTag)
- throws AMQException
- {
-
- 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();
-
- final AMQBody returnBlock = new AMQBody()
- {
-
- public AMQBody _underlyingBody;
-
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- isRedelivered,
- exchangeName,
- routingKey);
-
-
-
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
- }
-
- private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
- throws AMQException
- {
- 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,
- isRedelivered,
- exchangeName,
- routingKey,
- queueSize);
-
- return getOkBody;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
- int replyCode,
- AMQShortString replyText) throws AMQException
- {
-
- BasicReturnBody basicReturnBody =
- METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- messagePublishInfo.getExchange(),
- messagePublishInfo.getRoutingKey());
-
-
- return basicReturnBody;
- }
-
- public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
-
- AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
-
- writeMessageDelivery(message, header, channelId, returnFrame);
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
-
- BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
-}
+/* + * + * 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. + * + */ + +/* + * This file is auto-generated by Qpid Gentools v.0.1 - do not modify. + * Supported AMQP versions: + * 8-0 + */ +package org.apache.qpid.server.output.amqp0_8; + +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.apache.qpid.server.protocol.AMQProtocolSession; +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.MessagePublishInfo; +import org.apache.qpid.AMQException; +import org.apache.qpid.transport.DeliveryProperties; + +import java.io.DataOutput; +import java.io.IOException; + +public class ProtocolOutputConverterImpl implements ProtocolOutputConverter +{ + + private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0); + + public static Factory getInstanceFactory() + { + return new Factory() + { + + public ProtocolOutputConverter newInstance(AMQProtocolSession session) + { + return new ProtocolOutputConverterImpl(session); + } + }; + } + + + private final AMQProtocolSession _protocolSession; + + private ProtocolOutputConverterImpl(AMQProtocolSession session) + { + _protocolSession = session; + } + + + public AMQProtocolSession getProtocolSession() + { + return _protocolSession; + } + + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) + throws AMQException + { + 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, org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl.CLASS_ID); + chb.bodySize = message.getSize(); + return chb; + } + } + + + 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 + { + + + int bodySize = (int) message.getSize(); + + if(bodySize == 0) + { + SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody, + contentHeaderBody); + + writeFrame(compositeBlock); + } + else + { + int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead(); + + + int capacity = bodySize > maxBodySize ? maxBodySize : bodySize; + + int writtenSize = capacity; + + AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity); + + CompositeAMQBodyBlock + compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody); + writeFrame(compositeBlock); + + while(writtenSize < bodySize) + { + capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize; + MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity); + writtenSize += capacity; + + writeFrame(new AMQFrame(channelId, body)); + } + } + } + + private class MessageContentSourceBody implements AMQBody + { + public static final byte TYPE = 3; + private int _length; + private MessageContentSource _message; + private int _offset; + + public MessageContentSourceBody(MessageContentSource message, int offset, int length) + { + _message = message; + _offset = offset; + _length = length; + } + + public byte getFrameType() + { + return TYPE; + } + + public int getSize() + { + return _length; + } + + public void writePayload(DataOutput buffer) throws IOException + { + byte[] data = new byte[_length]; + + _message.getContent(java.nio.ByteBuffer.wrap(data), _offset); + + buffer.write(data); + } + + public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException + { + throw new UnsupportedOperationException(); + } + } + + private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody) + { + + AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, + contentHeaderBody); + return contentHeader; + } + + + public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException + { + AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); + writeMessageDelivery(entry, channelId, deliver); + } + + + private AMQBody createEncodedDeliverBody(QueueEntry entry, + final long deliveryTag, + final AMQShortString consumerTag) + throws AMQException + { + + 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().getDeliveryProperties(); + 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(); + + final AMQBody returnBlock = new AMQBody() + { + + public AMQBody _underlyingBody; + + public AMQBody createAMQBody() + { + return METHOD_REGISTRY.createBasicDeliverBody(consumerTag, + deliveryTag, + isRedelivered, + exchangeName, + routingKey); + + + + + + } + + public byte getFrameType() + { + return AMQMethodBody.TYPE; + } + + public int getSize() + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + return _underlyingBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + _underlyingBody.writePayload(buffer); + } + + public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) + throws AMQException + { + throw new AMQException("This block should never be dispatched!"); + } + }; + return returnBlock; + } + + private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) + throws AMQException + { + 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().getDeliveryProperties(); + 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, + isRedelivered, + exchangeName, + routingKey, + queueSize); + + return getOkBody; + } + + public byte getProtocolMinorVersion() + { + return getProtocolSession().getProtocolMinorVersion(); + } + + public byte getProtocolMajorVersion() + { + return getProtocolSession().getProtocolMajorVersion(); + } + + private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, + int replyCode, + AMQShortString replyText) throws AMQException + { + + BasicReturnBody basicReturnBody = + METHOD_REGISTRY.createBasicReturnBody(replyCode, + replyText, + messagePublishInfo.getExchange(), + messagePublishInfo.getRoutingKey()); + + + return basicReturnBody; + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText) + throws AMQException + { + + AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText); + + writeMessageDelivery(message, header, channelId, returnFrame); + } + + + public void writeFrame(AMQDataBlock block) + { + getProtocolSession().writeFrame(block); + } + + + public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) + { + + BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag); + writeFrame(basicCancelOkBody.generateFrame(channelId)); + + } + + + public static final class CompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final AMQBody _contentBody; + private final int _channel; + + + public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + _contentBody = contentBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); + } + } + + public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final int _channel; + + + public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ; + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java index aef3483282..010afcb1a9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java @@ -1,419 +1,418 @@ -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
- * 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.
- *
- */
-
-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.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.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;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
- private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
-
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- 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;
- }
- }
-
-
- 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
- {
-
-
- int bodySize = (int) message.getSize();
-
- if(bodySize == 0)
- {
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
- writeFrame(compositeBlock);
- }
- else
- {
- int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
-
-
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
-
- int writtenSize = capacity;
-
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
-
-
- CompositeAMQBodyBlock
- compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
- writeFrame(compositeBlock);
-
- while(writtenSize < bodySize)
- {
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
-
- writeFrame(new AMQFrame(channelId, body));
- }
- }
- }
-
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
- }
-
-
- public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
- AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
- writeMessageDelivery(entry, channelId, deliver);
- }
-
-
- private AMQBody createEncodedDeliverBody(QueueEntry entry,
- final long deliveryTag,
- final AMQShortString consumerTag)
- throws AMQException
- {
-
- 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();
-
- final AMQBody returnBlock = new AMQBody()
- {
-
- public AMQBody _underlyingBody;
-
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- isRedelivered,
- exchangeName,
- routingKey);
-
-
-
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
- }
-
- private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
- throws AMQException
- {
- 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,
- isRedelivered,
- exchangeName,
- routingKey,
- queueSize);
-
- return getOkBody;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
- int replyCode,
- AMQShortString replyText) throws AMQException
- {
-
- BasicReturnBody basicReturnBody =
- METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- messagePublishInfo.getExchange(),
- messagePublishInfo.getRoutingKey());
-
-
- return basicReturnBody;
- }
-
- public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
-
- AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
-
- writeMessageDelivery(message, header, channelId, returnFrame);
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
-
- BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
-
-}
+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 + * 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. + * + */ + +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.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.amqp_0_9.BasicGetBodyImpl; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.AMQException; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; + +import java.io.DataOutput; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class ProtocolOutputConverterImpl implements ProtocolOutputConverter +{ + private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); + + + public static Factory getInstanceFactory() + { + return new Factory() + { + + public ProtocolOutputConverter newInstance(AMQProtocolSession session) + { + return new ProtocolOutputConverterImpl(session); + } + }; + } + + private final AMQProtocolSession _protocolSession; + + private ProtocolOutputConverterImpl(AMQProtocolSession session) + { + _protocolSession = session; + } + + + public AMQProtocolSession getProtocolSession() + { + return _protocolSession; + } + + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) + throws AMQException + { + 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; + } + } + + + 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 + { + + + int bodySize = (int) message.getSize(); + + if(bodySize == 0) + { + SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody, + contentHeaderBody); + + writeFrame(compositeBlock); + } + else + { + int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead(); + + + int capacity = bodySize > maxBodySize ? maxBodySize : bodySize; + + int writtenSize = capacity; + + AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity); + + + CompositeAMQBodyBlock + compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody); + writeFrame(compositeBlock); + + while(writtenSize < bodySize) + { + capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize; + MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity); + writtenSize += capacity; + + writeFrame(new AMQFrame(channelId, body)); + } + } + } + + private class MessageContentSourceBody implements AMQBody + { + public static final byte TYPE = 3; + private int _length; + private MessageContentSource _message; + private int _offset; + + public MessageContentSourceBody(MessageContentSource message, int offset, int length) + { + _message = message; + _offset = offset; + _length = length; + } + + public byte getFrameType() + { + return TYPE; + } + + public int getSize() + { + return _length; + } + + public void writePayload(DataOutput buffer) throws IOException + { + byte[] data = new byte[_length]; + + _message.getContent(ByteBuffer.wrap(data), _offset); + + buffer.write(data); + } + + public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException + { + throw new UnsupportedOperationException(); + } + } + + + private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody) + { + + AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, + contentHeaderBody); + return contentHeader; + } + + + public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException + { + AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); + writeMessageDelivery(entry, channelId, deliver); + } + + + private AMQBody createEncodedDeliverBody(QueueEntry entry, + final long deliveryTag, + final AMQShortString consumerTag) + throws AMQException + { + + 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().getDeliveryProperties(); + 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(); + + final AMQBody returnBlock = new AMQBody() + { + + public AMQBody _underlyingBody; + + public AMQBody createAMQBody() + { + return METHOD_REGISTRY.createBasicDeliverBody(consumerTag, + deliveryTag, + isRedelivered, + exchangeName, + routingKey); + + + + + + } + + public byte getFrameType() + { + return AMQMethodBody.TYPE; + } + + public int getSize() + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + return _underlyingBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + _underlyingBody.writePayload(buffer); + } + + public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) + throws AMQException + { + throw new AMQException("This block should never be dispatched!"); + } + }; + return returnBlock; + } + + private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) + throws AMQException + { + 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().getDeliveryProperties(); + 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, + isRedelivered, + exchangeName, + routingKey, + queueSize); + + return getOkBody; + } + + public byte getProtocolMinorVersion() + { + return getProtocolSession().getProtocolMinorVersion(); + } + + public byte getProtocolMajorVersion() + { + return getProtocolSession().getProtocolMajorVersion(); + } + + private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, + int replyCode, + AMQShortString replyText) throws AMQException + { + + BasicReturnBody basicReturnBody = + METHOD_REGISTRY.createBasicReturnBody(replyCode, + replyText, + messagePublishInfo.getExchange(), + messagePublishInfo.getRoutingKey()); + + + return basicReturnBody; + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText) + throws AMQException + { + + AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText); + + writeMessageDelivery(message, header, channelId, returnFrame); + } + + + public void writeFrame(AMQDataBlock block) + { + getProtocolSession().writeFrame(block); + } + + + public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) + { + + BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag); + writeFrame(basicCancelOkBody.generateFrame(channelId)); + + } + + + public static final class CompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final AMQBody _contentBody; + private final int _channel; + + + public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + _contentBody = contentBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); + } + } + + public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final int _channel; + + + public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ; + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java index 10748298bc..5e2b3e4556 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java @@ -1,414 +1,425 @@ -package org.apache.qpid.server.output.amqp0_9_1;
-/*
- *
- * 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.
- *
- */
-
-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.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.amqp_0_91.BasicGetBodyImpl;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
- private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91);
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- 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;
- }
- }
-
-
- 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
- {
-
-
- int bodySize = (int) message.getSize();
-
- if(bodySize == 0)
- {
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
- writeFrame(compositeBlock);
- }
- else
- {
- int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
-
-
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
-
- int writtenSize = capacity;
-
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
-
- CompositeAMQBodyBlock
- compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
- writeFrame(compositeBlock);
-
- while(writtenSize < bodySize)
- {
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
-
- writeFrame(new AMQFrame(channelId, body));
- }
- }
- }
-
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
- }
-
-
- public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
- AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
- writeMessageDelivery(entry, channelId, deliver);
- }
-
-
- private AMQBody createEncodedDeliverBody(QueueEntry entry,
- final long deliveryTag,
- final AMQShortString consumerTag)
- throws AMQException
- {
-
- 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();
-
- final AMQBody returnBlock = new AMQBody()
- {
-
- public AMQBody _underlyingBody;
-
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- isRedelivered,
- exchangeName,
- routingKey);
-
-
-
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
- }
-
- private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
- throws AMQException
- {
- 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,
- isRedelivered,
- exchangeName,
- routingKey,
- queueSize);
-
- return getOkBody;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
- int replyCode,
- AMQShortString replyText) throws AMQException
- {
-
- BasicReturnBody basicReturnBody =
- METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- messagePublishInfo.getExchange(),
- messagePublishInfo.getRoutingKey());
-
-
- return basicReturnBody;
- }
-
- public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
-
- AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
-
- writeMessageDelivery(message, header, channelId, returnFrame);
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
-
- BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
-
+package org.apache.qpid.server.output.amqp0_9_1; +/* + * + * 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. + * + */ + +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.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.amqp_0_91.BasicGetBodyImpl; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.AMQException; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; + +import java.io.DataOutput; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class ProtocolOutputConverterImpl implements ProtocolOutputConverter +{ + private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91); + + public static Factory getInstanceFactory() + { + return new Factory() + { + + public ProtocolOutputConverter newInstance(AMQProtocolSession session) + { + return new ProtocolOutputConverterImpl(session); + } + }; + } + + private final AMQProtocolSession _protocolSession; + + private ProtocolOutputConverterImpl(AMQProtocolSession session) + { + _protocolSession = session; + } + + + public AMQProtocolSession getProtocolSession() + { + return _protocolSession; + } + + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) + throws AMQException + { + 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; + } + } + + + 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 + { + + + int bodySize = (int) message.getSize(); + + if(bodySize == 0) + { + SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody, + contentHeaderBody); + + writeFrame(compositeBlock); + } + else + { + int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead(); + + + int capacity = bodySize > maxBodySize ? maxBodySize : bodySize; + + int writtenSize = capacity; + + AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity); + + CompositeAMQBodyBlock + compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody); + writeFrame(compositeBlock); + + while(writtenSize < bodySize) + { + capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize; + MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity); + writtenSize += capacity; + + writeFrame(new AMQFrame(channelId, body)); + } + } + } + + private class MessageContentSourceBody implements AMQBody + { + public static final byte TYPE = 3; + private int _length; + private MessageContentSource _message; + private int _offset; + + public MessageContentSourceBody(MessageContentSource message, int offset, int length) + { + _message = message; + _offset = offset; + _length = length; + } + + public byte getFrameType() + { + return TYPE; + } + + public int getSize() + { + return _length; + } + + public void writePayload(DataOutput buffer) throws IOException + { + ByteBuffer buf = _message.getContent(_offset, _length); + + if(buf.hasArray()) + { + buffer.write(buf.array(), buf.arrayOffset()+buf.position(), buf.remaining()); + } + else + { + + byte[] data = new byte[_length]; + + buf.get(data); + + buffer.write(data); + } + } + + public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException + { + throw new UnsupportedOperationException(); + } + } + + private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody) + { + + AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, + contentHeaderBody); + return contentHeader; + } + + + public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException + { + AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); + writeMessageDelivery(entry, channelId, deliver); + } + + + private AMQBody createEncodedDeliverBody(QueueEntry entry, + final long deliveryTag, + final AMQShortString consumerTag) + throws AMQException + { + + 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().getDeliveryProperties(); + 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(); + + final AMQBody returnBlock = new AMQBody() + { + + public AMQBody _underlyingBody; + + public AMQBody createAMQBody() + { + return METHOD_REGISTRY.createBasicDeliverBody(consumerTag, + deliveryTag, + isRedelivered, + exchangeName, + routingKey); + + + + + + } + + public byte getFrameType() + { + return AMQMethodBody.TYPE; + } + + public int getSize() + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + return _underlyingBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + if(_underlyingBody == null) + { + _underlyingBody = createAMQBody(); + } + _underlyingBody.writePayload(buffer); + } + + public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) + throws AMQException + { + throw new AMQException("This block should never be dispatched!"); + } + }; + return returnBlock; + } + + private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) + throws AMQException + { + 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().getDeliveryProperties(); + 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, + isRedelivered, + exchangeName, + routingKey, + queueSize); + + return getOkBody; + } + + public byte getProtocolMinorVersion() + { + return getProtocolSession().getProtocolMinorVersion(); + } + + public byte getProtocolMajorVersion() + { + return getProtocolSession().getProtocolMajorVersion(); + } + + private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, + int replyCode, + AMQShortString replyText) throws AMQException + { + + BasicReturnBody basicReturnBody = + METHOD_REGISTRY.createBasicReturnBody(replyCode, + replyText, + messagePublishInfo.getExchange(), + messagePublishInfo.getRoutingKey()); + + + return basicReturnBody; + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText) + throws AMQException + { + + AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText); + + writeMessageDelivery(message, header, channelId, returnFrame); + } + + + public void writeFrame(AMQDataBlock block) + { + getProtocolSession().writeFrame(block); + } + + + public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) + { + + BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag); + writeFrame(basicCancelOkBody.generateFrame(channelId)); + + } + + + public static final class CompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final AMQBody _contentBody; + private final int _channel; + + + public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + _contentBody = contentBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize(); + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); + } + } + + public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock + { + public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead(); + + private final AMQBody _methodBody; + private final AMQBody _headerBody; + private final int _channel; + + + public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody) + { + _channel = channel; + _methodBody = methodBody; + _headerBody = headerBody; + + } + + public long getSize() + { + return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ; + } + + public void writePayload(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); + } + } + }
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 2a277848ed..b778cf4135 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -111,6 +111,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr // to save boxing the channelId and looking up in a map... cache in an array the low numbered // channels. This value must be of the form 2^x - 1. private static final int CHANNEL_CACHE_SIZE = 0xff; + private static final int REUSABLE_BYTE_BUFFER_CAPACITY = 65 * 1024; private AMQShortString _contextKey; @@ -280,6 +281,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr closeProtocolSession(); } } + receiveComplete(); } catch (Exception e) { @@ -288,6 +290,15 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr } } + private void receiveComplete() + { + for (AMQChannel channel : _channelMap.values()) + { + channel.receivedComplete(); + } + + } + public void dataBlockReceived(AMQDataBlock message) throws Exception { _lastReceived = message; @@ -405,35 +416,51 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr } } + + private final byte[] _reusableBytes = new byte[REUSABLE_BYTE_BUFFER_CAPACITY]; + private final ByteBuffer _reusableByteBuffer = ByteBuffer.wrap(_reusableBytes); + private final BytesDataOutput _reusableDataOutput = new BytesDataOutput(_reusableBytes); + private ByteBuffer asByteBuffer(AMQDataBlock block) { - final ByteBuffer buf = ByteBuffer.allocate((int) block.getSize()); + final int size = (int) block.getSize(); - try - { - block.writePayload(new DataOutputStream(new OutputStream() - { + final byte[] data; - @Override - public void write(int b) throws IOException - { - buf.put((byte) b); - } + if(size > REUSABLE_BYTE_BUFFER_CAPACITY) + { + data= new byte[size]; + } + else + { - @Override - public void write(byte[] b, int off, int len) throws IOException - { - buf.put(b, off, len); - } - })); + data = _reusableBytes; + } + _reusableDataOutput.setBuffer(data); + + try + { + block.writePayload(_reusableDataOutput); } catch (IOException e) { throw new RuntimeException(e); } - buf.flip(); + final ByteBuffer buf; + + if(size <= REUSABLE_BYTE_BUFFER_CAPACITY) + { + buf = _reusableByteBuffer; + buf.position(0); + } + else + { + buf = ByteBuffer.wrap(data); + } + buf.limit(_reusableDataOutput.length()); + return buf; } @@ -1425,7 +1452,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _statisticsEnabled = enabled; } - @Override public boolean isSessionNameUnique(byte[] name) { // 0-8/0-9/0-9-1 sessions don't have names @@ -1437,9 +1463,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _deferFlush = deferFlush; } - - - @Override public String getUserName() { return getAuthorizedPrincipal().getName(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java index b4765d6227..143a6ae8ca 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java @@ -557,7 +557,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que List<String> list = new ArrayList<String>(); AMQMessageHeader header = msg.getMessageHeader(); - MessageProperties msgProps = msg.getHeader().get(MessageProperties.class); + MessageProperties msgProps = msg.getHeader().getMessageProperties(); String appID = null; String userID = null; @@ -619,7 +619,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); } - ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog()); + ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore()); _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn); txn.commit(); } @@ -654,7 +654,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); } - ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog()); + ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore()); _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java index 05e0efd9a6..0bd40e8f13 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java @@ -35,6 +35,7 @@ public interface BaseQueue extends TransactionLogResource void enqueue(ServerMessage message) throws AMQException; void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException; + void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException; boolean isDurable(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java index c4762c98c9..ab0a567114 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java @@ -100,7 +100,7 @@ public class ConflationQueueList extends SimpleQueueEntryList { if(entry.acquire()) { - ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); + ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); txn.dequeue(entry.getQueue(),entry.getMessage(), new ServerTransaction.Action() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java index 26112d9f53..31e9725e47 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.framing.AMQShortString; public class InboundMessageAdapter implements InboundMessage { @@ -44,6 +45,11 @@ public class InboundMessageAdapter implements InboundMessage } + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(_entry.getMessage()); + } + public String getRoutingKey() { return _entry.getMessage().getRoutingKey(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java index a56f5685b8..19a7a15ad1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java @@ -63,7 +63,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes * delivered. It is <b>cleared after delivery has been attempted</b>. Any persistent record of destinations is done * by the message handle. */ - private ArrayList<? extends BaseQueue> _destinationQueues; + private List<? extends BaseQueue> _destinationQueues; private long _expiration; @@ -126,12 +126,18 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes public MessageMetaData headersReceived() { - _messageMetaData = new MessageMetaData(_messagePublishInfo, _contentHeaderBody, 0); + + return headersReceived(System.currentTimeMillis()); + } + + public MessageMetaData headersReceived(long currentTime) + { + _messageMetaData = new MessageMetaData(_messagePublishInfo, _contentHeaderBody, 0, currentTime); return _messageMetaData; } - public ArrayList<? extends BaseQueue> getDestinationQueues() + public List<? extends BaseQueue> getDestinationQueues() { return _destinationQueues; } @@ -158,6 +164,11 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes return _messagePublishInfo.getExchange(); } + public AMQShortString getRoutingKeyShortString() + { + return _messagePublishInfo.getRoutingKey(); + } + public String getRoutingKey() { return _messagePublishInfo.getRoutingKey() == null ? null : _messagePublishInfo.getRoutingKey().toString(); @@ -209,7 +220,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes return getContentHeader().bodySize; } - public Long getMessageNumber() + public long getMessageNumber() { return _storedMessageHandle.getMessageNumber(); } @@ -225,7 +236,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes } - public void enqueue(final ArrayList<? extends BaseQueue> queues) + public void enqueue(final List<? extends BaseQueue> queues) { _destinationQueues = queues; } @@ -288,6 +299,15 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes } + + public ByteBuffer getContent(int offset, int size) + { + ByteBuffer buf = ByteBuffer.allocate(size); + getContent(buf,offset); + buf.flip(); + return buf; + } + public void setStoredMessage(StoredMessage<MessageMetaData> storedMessageHandle) { _storedMessageHandle = storedMessageHandle; diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 5bb5dc3462..bd349e7512 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -29,6 +29,7 @@ import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; import java.util.Collection; @@ -424,7 +425,7 @@ public abstract class QueueEntryImpl implements QueueEntry if (rerouteQueues != null && rerouteQueues.size() != 0) { - ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); + ServerTransaction txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore()); txn.enqueue(rerouteQueues, message, new ServerTransaction.Action() { @@ -447,7 +448,8 @@ public abstract class QueueEntryImpl implements QueueEntry { } - }); + }, 0L); + txn.dequeue(currentQueue, message, new ServerTransaction.Action() { public void postCommit() @@ -460,8 +462,10 @@ public abstract class QueueEntryImpl implements QueueEntry } }); - } + + txn.commit(); } + } } public boolean isQueueDeleted() @@ -549,4 +553,11 @@ public abstract class QueueEntryImpl implements QueueEntry _deliveryCountUpdater.decrementAndGet(this); } + public String toString() + { + return "QueueEntryImpl{" + + "_entryId=" + _entryId + + ", _state=" + _state + + '}'; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java index 5270f9f740..a6cdb40d72 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java @@ -51,7 +51,6 @@ public class QueueRunner implements ReadWriteRunnable private final AtomicInteger _scheduled = new AtomicInteger(IDLE); - private static final long ITERATIONS = SimpleAMQQueue.MAX_ASYNC_DELIVERIES; private final AtomicBoolean _stateChange = new AtomicBoolean(); private final AtomicLong _lastRunAgain = new AtomicLong(); @@ -65,8 +64,6 @@ public class QueueRunner implements ReadWriteRunnable _queue = queue; } - private int trouble = 0; - public void run() { if(_scheduled.compareAndSet(SCHEDULED,RUNNING)) diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index cc93cbc2f1..25fc91b998 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -584,8 +584,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException { + enqueue(message, false, action); + } + + public void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException + { - incrementTxnEnqueueStats(message); + if(transactional) + { + incrementTxnEnqueueStats(message); + } incrementQueueCount(); incrementQueueSize(message); @@ -733,13 +741,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private void incrementTxnEnqueueStats(final ServerMessage message) { - SessionConfig session = message.getSessionConfig(); - - if(session !=null && session.isTransactional()) - { - _msgTxnEnqueues.incrementAndGet(); - _byteTxnEnqueues.addAndGet(message.getSize()); - } + _msgTxnEnqueues.incrementAndGet(); + _byteTxnEnqueues.addAndGet(message.getSize()); } private void incrementTxnDequeueStats(QueueEntry entry) @@ -1447,7 +1450,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { } - }); + }, 0L); txn.dequeue(this, entry.getMessage(), new ServerTransaction.Action() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java index abf9e3379d..7d4748bcaa 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java @@ -32,11 +32,9 @@ import static org.apache.qpid.server.security.access.Operation.UNBIND; import java.net.SocketAddress; import java.security.Principal; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import javax.security.auth.Subject; @@ -192,6 +190,15 @@ public class SecurityManager return _logger; } + private static class CachedPropertiesMap extends LinkedHashMap<String, PublishAccessCheck> + { + @Override + protected boolean removeEldestEntry(Entry<String, PublishAccessCheck> eldest) + { + return size() >= 200; + } + } + private abstract class AccessCheck { abstract Result allowed(SecurityPlugin plugin); @@ -204,56 +211,61 @@ public class SecurityManager return true; } - HashMap<String, SecurityPlugin> remainingPlugins = new HashMap<String, SecurityPlugin>(_globalPlugins); + Map<String, SecurityPlugin> remainingPlugins = _globalPlugins.isEmpty() + ? Collections.<String, SecurityPlugin>emptyMap() + : _hostPlugins.isEmpty() ? _globalPlugins : new HashMap<String, SecurityPlugin>(_globalPlugins); - for (Entry<String, SecurityPlugin> hostEntry : _hostPlugins.entrySet()) + if(!_hostPlugins.isEmpty()) { - // Create set of global only plugins - SecurityPlugin globalPlugin = remainingPlugins.get(hostEntry.getKey()); - if (globalPlugin != null) - { - remainingPlugins.remove(hostEntry.getKey()); - } - - Result host = checker.allowed(hostEntry.getValue()); - - if (host == Result.DENIED) - { - // Something vetoed the access, we're done - return false; - } - - // host allow overrides global allow, so only check global on abstain or defer - if (host != Result.ALLOWED) - { - if (globalPlugin == null) - { - if (host == Result.DEFER) - { - host = hostEntry.getValue().getDefault(); - } - if (host == Result.DENIED) + for (Entry<String, SecurityPlugin> hostEntry : _hostPlugins.entrySet()) + { + // Create set of global only plugins + SecurityPlugin globalPlugin = remainingPlugins.get(hostEntry.getKey()); + if (globalPlugin != null) + { + remainingPlugins.remove(hostEntry.getKey()); + } + + Result host = checker.allowed(hostEntry.getValue()); + + if (host == Result.DENIED) + { + // Something vetoed the access, we're done + return false; + } + + // host allow overrides global allow, so only check global on abstain or defer + if (host != Result.ALLOWED) + { + if (globalPlugin == null) { - return false; + if (host == Result.DEFER) + { + host = hostEntry.getValue().getDefault(); + } + if (host == Result.DENIED) + { + return false; + } } - } - else - { - Result global = checker.allowed(globalPlugin); - if (global == Result.DEFER) - { - global = globalPlugin.getDefault(); - } - if (global == Result.ABSTAIN && host == Result.DEFER) - { - global = hostEntry.getValue().getDefault(); - } - if (global == Result.DENIED) + else { - return false; + Result global = checker.allowed(globalPlugin); + if (global == Result.DEFER) + { + global = globalPlugin.getDefault(); + } + if (global == Result.ABSTAIN && host == Result.DEFER) + { + global = hostEntry.getValue().getDefault(); + } + if (global == Result.DENIED) + { + return false; + } } - } - } + } + } } for (SecurityPlugin plugin : remainingPlugins.values()) @@ -371,15 +383,33 @@ public class SecurityManager }); } + + private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _immediatePublishPropsCache + = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>(); + private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _publishPropsCache + = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>(); + public boolean authorisePublish(final boolean immediate, final String routingKey, final String exchangeName) { - return checkAllPlugins(new AccessCheck() + PublishAccessCheck check; + ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> cache = + immediate ? _immediatePublishPropsCache : _publishPropsCache; + + ConcurrentHashMap<String, PublishAccessCheck> exchangeMap = cache.get(exchangeName); + if(exchangeMap == null) { - Result allowed(SecurityPlugin plugin) + cache.putIfAbsent(exchangeName, new ConcurrentHashMap<String, PublishAccessCheck>()); + exchangeMap = cache.get(exchangeName); + } + + check = exchangeMap.get(routingKey); + if(check == null) { - return plugin.authorise(PUBLISH, EXCHANGE, new ObjectProperties(exchangeName, routingKey, immediate)); + check = new PublishAccessCheck(new ObjectProperties(exchangeName, routingKey, immediate)); + exchangeMap.put(routingKey, check); } - }); + + return checkAllPlugins(check); } public boolean authorisePurge(final AMQQueue queue) @@ -413,4 +443,19 @@ public class SecurityManager return current; } + + private class PublishAccessCheck extends AccessCheck + { + private final ObjectProperties _props; + + public PublishAccessCheck(ObjectProperties props) + { + _props = props; + } + + Result allowed(SecurityPlugin plugin) + { + return plugin.authorise(PUBLISH, EXCHANGE, _props); + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java index e4bf8df340..8a52d31f97 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java @@ -18,10 +18,7 @@ */ package org.apache.qpid.server.security.access; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import org.apache.commons.lang.StringUtils; import org.apache.qpid.framing.AMQShortString; @@ -35,7 +32,7 @@ import org.apache.qpid.server.queue.AMQQueue; * {@link #equals(Object)} and {@link #hashCode()} are intended for use in maps. This is due to the wildcard matching * described above. */ -public class ObjectProperties extends HashMap<ObjectProperties.Property, String> +public class ObjectProperties { /** serialVersionUID */ private static final long serialVersionUID = -1356019341374170495L; @@ -93,7 +90,9 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> return properties; } } - + + private final EnumMap<Property, String> _properties = new EnumMap<Property, String>(Property.class); + public static List<String> getAllPropertyNames() { List<String> properties = new ArrayList<String>(); @@ -113,7 +112,7 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> { super(); - putAll(copy); + _properties.putAll(copy._properties); } public ObjectProperties(String name) @@ -231,7 +230,7 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> public List<String> getPropertyNames() { List<String> properties = new ArrayList<String>(); - for (Property property : keySet()) + for (Property property : _properties.keySet()) { properties.add(property.getName()); } @@ -240,17 +239,22 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> public Boolean isSet(Property key) { - return containsKey(key) && Boolean.valueOf(get(key)); + return _properties.containsKey(key) && Boolean.valueOf(_properties.get(key)); } - + + public String get(Property key) + { + return _properties.get(key); + } + public String getName() { - return get(Property.NAME); + return _properties.get(Property.NAME); } public void setName(String name) { - put(Property.NAME, name); + _properties.put(Property.NAME, name); } public void setName(AMQShortString name) @@ -262,39 +266,38 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> { return put(key, value == null ? "" : value.asString()); } - - @Override + public String put(Property key, String value) { - return super.put(key, value == null ? "" : value.trim()); + return _properties.put(key, value == null ? "" : value.trim()); } public void put(Property key, Boolean value) { if (value != null) { - super.put(key, Boolean.toString(value)); + _properties.put(key, Boolean.toString(value)); } } public boolean matches(ObjectProperties properties) { - if (properties.keySet().isEmpty()) + if (properties._properties.keySet().isEmpty()) { return true; } - if (!keySet().containsAll(properties.keySet())) + if (!_properties.keySet().containsAll(properties._properties.keySet())) { return false; } - for (Map.Entry<Property,String> entry : properties.entrySet()) + for (Map.Entry<Property,String> entry : properties._properties.entrySet()) { Property key = entry.getKey(); String ruleValue = entry.getValue(); - String thisValue = get(key); + String thisValue = _properties.get(key); if (!valueMatches(thisValue, ruleValue)) { @@ -315,4 +318,29 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String> && thisValue.length() > ruleValue.length() && thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 2))); } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ObjectProperties that = (ObjectProperties) o; + + if (_properties != null ? !_properties.equals(that._properties) : that._properties != null) return false; + + return true; + } + + @Override + public int hashCode() + { + return _properties != null ? _properties.hashCode() : 0; + } + + @Override + public String toString() + { + return _properties.toString(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java index d3f46d2e90..d90b3d02ba 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java @@ -52,6 +52,8 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; /** @@ -60,7 +62,7 @@ import org.apache.qpid.server.queue.AMQQueue; * * TODO extract the SQL statements into a generic JDBC store */ -public class DerbyMessageStore implements MessageStore +public class DerbyMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger _logger = Logger.getLogger(DerbyMessageStore.class); @@ -197,12 +199,16 @@ public class DerbyMessageStore implements MessageStore Configuration storeConfiguration, LogSubject logSubject) throws Exception { - CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName())); - if(!_configured) { _logSubject = logSubject; + } + + CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName())); + + if(!_configured) + { commonConfiguration(name, storeConfiguration, logSubject); _configured = true; @@ -219,6 +225,11 @@ public class DerbyMessageStore implements MessageStore Configuration storeConfiguration, LogSubject logSubject) throws Exception { + + if(!_configured) + { + _logSubject = logSubject; + } CurrentActor.get().message(_logSubject, TransactionLogMessages.CREATED(this.getClass().getName())); if(!_configured) @@ -697,7 +708,7 @@ public class DerbyMessageStore implements MessageStore if (results == 0) { - throw new RuntimeException("Message metadata not found for message id " + messageId); + _logger.warn("Message metadata not found for message id " + messageId); } if (_logger.isDebugEnabled()) @@ -1678,14 +1689,26 @@ public class DerbyMessageStore implements MessageStore } } - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, messageId); + if(message.getStoredMessage() instanceof StoredDerbyMessage) + { + try + { + ((StoredDerbyMessage)message.getStoredMessage()).store(_connWrapper.getConnection()); + } + catch (SQLException e) + { + throw new AMQStoreException("Exception on enqueuing message " + _messageId, e); + } + } + + DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber()); } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, messageId); + DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, message.getMessageNumber()); } @@ -1709,8 +1732,11 @@ public class DerbyMessageStore implements MessageStore { private final long _messageId; + private StorableMessageMetaData _metaData; private volatile SoftReference<StorableMessageMetaData> _metaDataRef; - private Connection _conn; + private byte[] _data; + private volatile SoftReference<byte[]> _dataRef; + StoredDerbyMessage(long messageId, StorableMessageMetaData metaData) { @@ -1721,27 +1747,19 @@ public class DerbyMessageStore implements MessageStore StoredDerbyMessage(long messageId, StorableMessageMetaData metaData, boolean persist) { - try - { - _messageId = messageId; + _messageId = messageId; + - _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); - if(persist) - { - _conn = newConnection(); - storeMetaData(_conn, messageId, metaData); - } - } - catch (SQLException e) + _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); + if(persist) { - throw new RuntimeException(e); + _metaData = metaData; } - } public StorableMessageMetaData getMetaData() { - StorableMessageMetaData metaData = _metaDataRef.get(); + StorableMessageMetaData metaData = _metaData == null ? _metaDataRef.get() : _metaData; if(metaData == null) { try @@ -1765,27 +1783,62 @@ public class DerbyMessageStore implements MessageStore public void addContent(int offsetInMessage, java.nio.ByteBuffer src) { - DerbyMessageStore.this.addContent(_conn, _messageId, offsetInMessage, src); + src = src.slice(); + + if(_data == null) + { + _data = new byte[src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + src.duplicate().get(_data); + } + else + { + byte[] oldData = _data; + _data = new byte[oldData.length + src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + + System.arraycopy(oldData,0,_data,0,oldData.length); + src.duplicate().get(_data, oldData.length, src.remaining()); + } + } public int getContent(int offsetInMessage, java.nio.ByteBuffer dst) { - return DerbyMessageStore.this.getContent(_messageId, offsetInMessage, dst); + byte[] data = _dataRef == null ? null : _dataRef.get(); + if(data != null) + { + int length = Math.min(dst.remaining(), data.length - offsetInMessage); + dst.put(data, offsetInMessage, length); + return length; + } + else + { + return DerbyMessageStore.this.getContent(_messageId, offsetInMessage, dst); + } + } + + + public ByteBuffer getContent(int offsetInMessage, int size) + { + ByteBuffer buf = ByteBuffer.allocate(size); + getContent(offsetInMessage, buf); + buf.position(0); + return buf; } - public StoreFuture flushToStore() + public synchronized StoreFuture flushToStore() { try { - if(_conn != null) + if(_metaData != null) { - if(_logger.isDebugEnabled()) - { - _logger.debug("Flushing message " + _messageId + " to store"); - } + Connection conn = newConnection(); + + store(conn); - _conn.commit(); - _conn.close(); + conn.commit(); + conn.close(); } } catch (SQLException e) @@ -1796,16 +1849,34 @@ public class DerbyMessageStore implements MessageStore } throw new RuntimeException(e); } - finally + return IMMEDIATE_FUTURE; + } + + private synchronized void store(final Connection conn) throws SQLException + { + if(_metaData != null) { - _conn = null; + try + { + storeMetaData(conn, _messageId, _metaData); + DerbyMessageStore.this.addContent(conn, _messageId, 0, + _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data)); + } + finally + { + _metaData = null; + _data = null; + } + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Storing message " + _messageId + " to store"); } - return IMMEDIATE_FUTURE; } public void remove() { - flushToStore(); DerbyMessageStore.this.removeMessage(_messageId); } } @@ -1839,4 +1910,5 @@ public class DerbyMessageStore implements MessageStore } } } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java index d008d42fa0..005055dbaa 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -35,10 +35,12 @@ import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.MessageStoreMessages; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; /** A simple message store that stores the messages in a threadsafe structure in memory. */ -public class MemoryMessageStore implements MessageStore +public class MemoryMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger _log = Logger.getLogger(MemoryMessageStore.class); @@ -53,11 +55,11 @@ public class MemoryMessageStore implements MessageStore private static final Transaction IN_MEMORY_TRANSACTION = new Transaction() { - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java index e2fca2f9c7..88c95ad65e 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -20,14 +20,16 @@ */ package org.apache.qpid.server.store; +import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.logging.LogSubject; import org.apache.commons.configuration.Configuration; +import org.apache.qpid.server.message.EnqueableMessage; /** * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages. * */ -public interface MessageStore extends DurableConfigurationStore, TransactionLog +public interface MessageStore { StoreFuture IMMEDIATE_FUTURE = new StoreFuture() { @@ -77,4 +79,69 @@ public interface MessageStore extends DurableConfigurationStore, TransactionLog boolean isPersistent(); + + 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 message + * @throws org.apache.qpid.AMQStoreException If the operation fails for any reason. + */ + void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException; + + /** + * Extracts a message from a specified queue, in a given transactional context. + * + * @param queue The queue to place the message on. + * @param message The message to dequeue. + * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist. + */ + void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException; + + + /** + * Commits all operations performed within a given transactional context. + * + * @throws AMQStoreException If the operation fails for any reason. + */ + void commitTran() throws AMQStoreException; + + /** + * Commits all operations performed within a given transactional context. + * + * @throws AMQStoreException If the operation fails for any reason. + */ + StoreFuture commitTranAsync() throws AMQStoreException; + + /** + * Abandons all operations performed within a given transactional context. + * + * @throws AMQStoreException If the operation fails for any reason. + */ + void abortTran() throws AMQStoreException; + + + + } + + public void configureTransactionLog(String name, + TransactionLogRecoveryHandler recoveryHandler, + Configuration storeConfiguration, + LogSubject logSubject) throws Exception; + + Transaction newTransaction(); + + + + public static interface StoreFuture + { + boolean isComplete(); + + void waitForCompletion(); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java index 1f5b027b80..858a850d8c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java @@ -26,15 +26,13 @@ import java.nio.ByteBuffer; public class StoredMemoryMessage implements StoredMessage { private final long _messageNumber; - private final ByteBuffer _content; + private ByteBuffer _content; private final StorableMessageMetaData _metaData; public StoredMemoryMessage(long messageNumber, StorableMessageMetaData metaData) { _messageNumber = messageNumber; _metaData = metaData; - _content = ByteBuffer.allocate(metaData.getContentSize()); - } public long getMessageNumber() @@ -44,26 +42,79 @@ public class StoredMemoryMessage implements StoredMessage public void addContent(int offsetInMessage, ByteBuffer src) { - src = src.duplicate(); - ByteBuffer dst = _content.duplicate(); - dst.position(offsetInMessage); - dst.put(src); + if(_content == null) + { + if(offsetInMessage == 0) + { + _content = src.slice(); + } + else + { + final int contentSize = _metaData.getContentSize(); + int size = (contentSize < offsetInMessage + src.remaining()) + ? offsetInMessage + src.remaining() + : contentSize; + _content = ByteBuffer.allocate(size); + addContent(offsetInMessage, src); + } + } + else + { + if(_content.limit() >= offsetInMessage + src.remaining()) + { + _content.position(offsetInMessage); + _content.put(src); + _content.position(0); + } + else + { + final int contentSize = _metaData.getContentSize(); + int size = (contentSize < offsetInMessage + src.remaining()) + ? offsetInMessage + src.remaining() + : contentSize; + ByteBuffer oldContent = _content; + _content = ByteBuffer.allocate(size); + _content.put(oldContent); + _content.position(0); + addContent(offsetInMessage, src); + } + + } } public int getContent(int offset, ByteBuffer dst) { ByteBuffer src = _content.duplicate(); - src.position(offset); - src = src.slice(); - if(dst.remaining() < src.limit()) + + int oldPosition = src.position(); + + src.position(oldPosition + offset); + + int length = dst.remaining() < src.remaining() ? dst.remaining() : src.remaining(); + src.limit(oldPosition + length); + + dst.put(src); + + + return length; + } + + + public ByteBuffer getContent(int offsetInMessage, int size) + { + ByteBuffer buf = _content.duplicate(); + + if(offsetInMessage != 0) { - src.limit(dst.remaining()); + buf.position(offsetInMessage); + buf = buf.slice(); } - dst.put(src); - return src.limit(); + + buf.limit(size); + return buf; } - public TransactionLog.StoreFuture flushToStore() + public MessageStore.StoreFuture flushToStore() { return MessageStore.IMMEDIATE_FUTURE; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java index 0bc45c6718..d4a0381929 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java @@ -32,7 +32,9 @@ public interface StoredMessage<M extends StorableMessageMetaData> int getContent(int offsetInMessage, ByteBuffer dst); - TransactionLog.StoreFuture flushToStore(); + ByteBuffer getContent(int offsetInMessage, int size); + + MessageStore.StoreFuture flushToStore(); void remove(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java index d196a91930..da7f8d18b2 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java @@ -20,72 +20,7 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.AMQStoreException; -import org.apache.commons.configuration.Configuration; - public interface TransactionLog { - 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 AMQStoreException If the operation fails for any reason. - */ - void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException; - - /** - * 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 AMQStoreException If the operation fails for any reason, or if the specified message does not exist. - */ - void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException; - - - /** - * Commits all operations performed within a given transactional context. - * - * @throws AMQStoreException If the operation fails for any reason. - */ - void commitTran() throws AMQStoreException; - - /** - * Commits all operations performed within a given transactional context. - * - * @throws AMQStoreException If the operation fails for any reason. - */ - StoreFuture commitTranAsync() throws AMQStoreException; - - /** - * Abandons all operations performed within a given transactional context. - * - * @throws AMQStoreException If the operation fails for any reason. - */ - void abortTran() throws AMQStoreException; - - - - } - - public void configureTransactionLog(String name, - TransactionLogRecoveryHandler recoveryHandler, - Configuration storeConfiguration, - LogSubject logSubject) throws Exception; - - Transaction newTransaction(); - - - - public static interface StoreFuture - { - boolean isComplete(); - - void waitForCompletion(); - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java index 7781c52df3..802596ed1e 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.store; public interface TransactionLogRecoveryHandler { - QueueEntryRecoveryHandler begin(TransactionLog log); + QueueEntryRecoveryHandler begin(MessageStore log); public static interface QueueEntryRecoveryHandler { diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index 6c18b2e229..dea88c4776 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -62,7 +62,6 @@ import org.apache.qpid.transport.MessageProperties; import org.apache.qpid.transport.MessageTransfer; import org.apache.qpid.transport.Method; import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.Session; import org.apache.qpid.transport.Struct; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; @@ -70,10 +69,10 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.AMQException; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.locks.Lock; @@ -183,6 +182,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); } _queue = queue; + Map<String, Object> arguments = queue.getArguments() == null ? Collections.EMPTY_MAP : queue.getArguments(); _traceExclude = (String) arguments.get("qpid.trace.exclude"); _trace = (String) arguments.get("qpid.trace.id"); @@ -224,8 +224,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr if (_noLocal && entry.getMessage() instanceof MessageTransferMessage) { - Session messageSession= ((MessageTransferMessage)entry.getMessage()).getSession(); - if (messageSession != null && messageSession.getConnection() == _session.getConnection()) + Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference(); + if (connectionRef != null && connectionRef == _session.getReference()) { return false; } @@ -377,35 +377,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { MessageTransferMessage msg = (MessageTransferMessage) serverMsg; - - - Struct[] headers; - if(msg.getHeader() == null) - { - headers = EMPTY_STRUCT_ARRAY; - } - else - { - headers = msg.getHeader().getStructs(); - } - - ArrayList<Struct> newHeaders = new ArrayList<Struct>(headers.length); - DeliveryProperties origDeliveryProps = null; - for(Struct header : headers) - { - if(header instanceof DeliveryProperties) - { - origDeliveryProps = (DeliveryProperties) header; - } - else - { - if(header instanceof MessageProperties) - { - messageProps = (MessageProperties) header; - } - newHeaders.add(header); - } - } + DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties(); + messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties(); deliveryProps = new DeliveryProperties(); if(origDeliveryProps != null) @@ -440,17 +413,16 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr deliveryProps.setRedelivered(entry.isRedelivered()); - newHeaders.add(deliveryProps); - if(_trace != null && messageProps == null) { messageProps = new MessageProperties(); - newHeaders.add(messageProps); } - Header header = new Header(newHeaders); + Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties()); + - xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); } else if(serverMsg instanceof AMQMessage) { @@ -463,8 +435,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr message_0_8.getContent(body, 0); body.flip(); - Struct[] headers = new Struct[] { deliveryProps, messageProps }; - BasicContentHeaderProperties properties = (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties(); final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); @@ -505,8 +475,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr messageProps.setApplicationHeaders(appHeaders); - Header header = new Header(headers); - xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + Header header = new Header(deliveryProps, messageProps, null); + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); } else { @@ -519,8 +490,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr serverMsg.getContent(body, 0); body.flip(); - Struct[] headers = new Struct[] { deliveryProps, messageProps }; - deliveryProps.setExpiration(serverMsg.getExpiration()); deliveryProps.setImmediate(serverMsg.isImmediate()); @@ -567,8 +536,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr messageProps.setApplicationHeaders(appHeaders); */ - Header header = new Header(headers); - xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + Header header = new Header(deliveryProps, messageProps, null); + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); } boolean excludeDueToFederation = false; @@ -644,28 +614,51 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } } - private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) + private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit) { - ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); - txn.dequeue(entry.getQueue(),entry.getMessage(), - new ServerTransaction.Action() - { - public void postCommit() - { - if(restoreCredit) - { - restoreCredit(entry); - } - entry.discard(); - } + _deferredMessageCredit += deferredMessageCredit; + _deferredSizeCredit += deferredSizeCredit; - public void onRollback() - { + } - } - }); + public void flushCreditState() + { + flushCreditState(false); + } + public void flushCreditState(boolean strict) + { + if(strict || !isSuspended() || _deferredMessageCredit >= 200 + || !(_creditManager instanceof WindowCreditManager) + || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 ) + { + _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit); + _deferredMessageCredit = 0; + _deferredSizeCredit = 0l; + } } + private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) + { + AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); + dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(), + new ServerTransaction.Action() + { + public void postCommit() + { + if (restoreCredit) + { + restoreCredit(entry); + } + entry.discard(); + } + + public void onRollback() + { + + } + }); + } + void reject(final QueueEntry entry) { entry.setRedelivered(); @@ -704,7 +697,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { final InboundMessage m = new InboundMessageAdapter(entry); - final ArrayList<? extends BaseQueue> destinationQueues = alternateExchange.route(m); + final List<? extends BaseQueue> destinationQueues = alternateExchange.route(m); if (destinationQueues == null || destinationQueues.isEmpty()) { @@ -751,6 +744,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _stateChangeLock.tryLock(); } + public void getSendLock() { _stateChangeLock.lock(); @@ -816,28 +810,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _properties.get(key); } - private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit) - { - _deferredMessageCredit += deferredMessageCredit; - _deferredSizeCredit += deferredSizeCredit; - - } - - public void flushCreditState() - { - flushCreditState(false); - } - public void flushCreditState(boolean strict) - { - if(strict || !isSuspended() || _deferredMessageCredit >= 200 - || !(_creditManager instanceof WindowCreditManager) - || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 ) - { - _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit); - _deferredMessageCredit = 0; - _deferredSizeCredit = 0l; - } - } public FlowCreditManager_0_10 getCreditManager() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index 00f0c9f0f1..ab07ed20f6 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -75,7 +75,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec private boolean _statisticsEnabled = false; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private final long _connectionId; - + private final Object _reference = new Object(); private ServerConnectionMBean _mBean; private VirtualHost _virtualHost; private AtomicLong _lastIoTime = new AtomicLong(); @@ -90,6 +90,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec return _config.getId(); } + public Object getReference() + { + return _reference; + } + @Override protected void invoke(Method method) { @@ -414,13 +419,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec return _connectionId; } - @Override public boolean isSessionNameUnique(byte[] name) { return !super.hasSessionWithName(name); } - @Override public String getUserName() { return _authorizedPrincipal.getName(); @@ -450,11 +453,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec { for (Session ssn : getChannels()) { - ((ServerSession)ssn).flushCreditState(); + ((ServerSession)ssn).receivedComplete(); } } - @Override + public ManagedObject getManagedObject() { return _mBean; diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index 1ce7b806d8..8e6d33d3bc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.transport; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; import static org.apache.qpid.util.Serial.gt; -import java.lang.ref.WeakReference; import java.security.Principal; import java.text.MessageFormat; import java.util.ArrayList; @@ -71,6 +70,7 @@ import org.apache.qpid.transport.MessageTransfer; import org.apache.qpid.transport.Method; import org.apache.qpid.transport.Range; import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.RangeSetFactory; import org.apache.qpid.transport.Session; import org.apache.qpid.transport.SessionDelegate; import org.slf4j.Logger; @@ -86,6 +86,7 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi private ConnectionConfig _connectionConfig; private long _createTime = System.currentTimeMillis(); private LogActor _actor = GenericActor.getInstance(this); + private PostEnqueueAction _postEnqueueAction = new PostEnqueueAction(); public static interface MessageDispositionChangeListener { @@ -121,8 +122,6 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi private final List<Task> _taskList = new CopyOnWriteArrayList<Task>(); - private final WeakReference<Session> _reference; - ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) { this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig()); @@ -134,7 +133,6 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi _connectionConfig = connConfig; _transaction = new AutoCommitTransaction(this.getMessageStore()); - _reference = new WeakReference<Session>(this); _id = getConfigStore().createId(); getConfigStore().addConfiguredObject(this); } @@ -161,40 +159,22 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi return isCommandsFull(id); } - public void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues) + public void enqueue(final ServerMessage message, final List<? extends BaseQueue> queues) { getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime()); - _transaction.enqueue(queues,message, new ServerTransaction.Action() - { - - BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]); - - public void postCommit() - { - MessageReference<?> ref = message.newReference(); - for(int i = 0; i < _queues.length; i++) - { - try - { - _queues[i].enqueue(message); - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - } - ref.release(); - } - - public void onRollback() - { - // NO-OP - } - }); - - incrementOutstandingTxnsIfNecessary(); - updateTransactionalActivity(); + PostEnqueueAction postTransactionAction; + if(isTransactional()) + { + postTransactionAction = new PostEnqueueAction(queues, message) ; + } + else + { + postTransactionAction = _postEnqueueAction; + postTransactionAction.setState(queues, message); + } + _transaction.enqueue(queues,message, postTransactionAction, 0L); + incrementOutstandingTxnsIfNecessary(); + updateTransactionalActivity(); } @@ -252,7 +232,7 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi public RangeSet acquire(RangeSet transfers) { - RangeSet acquired = new RangeSet(); + RangeSet acquired = RangeSetFactory.createRangeSet(); if(!_messageDispositionListenerMap.isEmpty()) { @@ -300,41 +280,56 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi public void dispositionChange(RangeSet ranges, MessageDispositionAction action) { - if(ranges != null && !_messageDispositionListenerMap.isEmpty()) + if(ranges != null) { - Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); - Iterator<Range> rangeIter = ranges.iterator(); - if(rangeIter.hasNext()) + if(ranges.size() == 1) { - Range range = rangeIter.next(); + Range r = ranges.getFirst(); + for(int i = r.getLower(); i <= r.getUpper(); i++) + { + MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(i); + if(changeListener != null) + { + action.performAction(changeListener); + } + } + } + else if(!_messageDispositionListenerMap.isEmpty()) + { + Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); + Iterator<Range> rangeIter = ranges.iterator(); - while(range != null && unacceptedMessages.hasNext()) + if(rangeIter.hasNext()) { - int next = unacceptedMessages.next(); - while(gt(next, range.getUpper())) + Range range = rangeIter.next(); + + while(range != null && unacceptedMessages.hasNext()) { - if(rangeIter.hasNext()) + int next = unacceptedMessages.next(); + while(gt(next, range.getUpper())) { - range = rangeIter.next(); + if(rangeIter.hasNext()) + { + range = rangeIter.next(); + } + else + { + range = null; + break; + } } - else + if(range != null && range.includes(next)) { - range = null; - break; + MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(next); + action.performAction(changeListener); } - } - if(range != null && range.includes(next)) - { - MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(next); - action.performAction(changeListener); - } - } + } + } } - } } @@ -534,10 +529,10 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi _taskList.remove(task); } - public WeakReference<Session> getReference() - { - return _reference; - } + public Object getReference() + { + return ((ServerConnection) getConnection()).getReference(); + } public MessageStore getMessageStore() { @@ -697,7 +692,7 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi } } - public void flushCreditState() + public void receivedComplete() { final Collection<Subscription_0_10> subscriptions = getSubscriptions(); for (Subscription_0_10 subscription_0_10 : subscriptions) @@ -706,6 +701,54 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi } } + private static class PostEnqueueAction implements ServerTransaction.Action + { + + private List<? extends BaseQueue> _queues; + private ServerMessage _message; + private final boolean _transactional; + + public PostEnqueueAction(List<? extends BaseQueue> queues, ServerMessage message) + { + _transactional = true; + setState(queues, message); + } + + public PostEnqueueAction() + { + _transactional = false; + } + + public void setState(List<? extends BaseQueue> queues, ServerMessage message) + { + _message = message; + _queues = queues; + } + + public void postCommit() + { + MessageReference<?> ref = _message.newReference(); + for(int i = 0; i < _queues.size(); i++) + { + try + { + _queues.get(i).enqueue(_message, _transactional, null); + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + } + ref.release(); + } + + public void onRollback() + { + // NO-OP + } + } + public int getUnacknowledgedMessageCount() { return _messageDispositionListenerMap.size(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index a0dca53ed0..b6e142a5fd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.transport; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import org.apache.log4j.Logger; @@ -55,46 +56,7 @@ import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Acquired; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.ExchangeBind; -import org.apache.qpid.transport.ExchangeBound; -import org.apache.qpid.transport.ExchangeBoundResult; -import org.apache.qpid.transport.ExchangeDeclare; -import org.apache.qpid.transport.ExchangeDelete; -import org.apache.qpid.transport.ExchangeQuery; -import org.apache.qpid.transport.ExchangeQueryResult; -import org.apache.qpid.transport.ExchangeUnbind; -import org.apache.qpid.transport.ExecutionErrorCode; -import org.apache.qpid.transport.ExecutionException; -import org.apache.qpid.transport.MessageAccept; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquire; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageCancel; -import org.apache.qpid.transport.MessageFlow; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.MessageFlush; -import org.apache.qpid.transport.MessageReject; -import org.apache.qpid.transport.MessageRejectCode; -import org.apache.qpid.transport.MessageRelease; -import org.apache.qpid.transport.MessageResume; -import org.apache.qpid.transport.MessageSetFlowMode; -import org.apache.qpid.transport.MessageStop; -import org.apache.qpid.transport.MessageSubscribe; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Method; -import org.apache.qpid.transport.QueueDeclare; -import org.apache.qpid.transport.QueueDelete; -import org.apache.qpid.transport.QueuePurge; -import org.apache.qpid.transport.QueueQuery; -import org.apache.qpid.transport.QueueQueryResult; -import org.apache.qpid.transport.RangeSet; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.SessionDelegate; -import org.apache.qpid.transport.TxCommit; -import org.apache.qpid.transport.TxRollback; -import org.apache.qpid.transport.TxSelect; +import org.apache.qpid.transport.*; public class ServerSessionDelegate extends SessionDelegate { @@ -295,7 +257,8 @@ public class ServerSessionDelegate extends SessionDelegate final Exchange exchange = getExchangeForMessage(ssn, xfr); DeliveryProperties delvProps = null; - if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration()) + if(xfr.getHeader() != null && (delvProps = xfr.getHeader().getDeliveryProperties()) != null && delvProps.hasTtl() && !delvProps + .hasExpiration()) { delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); } @@ -312,7 +275,7 @@ public class ServerSessionDelegate extends SessionDelegate } final Exchange exchangeInUse; - ArrayList<? extends BaseQueue> queues = exchange.route(messageMetaData); + List<? extends BaseQueue> queues = exchange.route(messageMetaData); if(queues.isEmpty() && exchange.getAlternateExchange() != null) { final Exchange alternateExchange = exchange.getAlternateExchange(); @@ -334,15 +297,16 @@ public class ServerSessionDelegate extends SessionDelegate if(!queues.isEmpty()) { final MessageStore store = getVirtualHost(ssn).getMessageStore(); - final StoredMessage<MessageMetaData_0_10> storeMessage = createAndFlushStoreMessage(xfr, messageMetaData, store); + final StoredMessage<MessageMetaData_0_10> storeMessage = createStoreMessage(xfr, messageMetaData, store); MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference()); ((ServerSession) ssn).enqueue(message, queues); + storeMessage.flushToStore(); } else { if((delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) { - RangeSet rejects = new RangeSet(); + RangeSet rejects = RangeSetFactory.createRangeSet(); rejects.add(xfr.getId()); MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); ssn.invoke(reject); @@ -353,11 +317,13 @@ public class ServerSessionDelegate extends SessionDelegate } } + + ssn.processed(xfr); } - private StoredMessage<MessageMetaData_0_10> createAndFlushStoreMessage(final MessageTransfer xfr, - final MessageMetaData_0_10 messageMetaData, final MessageStore store) + private StoredMessage<MessageMetaData_0_10> createStoreMessage(final MessageTransfer xfr, + final MessageMetaData_0_10 messageMetaData, final MessageStore store) { final StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData); ByteBuffer body = xfr.getBody(); @@ -365,7 +331,6 @@ public class ServerSessionDelegate extends SessionDelegate { storeMessage.addContent(0, body); } - storeMessage.flushToStore(); return storeMessage; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java index 36e9d78440..a67d4badd1 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.txn; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -30,7 +31,7 @@ import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.MessageStore; /** * An implementation of ServerTransaction where each enqueue/dequeue @@ -43,11 +44,11 @@ public class AutoCommitTransaction implements ServerTransaction { protected static final Logger _logger = Logger.getLogger(AutoCommitTransaction.class); - private final TransactionLog _transactionLog; + private final MessageStore _messageStore; - public AutoCommitTransaction(TransactionLog transactionLog) + public AutoCommitTransaction(MessageStore transactionLog) { - _transactionLog = transactionLog; + _messageStore = transactionLog; } public long getTransactionStartTime() @@ -59,14 +60,14 @@ public class AutoCommitTransaction implements ServerTransaction * Since AutoCommitTransaction have no concept of a long lived transaction, any Actions registered * by the caller are executed immediately. */ - public void addPostTransactionAction(Action immediateAction) + public void addPostTransactionAction(final Action immediateAction) { immediateAction.postCommit(); } public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction) { - TransactionLog.Transaction txn = null; + MessageStore.Transaction txn = null; try { if(message.isPersistent() && queue.isDurable()) @@ -76,8 +77,8 @@ public class AutoCommitTransaction implements ServerTransaction _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); } - txn = _transactionLog.newTransaction(); - txn.dequeueMessage(queue, message.getMessageNumber()); + txn = _messageStore.newTransaction(); + txn.dequeueMessage(queue, message); txn.commitTran(); txn = null; } @@ -98,7 +99,7 @@ public class AutoCommitTransaction implements ServerTransaction public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction) { - TransactionLog.Transaction txn = null; + MessageStore.Transaction txn = null; try { for(QueueEntry entry : queueEntries) @@ -115,10 +116,10 @@ public class AutoCommitTransaction implements ServerTransaction if(txn == null) { - txn = _transactionLog.newTransaction(); + txn = _messageStore.newTransaction(); } - txn.dequeueMessage(queue, message.getMessageNumber()); + txn.dequeueMessage(queue, message); } } @@ -145,7 +146,7 @@ public class AutoCommitTransaction implements ServerTransaction public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction) { - TransactionLog.Transaction txn = null; + MessageStore.Transaction txn = null; try { if(message.isPersistent() && queue.isDurable()) @@ -155,8 +156,8 @@ public class AutoCommitTransaction implements ServerTransaction _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); } - txn = _transactionLog.newTransaction(); - txn.enqueueMessage(queue, message.getMessageNumber()); + txn = _messageStore.newTransaction(); + txn.enqueueMessage(queue, message); txn.commitTran(); txn = null; } @@ -176,15 +177,14 @@ public class AutoCommitTransaction implements ServerTransaction } - public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction) + public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime) { - TransactionLog.Transaction txn = null; + MessageStore.Transaction txn = null; try { if(message.isPersistent()) { - Long id = message.getMessageNumber(); for(BaseQueue queue : queues) { if (queue.isDurable()) @@ -195,22 +195,26 @@ public class AutoCommitTransaction implements ServerTransaction } if (txn == null) { - txn = _transactionLog.newTransaction(); + txn = _messageStore.newTransaction(); } - txn.enqueueMessage(queue, id); + txn.enqueueMessage(queue, message); + + } } - if (txn != null) - { - txn.commitTran(); - txn = null; - - } } + if (txn != null) + { + txn.commitTran(); + txn = null; + } + postTransactionAction.postCommit(); postTransactionAction = null; + + } catch (AMQException e) { @@ -225,6 +229,11 @@ public class AutoCommitTransaction implements ServerTransaction } + public void commit(final Runnable immediatePostTransactionAction) + { + immediatePostTransactionAction.run(); + } + public void commit() { } @@ -233,7 +242,7 @@ public class AutoCommitTransaction implements ServerTransaction { } - private void rollbackIfNecessary(Action postTransactionAction, TransactionLog.Transaction txn) + private void rollbackIfNecessary(Action postTransactionAction, MessageStore.Transaction txn) { if (txn != null) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index 946dbd7c28..7f5b5fb8b2 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -29,11 +29,7 @@ import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.TransactionLog; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.MessageStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,11 +46,11 @@ public class LocalTransaction implements ServerTransaction private final List<Action> _postTransactionActions = new ArrayList<Action>(); - private volatile TransactionLog.Transaction _transaction; - private TransactionLog _transactionLog; + private volatile MessageStore.Transaction _transaction; + private MessageStore _transactionLog; private long _txnStartTime = 0L; - public LocalTransaction(TransactionLog transactionLog) + public LocalTransaction(MessageStore transactionLog) { _transactionLog = transactionLog; } @@ -63,7 +59,7 @@ public class LocalTransaction implements ServerTransaction { return _transaction != null; } - + public long getTransactionStartTime() { return _txnStartTime; @@ -88,7 +84,7 @@ public class LocalTransaction implements ServerTransaction } beginTranIfNecessary(); - _transaction.dequeueMessage(queue, message.getMessageNumber()); + _transaction.dequeueMessage(queue, message); } catch(AMQException e) @@ -118,7 +114,7 @@ public class LocalTransaction implements ServerTransaction } beginTranIfNecessary(); - _transaction.dequeueMessage(queue, message.getMessageNumber()); + _transaction.dequeueMessage(queue, message); } } @@ -191,7 +187,7 @@ public class LocalTransaction implements ServerTransaction } beginTranIfNecessary(); - _transaction.enqueueMessage(queue, message.getMessageNumber()); + _transaction.enqueueMessage(queue, message); } catch (Exception e) { @@ -202,13 +198,13 @@ public class LocalTransaction implements ServerTransaction } } - public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction) + public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime) { _postTransactionActions.add(postTransactionAction); if (_txnStartTime == 0L) { - _txnStartTime = System.currentTimeMillis(); + _txnStartTime = currentTime == 0L ? System.currentTimeMillis() : currentTime; } if(message.isPersistent()) @@ -226,7 +222,7 @@ public class LocalTransaction implements ServerTransaction beginTranIfNecessary(); - _transaction.enqueueMessage(queue, message.getMessageNumber()); + _transaction.enqueueMessage(queue, message); } } @@ -242,6 +238,11 @@ public class LocalTransaction implements ServerTransaction public void commit() { + commit(null); + } + + public void commit(Runnable immediateAction) + { try { if(_transaction != null) @@ -249,9 +250,14 @@ public class LocalTransaction implements ServerTransaction _transaction.commitTran(); } - for(Action action : _postTransactionActions) + if(immediateAction != null) + { + immediateAction.run(); + } + + for(int i = 0; i < _postTransactionActions.size(); i++) { - action.postCommit(); + _postTransactionActions.get(i).postCommit(); } } catch (Exception e) diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java index b3c6e1ac3a..64fdc0ba9a 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; @@ -42,7 +43,7 @@ import java.util.List; */ public interface ServerTransaction { - /** + /** * Represents an action to be performed on transaction commit or rollback */ public static interface Action @@ -91,7 +92,7 @@ public interface ServerTransaction * * Store operations will result only for a persistent messages on durable queues. */ - void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction); + void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime); /** * Commit the transaction represented by this object. @@ -101,6 +102,8 @@ public interface ServerTransaction */ void commit(); + void commit(Runnable immediatePostTransactionAction); + /** Rollback the transaction represented by this object. * * If the caller has registered one or more Actions, the onRollback() method on each will diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index 04f19b79bb..24ab29444c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -39,7 +39,6 @@ import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TransactionLog; public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer { @@ -57,8 +56,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo MessageStore getMessageStore(); - TransactionLog getTransactionLog(); - DurableConfigurationStore getDurableConfigurationStore(); AuthenticationManager getAuthenticationManager(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index 0fd31973b2..aad3547789 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -20,12 +20,12 @@ */ package org.apache.qpid.server.virtualhost; +import org.apache.qpid.server.message.EnqueableMessage; 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; @@ -73,7 +73,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa 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>(); @@ -86,7 +85,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa _virtualHost = virtualHost; } - public QueueRecoveryHandler begin(MessageStore store) + public VirtualHostConfigRecoveryHandler begin(MessageStore store) { _logSubject = new MessageStoreLogSubject(_virtualHost,store); _store = store; @@ -99,14 +98,12 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa { try { - AMQShortString queueNameShortString = new AMQShortString(queueName); - - AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueNameShortString); + AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueName); if (q == null) { - q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, exclusive, _virtualHost, - arguments); + q = AMQQueueFactory.createAMQQueueImpl(queueName, true, owner, false, exclusive, _virtualHost, + FieldTable.convertToMap(arguments)); _virtualHost.getQueueRegistry().registerQueue(q); } @@ -186,12 +183,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa //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; @@ -316,15 +307,15 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa else { _logger.warn("Message id " + messageId + " referenced in log as enqueued in queue " + queue.getNameShortString() + " is unknown, entry will be discarded"); - TransactionLog.Transaction txn = _transactionLog.newTransaction(); - txn.dequeueMessage(queue, messageId); + MessageStore.Transaction txn = _store.newTransaction(); + txn.dequeueMessage(queue, new DummyMessage(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(); + MessageStore.Transaction txn = _store.newTransaction(); TransactionLogResource mockQueue = new TransactionLogResource() { @@ -334,7 +325,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa return queueName; } }; - txn.dequeueMessage(mockQueue, messageId); + txn.dequeueMessage(mockQueue, new DummyMessage(messageId)); txn.commitTranAsync(); } @@ -367,4 +358,32 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false)); } + private static class DummyMessage implements EnqueableMessage + { + + + private final long _messageId; + + public DummyMessage(long messageId) + { + _messageId = messageId; + } + + public long getMessageNumber() + { + return _messageId; + } + + + public boolean isPersistent() + { + return true; + } + + + public StoredMessage getStoredMessage() + { + return null; + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index 17c65003e9..9b1c5474a3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -75,7 +75,6 @@ import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.ConfigurationRecoveryHandler; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TransactionLog; import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin; import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory; @@ -228,7 +227,10 @@ public class VirtualHostImpl implements VirtualHost if (store != null) { _messageStore = store; - _durableConfigurationStore = store; + if(store instanceof DurableConfigurationStore) + { + _durableConfigurationStore = (DurableConfigurationStore) store; + } } else { @@ -380,6 +382,8 @@ public class VirtualHostImpl implements VirtualHost 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 + @@ -390,10 +394,18 @@ public class VirtualHostImpl implements VirtualHost MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStore); - messageStore.configureConfigStore(this.getName(), - recoveryHandler, - hostConfig.getStoreConfiguration(), - storeLogSubject); + + if(messageStore instanceof DurableConfigurationStore) + { + DurableConfigurationStore durableConfigurationStore = (DurableConfigurationStore) messageStore; + + durableConfigurationStore.configureConfigStore(this.getName(), + recoveryHandler, + hostConfig.getStoreConfiguration(), + storeLogSubject); + + _durableConfigurationStore = durableConfigurationStore; + } messageStore.configureMessageStore(this.getName(), recoveryHandler, @@ -405,7 +417,8 @@ public class VirtualHostImpl implements VirtualHost storeLogSubject); _messageStore = messageStore; - _durableConfigurationStore = messageStore; + + } private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException @@ -553,11 +566,6 @@ public class VirtualHostImpl implements VirtualHost return _messageStore; } - public TransactionLog getTransactionLog() - { - return _messageStore; - } - public DurableConfigurationStore getDurableConfigurationStore() { return _durableConfigurationStore; diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java index ea2fe90da6..24c790d799 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java @@ -72,7 +72,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase /** * Not used in this test, just there to stub out the routing calls */ - private MessageStore _store = new MemoryMessageStore(); + private MemoryMessageStore _store = new MemoryMessageStore(); BindingFactory bindingFactory = new BindingFactory(new DurableConfigurationStore.Source() @@ -310,7 +310,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase * @throws AMQException */ @Override - public void enqueue(ServerMessage msg, PostEnqueueAction action) throws AMQException + public void enqueue(ServerMessage msg, boolean sync, PostEnqueueAction action) throws AMQException { messages.add( new HeadersExchangeTest.Message((AMQMessage) msg)); final QueueEntry queueEntry = new QueueEntry() @@ -318,47 +318,47 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase public AMQQueue getQueue() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public AMQMessage getMessage() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public long getSize() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public boolean getDeliveredToConsumer() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean expired() throws AMQException { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isAvailable() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isAcquired() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean acquire() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean acquire(Subscription sub) { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean delete() @@ -373,17 +373,17 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase public boolean acquiredBySubscription() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isAcquiredBy(Subscription subscription) { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public void release() { - //To change body of implemented methods use File | Settings | File Templates. + } public boolean releaseButRetain() @@ -393,82 +393,82 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase public boolean immediateAndNotDelivered() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public void setRedelivered() { - //To change body of implemented methods use File | Settings | File Templates. + } public AMQMessageHeader getMessageHeader() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public boolean isPersistent() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isRedelivered() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public Subscription getDeliveredSubscription() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void reject() { - //To change body of implemented methods use File | Settings | File Templates. + } public boolean isRejectedBy(long subscriptionId) { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public void dequeue() { - //To change body of implemented methods use File | Settings | File Templates. + } public void dispose() { - //To change body of implemented methods use File | Settings | File Templates. + } public void discard() { - //To change body of implemented methods use File | Settings | File Templates. + } public void routeToAlternate() { - //To change body of implemented methods use File | Settings | File Templates. + } public boolean isQueueDeleted() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public void addStateChangeListener(StateChangeListener listener) { - //To change body of implemented methods use File | Settings | File Templates. + } public boolean removeStateChangeListener(StateChangeListener listener) { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public int compareTo(final QueueEntry o) { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public boolean isDequeued() diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index 2ce43052d9..d5f8ef3d54 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java @@ -64,17 +64,17 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest ArrayList<QueueEntry> msgs = _subscription.getMessages(); try { - assertEquals(new Long(1L), msgs.get(0).getMessage().getMessageNumber()); - assertEquals(new Long(6L), msgs.get(1).getMessage().getMessageNumber()); - assertEquals(new Long(8L), msgs.get(2).getMessage().getMessageNumber()); + assertEquals(1L, msgs.get(0).getMessage().getMessageNumber()); + assertEquals(6L, msgs.get(1).getMessage().getMessageNumber()); + assertEquals(8L, msgs.get(2).getMessage().getMessageNumber()); - assertEquals(new Long(2L), msgs.get(3).getMessage().getMessageNumber()); - assertEquals(new Long(5L), msgs.get(4).getMessage().getMessageNumber()); - assertEquals(new Long(7L), msgs.get(5).getMessage().getMessageNumber()); + assertEquals(2L, msgs.get(3).getMessage().getMessageNumber()); + assertEquals(5L, msgs.get(4).getMessage().getMessageNumber()); + assertEquals(7L, msgs.get(5).getMessage().getMessageNumber()); - assertEquals(new Long(3L), msgs.get(6).getMessage().getMessageNumber()); - assertEquals(new Long(4L), msgs.get(7).getMessage().getMessageNumber()); - assertEquals(new Long(9L), msgs.get(8).getMessage().getMessageNumber()); + assertEquals(3L, msgs.get(6).getMessage().getMessageNumber()); + assertEquals(4L, msgs.get(7).getMessage().getMessageNumber()); + assertEquals(9L, msgs.get(8).getMessage().getMessageNumber()); } catch (AssertionFailedError afe) { diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index 0daf79122c..f43af447ff 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -168,22 +168,22 @@ public class MockAMQQueue implements AMQQueue public UUID getId() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public QueueConfigType getConfigType() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public ConfiguredObject getParent() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public boolean isDurable() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isAutoDelete() @@ -199,7 +199,7 @@ public class MockAMQQueue implements AMQQueue public AMQShortString getOwner() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void setVirtualHost(VirtualHost virtualhost) @@ -219,22 +219,22 @@ public class MockAMQQueue implements AMQQueue public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException { - //To change body of implemented methods use File | Settings | File Templates. + } public void unregisterSubscription(Subscription subscription) throws AMQException { - //To change body of implemented methods use File | Settings | File Templates. + } public int getConsumerCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public int getActiveConsumerCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public boolean hasExclusiveSubscriber() @@ -244,37 +244,37 @@ public class MockAMQQueue implements AMQQueue public boolean isUnused() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isEmpty() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public int getMessageCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public int getUndeliveredMessageCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public long getQueueDepth() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public long getReceivedMessageCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public long getOldestMessageArrivalTime() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public boolean isDeleted() @@ -297,59 +297,58 @@ public class MockAMQQueue implements AMQQueue } + public void enqueue(ServerMessage message, boolean sync, PostEnqueueAction action) throws AMQException + { + } + public void requeue(QueueEntry entry) { - //To change body of implemented methods use File | Settings | File Templates. } public void requeue(QueueEntryImpl storeContext, Subscription subscription) { - //To change body of implemented methods use File | Settings | File Templates. } public void dequeue(QueueEntry entry, Subscription sub) { - //To change body of implemented methods use File | Settings | File Templates. } public boolean resend(QueueEntry entry, Subscription subscription) throws AMQException { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public void addQueueDeleteTask(Task task) { - //To change body of implemented methods use File | Settings | File Templates. } public void removeQueueDeleteTask(final Task task) { - //To change body of implemented methods use File | Settings | File Templates. } public List<QueueEntry> getMessagesOnTheQueue() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public List<Long> getMessagesOnTheQueue(int num) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public List<Long> getMessagesOnTheQueue(int num, int offest) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public QueueEntry getMessageOnTheQueue(long messageId) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public List<QueueEntry> getMessagesRangeOnTheQueue(long fromPosition, long toPosition) @@ -359,132 +358,123 @@ public class MockAMQQueue implements AMQQueue 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, ServerTransaction storeContext) { - //To change body of implemented methods use File | Settings | File Templates. + } public void removeMessagesFromQueue(long fromMessageId, long toMessageId) { - //To change body of implemented methods use File | Settings | File Templates. + } public long getMaximumMessageSize() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setMaximumMessageSize(long value) { - //To change body of implemented methods use File | Settings | File Templates. + } public long getMaximumMessageCount() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setMaximumMessageCount(long value) { - //To change body of implemented methods use File | Settings | File Templates. + } public long getMaximumQueueDepth() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setMaximumQueueDepth(long value) { - //To change body of implemented methods use File | Settings | File Templates. + } public long getMaximumMessageAge() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setMaximumMessageAge(long maximumMessageAge) { - //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean getBlockOnQueueFull() - { - return false; - } - - public void setBlockOnQueueFull(boolean block) - { + } public long getMinimumAlertRepeatGap() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void deleteMessageFromTop() { - //To change body of implemented methods use File | Settings | File Templates. + } public long clearQueue() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void checkMessageStatus() throws AMQException { - //To change body of implemented methods use File | Settings | File Templates. + } public Set<NotificationCheck> getNotificationChecks() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void flushSubscription(Subscription sub) throws AMQException { - //To change body of implemented methods use File | Settings | File Templates. + } public void deliverAsync(Subscription sub) { - //To change body of implemented methods use File | Settings | File Templates. + } public void deliverAsync() { - //To change body of implemented methods use File | Settings | File Templates. + } public void stop() { - //To change body of implemented methods use File | Settings | File Templates. + } public boolean isExclusive() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } 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 Map<String, Object> getArguments() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void checkCapacity(AMQChannel channel) @@ -493,12 +483,12 @@ public class MockAMQQueue implements AMQQueue public ManagedObject getManagedObject() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public int compareTo(AMQQueue o) { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setMinimumAlertRepeatGap(long value) @@ -508,22 +498,22 @@ public class MockAMQQueue implements AMQQueue public long getCapacity() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setCapacity(long capacity) { - //To change body of implemented methods use File | Settings | File Templates. + } public long getFlowResumeCapacity() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return 0; } public void setFlowResumeCapacity(long flowResumeCapacity) { - //To change body of implemented methods use File | Settings | File Templates. + } public void configure(ConfigurationPlugin config) @@ -533,7 +523,7 @@ public class MockAMQQueue implements AMQQueue public ConfigurationPlugin getConfiguration() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public AuthorizationHolder getAuthorizationHolder() diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java index 78ed3e9f34..75f633f2af 100755 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.framing.FieldTable; 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; @@ -97,7 +96,17 @@ public class MockStoredMessage implements StoredMessage<MessageMetaData> return src.limit(); } - public TransactionLog.StoreFuture flushToStore() + + + public ByteBuffer getContent(int offsetInMessage, int size) + { + ByteBuffer buf = ByteBuffer.allocate(size); + getContent(offsetInMessage, buf); + buf.position(0); + return buf; + } + + public MessageStore.StoreFuture flushToStore() { return MessageStore.IMMEDIATE_FUTURE; } diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java index 7a3f6f701c..cf910208e7 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java @@ -164,7 +164,7 @@ public abstract class QueueEntryListTestBase extends TestCase final QueueEntry head = getTestList().getHead(); assertNull("Head entry should not contain an actual message", head.getMessage()); assertEquals("Unexpected message id for first list entry", getExpectedFirstMsgId(), getTestList().next(head) - .getMessage().getMessageNumber().longValue()); + .getMessage().getMessageNumber()); } /** diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index 6c7094cac0..28d52f4fd1 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -649,9 +649,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void onRollback() { } - }); - - + }, 0L); // Check that it is enqueued AMQQueue data = _store.getMessages().get(1L); diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java index f3ba6a5495..a873739ca7 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java @@ -162,8 +162,8 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase while (entry != null) { assertFalse("Entry " + entry.getMessage().getMessageNumber() + " should not have been deleted", entry.isDeleted()); - assertNotNull("QueueEntry was not found in the list of remaining entries", - remainingMessages.get(entry.getMessage().getMessageNumber().intValue())); + assertNotNull("QueueEntry "+entry.getMessage().getMessageNumber()+" was not found in the list of remaining entries " + remainingMessages, + remainingMessages.get((int)(entry.getMessage().getMessageNumber()))); count++; entry = entry.getNextNode(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java index eca845644e..34ad0e5668 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java @@ -317,7 +317,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase assertEquals("Sorted queue entry value is not as expected", expectedSortKey, entry.getMessage().getMessageHeader().getHeader("KEY")); assertEquals("Sorted queue entry id is not as expected", - Long.valueOf(expectedMessageId), entry.getMessage().getMessageNumber()); + expectedMessageId, entry.getMessage().getMessageNumber()); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java index 1d0a9d6316..90adaa1319 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -558,7 +558,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase /** * Delete the Store Environment path * - * @param configuration The configuration that contains the store environment path. + * @param environmentPath The configuration that contains the store environment path. */ private void cleanup(File environmentPath) { @@ -636,7 +636,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase { //To change body of implemented methods use File | Settings | File Templates. } - }); + }, 0L); } } @@ -710,7 +710,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase if (queue.isDurable() && !queue.isAutoDelete()) { - getVirtualHost().getMessageStore().createQueue(queue, queueArguments); + getVirtualHost().getDurableConfigurationStore().createQueue(queue, queueArguments); } } catch (AMQException e) @@ -754,7 +754,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase getVirtualHost().getExchangeRegistry().registerExchange(exchange); if (durable) { - getVirtualHost().getMessageStore().createExchange(exchange); + getVirtualHost().getDurableConfigurationStore().createExchange(exchange); } } catch (AMQException e) diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java index 5ff84557d8..44006df517 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java @@ -26,6 +26,7 @@ import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.ContentChunk; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.exchange.Exchange; @@ -42,18 +43,11 @@ import java.nio.ByteBuffer; */ public class SkeletonMessageStore implements MessageStore { - private final AtomicLong _messageId = new AtomicLong(1); - - public void configure(String base, Configuration 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, @@ -61,7 +55,6 @@ public class SkeletonMessageStore implements MessageStore Configuration config, LogSubject logSubject) throws Exception { - //To change body of implemented methods use File | Settings | File Templates. } public void close() throws Exception @@ -70,31 +63,28 @@ 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. + return null; } - public void removeMessage(Long messageId) - { - } public void createExchange(Exchange exchange) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public void removeExchange(Exchange exchange) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public void createQueue(AMQQueue queue) throws AMQStoreException @@ -105,63 +95,11 @@ public class SkeletonMessageStore implements MessageStore { } - - - - public List<AMQQueue> createQueues() throws AMQException - { - return null; - } - - public Long getNewMessageId() - { - return _messageId.getAndIncrement(); - } - - public void storeContentBodyChunk( - Long messageId, - int index, - ContentChunk contentBody, - boolean lastContentBody) throws AMQException - { - - } - - public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException - { - - } - - public MessageMetaData getMessageMetaData(Long messageId) throws AMQException - { - return null; - } - - public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException - { - return null; - } - 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. - } - public void removeQueue(final AMQQueue queue) throws AMQStoreException { @@ -172,7 +110,7 @@ public class SkeletonMessageStore implements MessageStore Configuration storeConfiguration, LogSubject logSubject) throws Exception { - //To change body of implemented methods use File | Settings | File Templates. + } public Transaction newTransaction() @@ -180,19 +118,19 @@ public class SkeletonMessageStore implements MessageStore return new Transaction() { - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public void commitTran() throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } public StoreFuture commitTranAsync() throws AMQStoreException @@ -213,7 +151,7 @@ public class SkeletonMessageStore implements MessageStore public void abortTran() throws AMQStoreException { - //To change body of implemented methods use File | Settings | File Templates. + } }; } diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java index 4dea13d391..fa698f4cf8 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java @@ -82,6 +82,12 @@ public class TestMemoryMessageStore extends MemoryMessageStore return _storedMessage.getContent(offsetInMessage, dst); } + + public ByteBuffer getContent(int offsetInMessage, int size) + { + return _storedMessage.getContent(offsetInMessage, size); + } + public StoreFuture flushToStore() { return _storedMessage.flushToStore(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java index 3593297a05..3804d0dc8e 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java @@ -25,6 +25,8 @@ import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; /** @@ -66,14 +68,14 @@ public class TestableMemoryMessageStore extends MemoryMessageStore private class TestableTransaction implements Transaction { - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - getMessages().put(messageId, (AMQQueue)queue); + getMessages().put(message.getMessageNumber(), (AMQQueue)queue); } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - getMessages().remove(messageId); + getMessages().remove(message.getMessageNumber()); } public void commitTran() throws AMQStoreException @@ -143,6 +145,12 @@ public class TestableMemoryMessageStore extends MemoryMessageStore return _storedMessage.getContent(offsetInMessage, dst); } + + public ByteBuffer getContent(int offsetInMessage, int size) + { + return _storedMessage.getContent(offsetInMessage, size); + } + public StoreFuture flushToStore() { return _storedMessage.flushToStore(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java index 9afed49922..98484db264 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; import org.apache.qpid.server.queue.MockQueueEntry; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState; import org.apache.qpid.test.utils.QpidTestCase; @@ -44,7 +44,7 @@ public class AutoCommitTransactionTest extends QpidTestCase { private ServerTransaction _transaction = null; // Class under test - private TransactionLog _transactionLog; + private MessageStore _transactionLog; private AMQQueue _queue; private List<AMQQueue> _queues; private Collection<QueueEntry> _queueEntries; @@ -137,7 +137,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(false); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action); + _transaction.enqueue(_queues, _message, _action, 0L); assertEquals("Enqueue of non-persistent message must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -157,7 +157,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action); + _transaction.enqueue(_queues, _message, _action, 0L); assertEquals("Enqueue of persistent message to non-durable queues must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -175,7 +175,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, true, false, true}); - _transaction.enqueue(_queues, _message, _action); + _transaction.enqueue(_queues, _message, _action, 0L); assertEquals("Enqueue of persistent message to durable/non-durable queues must cause messages to be enqueued", 2, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.COMMITTED, _storeTransaction.getState()); @@ -198,7 +198,7 @@ public class AutoCommitTransactionTest extends QpidTestCase try { - _transaction.enqueue(_queues, _message, _action); + _transaction.enqueue(_queues, _message, _action, 0L); fail("Exception not thrown"); } catch (RuntimeException re) diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java index e81fd8e3f1..484beb8fb4 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; import org.apache.qpid.server.queue.MockQueueEntry; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.TransactionLog; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState; import org.apache.qpid.test.utils.QpidTestCase; @@ -51,7 +51,7 @@ public class LocalTransactionTest extends QpidTestCase private MockAction _action1; private MockAction _action2; private MockStoreTransaction _storeTransaction; - private TransactionLog _transactionLog; + private MessageStore _transactionLog; @Override @@ -140,7 +140,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(false); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action1); + _transaction.enqueue(_queues, _message, _action1, 0L); assertEquals("Enqueue of non-persistent message must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -156,7 +156,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action1); + _transaction.enqueue(_queues, _message, _action1, 0L); assertEquals("Enqueue of persistent message to non-durable queues must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -173,7 +173,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, true, false, true}); - _transaction.enqueue(_queues, _message, _action1); + _transaction.enqueue(_queues, _message, _action1, 0L); assertEquals("Enqueue of persistent message to durable/non-durable queues must cause messages to be enqueued", 2, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.STARTED, _storeTransaction.getState()); @@ -196,7 +196,7 @@ public class LocalTransactionTest extends QpidTestCase try { - _transaction.enqueue(_queues, _message, _action1); + _transaction.enqueue(_queues, _message, _action1, 0L); fail("Exception not thrown"); } catch (RuntimeException re) diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java index 422105e410..f3d71c6dea 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java @@ -27,6 +27,7 @@ import org.apache.qpid.server.configuration.SessionConfig; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.StoredMessage; /** * Mock Server Message allowing its persistent flag to be controlled from test. @@ -81,6 +82,11 @@ class MockServerMessage implements ServerMessage throw new NotImplementedException(); } + public StoredMessage getStoredMessage() + { + throw new NotImplementedException(); + } + public long getExpiration() { throw new NotImplementedException(); @@ -91,12 +97,18 @@ class MockServerMessage implements ServerMessage throw new NotImplementedException(); } + + public ByteBuffer getContent(int offset, int size) + { + throw new NotImplementedException(); + } + public long getArrivalTime() { throw new NotImplementedException(); } - public Long getMessageNumber() + public long getMessageNumber() { return 0L; } diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java index ff372532ac..bf8fda307a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java @@ -24,11 +24,11 @@ import org.apache.commons.configuration.Configuration; import org.apache.commons.lang.NotImplementedException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.store.TransactionLog; -import org.apache.qpid.server.store.TransactionLogRecoveryHandler; -import org.apache.qpid.server.store.TransactionLogResource; -import org.apache.qpid.server.store.TransactionLog.StoreFuture; -import org.apache.qpid.server.store.TransactionLog.Transaction; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.*; +import org.apache.qpid.server.store.MessageStore.StoreFuture; +import org.apache.qpid.server.store.MessageStore.Transaction; /** * Mock implementation of a (Store) Transaction allow its state to be observed. @@ -61,7 +61,7 @@ class MockStoreTransaction implements Transaction return _state; } - public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { if (_throwExceptionOnQueueOp) { @@ -82,7 +82,7 @@ class MockStoreTransaction implements Transaction return _numberOfEnqueuedMessages; } - public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { if (_throwExceptionOnQueueOp) { @@ -107,10 +107,33 @@ class MockStoreTransaction implements Transaction _state = TransactionState.ABORTED; } - public static TransactionLog createTestTransactionLog(final MockStoreTransaction storeTransaction) + public static MessageStore createTestTransactionLog(final MockStoreTransaction storeTransaction) { - return new TransactionLog() + return new MessageStore() { + public void configureMessageStore(final String name, + final MessageStoreRecoveryHandler recoveryHandler, + final Configuration config, + final LogSubject logSubject) throws Exception + { + //TODO. + } + + public void close() throws Exception + { + //TODO. + } + + public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(final T metaData) + { + return null; //TODO. + } + + public boolean isPersistent() + { + return false; //TODO. + } + public void configureTransactionLog(String name, TransactionLogRecoveryHandler recoveryHandler, Configuration storeConfiguration, LogSubject logSubject) throws Exception { diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index 7aa314bf22..153371c8d9 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java @@ -41,7 +41,6 @@ import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TransactionLog; public class MockVirtualHost implements VirtualHost { @@ -159,10 +158,6 @@ public class MockVirtualHost implements VirtualHost return null; } - public TransactionLog getTransactionLog() - { - return null; - } public void removeBrokerConnection(BrokerLink brokerLink) { diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 756b5cacb0..8dc36673dc 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -30,7 +30,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; @@ -60,23 +59,7 @@ import org.apache.qpid.filter.MessageFilter; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.transport.ExchangeBoundResult; -import org.apache.qpid.transport.ExchangeQueryResult; -import org.apache.qpid.transport.ExecutionErrorCode; -import org.apache.qpid.transport.ExecutionException; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageCreditUnit; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.QueueQueryResult; -import org.apache.qpid.transport.Range; -import org.apache.qpid.transport.RangeSet; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.SessionException; -import org.apache.qpid.transport.SessionListener; -import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.*; import org.apache.qpid.util.Serial; import org.apache.qpid.util.Strings; import org.slf4j.Logger; @@ -141,13 +124,13 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic private long maxAckDelay = Long.getLong("qpid.session.max_ack_delay", 1000); private TimerTask flushTask = null; - private RangeSet unacked = new RangeSet(); + private RangeSet unacked = RangeSetFactory.createRangeSet(); private int unackedCount = 0; /** * Used to store the range of in tx messages */ - private final RangeSet _txRangeSet = new RangeSet(); + private final RangeSet _txRangeSet = RangeSetFactory.createRangeSet(); private int _txSize = 0; //--- constructors @@ -460,7 +443,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic public void sendRecover() throws AMQException, FailoverException { // release all unacked messages - RangeSet all = new RangeSet(); + RangeSet all = RangeSetFactory.createRangeSet(); RangeSet delivered = gatherRangeSet(_unacknowledgedMessageTags); RangeSet prefetched = gatherRangeSet(_prefetchedMessageTags); for (Iterator<Range> deliveredIter = delivered.iterator(); deliveredIter.hasNext();) @@ -483,7 +466,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic private RangeSet gatherRangeSet(ConcurrentLinkedQueue<Long> messageTags) { - RangeSet ranges = new RangeSet(); + RangeSet ranges = RangeSetFactory.createRangeSet(); while (true) { Long tag = messageTags.poll(); @@ -518,7 +501,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic public void rejectMessage(long deliveryTag, boolean requeue) { // The value of requeue is always true - RangeSet ranges = new RangeSet(); + RangeSet ranges = RangeSetFactory.createRangeSet(); ranges.add((int) deliveryTag); flushProcessed(ranges, false); if (requeue) diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java index 96df463481..ab3a0284a6 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java @@ -21,6 +21,8 @@ package org.apache.qpid.client; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.ArrayList; import java.util.Map; @@ -80,7 +82,7 @@ import org.apache.qpid.transport.TransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> +public class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> { /** Used for debugging. */ private static final Logger _logger = LoggerFactory.getLogger(AMQSession.class); @@ -96,8 +98,8 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B * @param defaultPrefetchHighMark The maximum number of messages to prefetched before suspending the session. * @param defaultPrefetchLowMark The number of prefetched messages at which to resume the session. */ - AMQSession_0_8(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode, - MessageFactoryRegistry messageFactoryRegistry, int defaultPrefetchHighMark, int defaultPrefetchLowMark) + protected AMQSession_0_8(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode, + MessageFactoryRegistry messageFactoryRegistry, int defaultPrefetchHighMark, int defaultPrefetchLowMark) { super(con,channelId,transacted,acknowledgeMode,messageFactoryRegistry,defaultPrefetchHighMark,defaultPrefetchLowMark); @@ -150,7 +152,7 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B _logger.debug("Sending ack for delivery tag " + deliveryTag + " on channel " + _channelId); } - getProtocolHandler().writeFrame(ackFrame); + getProtocolHandler().writeFrame(ackFrame, !getTransacted()); _unacknowledgedMessageTags.remove(deliveryTag); } @@ -512,7 +514,7 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B // Bounced message is processed here, away from the mina thread AbstractJMSMessage bouncedMessage = _messageFactoryRegistry.createMessage(0, false, msg.getExchange(), - msg.getRoutingKey(), msg.getContentHeader(), msg.getBodies()); + msg.getRoutingKey(), msg.getContentHeader(), msg.getBodies(),_queueDestinationCache,_topicDestinationCache); AMQConstant errorCode = AMQConstant.getConstant(msg.getReplyCode()); AMQShortString reason = msg.getReplyText(); _logger.debug("Message returned with error code " + errorCode + " (" + reason + ")"); @@ -572,6 +574,16 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B }, _connection).execute(); } + public DestinationCache<AMQQueue> getQueueDestinationCache() + { + return _queueDestinationCache; + } + + public DestinationCache<AMQTopic> getTopicDestinationCache() + { + return _topicDestinationCache; + } + class QueueDeclareOkHandler extends SpecificMethodFrameListener { @@ -613,12 +625,12 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B return okHandler._messageCount; } - protected final boolean tagLE(long tag1, long tag2) + protected boolean tagLE(long tag1, long tag2) { return tag1 <= tag2; } - protected final boolean updateRollbackMark(long currentMark, long deliveryTag) + protected boolean updateRollbackMark(long currentMark, long deliveryTag) { return false; } @@ -695,4 +707,55 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B return null; } } + + public abstract static class DestinationCache<T extends AMQDestination> + { + private final Map<AMQShortString, Map<AMQShortString, T>> cache = new HashMap<AMQShortString, Map<AMQShortString, T>>(); + + public T getDestination(AMQShortString exchangeName, AMQShortString routingKey) + { + Map<AMQShortString, T> routingMap = cache.get(exchangeName); + if(routingMap == null) + { + routingMap = new LinkedHashMap<AMQShortString, T>() + { + + protected boolean removeEldestEntry(Map.Entry<AMQShortString, T> eldest) + { + return size() >= 200; + } + }; + cache.put(exchangeName,routingMap); + } + T destination = routingMap.get(routingKey); + if(destination == null) + { + destination = newDestination(exchangeName, routingKey); + routingMap.put(routingKey,destination); + } + return destination; + } + + protected abstract T newDestination(AMQShortString exchangeName, AMQShortString routingKey); + } + + private static class TopicDestinationCache extends DestinationCache<AMQTopic> + { + protected AMQTopic newDestination(AMQShortString exchangeName, AMQShortString routingKey) + { + return new AMQTopic(exchangeName, routingKey, null); + } + } + + private static class QueueDestinationCache extends DestinationCache<AMQQueue> + { + protected AMQQueue newDestination(AMQShortString exchangeName, AMQShortString routingKey) + { + return new AMQQueue(exchangeName, routingKey, routingKey); + } + } + + private final TopicDestinationCache _topicDestinationCache = new TopicDestinationCache(); + private final QueueDestinationCache _queueDestinationCache = new QueueDestinationCache(); + } diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java index bb277887aa..a49e31ce8c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java @@ -272,10 +272,8 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM */ private void acknowledgeMessage(final AbstractJMSMessage message) throws AMQException { - final RangeSet ranges = new RangeSet(); - ranges.add((int) message.getDeliveryTag()); _0_10session.messageAcknowledge - (ranges, + (Range.newInstance((int) message.getDeliveryTag()), _acknowledgeMode != org.apache.qpid.jms.Session.NO_ACKNOWLEDGE); final AMQException amqe = _0_10session.getCurrentException(); @@ -294,9 +292,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM */ private void flushUnwantedMessage(final AbstractJMSMessage message) throws AMQException { - final RangeSet ranges = new RangeSet(); - ranges.add((int) message.getDeliveryTag()); - _0_10session.flushProcessed(ranges,false); + _0_10session.flushProcessed(Range.newInstance((int) message.getDeliveryTag()),false); final AMQException amqe = _0_10session.getCurrentException(); if (amqe != null) @@ -315,10 +311,8 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM private boolean acquireMessage(final AbstractJMSMessage message) throws AMQException { boolean result = false; - final RangeSet ranges = new RangeSet(); - ranges.add((int) message.getDeliveryTag()); - final Acquired acq = _0_10session.getQpidSession().messageAcquire(ranges).get(); + final Acquired acq = _0_10session.getQpidSession().messageAcquire(Range.newInstance((int)message.getDeliveryTag())).get(); final RangeSet acquired = acq.getTransfers(); if (acquired != null && acquired.size() > 0) @@ -451,7 +445,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM { if (_synchronousQueue.size() > 0) { - RangeSet ranges = new RangeSet(); + RangeSet ranges = RangeSetFactory.createRangeSet(); Iterator iterator = _synchronousQueue.iterator(); while (iterator.hasNext()) { diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java index efcbfd5532..b2f4fcef84 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java @@ -38,11 +38,13 @@ import org.slf4j.LoggerFactory; public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMessage_0_8> { protected final Logger _logger = LoggerFactory.getLogger(getClass()); + private AMQSession_0_8.DestinationCache<AMQTopic> _topicDestinationCache; + private AMQSession_0_8.DestinationCache<AMQQueue> _queueDestinationCache; private final RejectBehaviour _rejectBehaviour; protected BasicMessageConsumer_0_8(int channelId, AMQConnection connection, AMQDestination destination, - String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session, + String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession_0_8 session, AMQProtocolHandler protocolHandler, FieldTable rawSelector, int prefetchHigh, int prefetchLow, boolean exclusive, int acknowledgeMode, boolean browseOnly, boolean autoClose) throws JMSException { @@ -60,6 +62,9 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMe consumerArguments.put(AMQPFilterTypes.NO_CONSUME.getValue(), Boolean.TRUE); } + _topicDestinationCache = session.getTopicDestinationCache(); + _queueDestinationCache = session.getQueueDestinationCache(); + if (destination.getRejectBehaviour() != null) { _rejectBehaviour = destination.getRejectBehaviour(); @@ -100,7 +105,8 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMe return _messageFactory.createMessage(messageFrame.getDeliveryTag(), messageFrame.isRedelivered(), messageFrame.getExchange(), - messageFrame.getRoutingKey(), messageFrame.getContentHeader(), messageFrame.getBodies()); + messageFrame.getRoutingKey(), messageFrame.getContentHeader(), messageFrame.getBodies(), + _queueDestinationCache, _topicDestinationCache); } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java index 6237234c4d..33ca584b34 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java @@ -48,7 +48,10 @@ public class BasicDeliverMethodHandler implements StateAwareMethodListener<Basic body.getExchange(), body.getRoutingKey(), body.getRedelivered()); - _logger.debug("New JmsDeliver method received:" + session); + if(_logger.isDebugEnabled()) + { + _logger.debug("New JmsDeliver method received:" + session); + } session.unprocessedMessageReceived(channelId, msg); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java index f360b546b2..179ebd66d1 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java @@ -124,7 +124,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate */ public static void updateExchangeTypeMapping(Header header, org.apache.qpid.transport.Session session) { - DeliveryProperties deliveryProps = header.get(DeliveryProperties.class); + DeliveryProperties deliveryProps = header.getDeliveryProperties(); if (deliveryProps != null) { String exchange = deliveryProps.getExchange(); @@ -132,7 +132,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate } - MessageProperties msgProps = header.get(MessageProperties.class); + MessageProperties msgProps = header.getMessageProperties(); if (msgProps != null && msgProps.getReplyTo() != null) { String exchange = msgProps.getReplyTo().getExchange(); diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java index 9ab03412fe..ab7061c382 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java @@ -31,12 +31,7 @@ import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageNotWriteableException; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.client.CustomJMSXProperty; -import org.apache.qpid.client.JMSAMQException; +import org.apache.qpid.client.*; import org.apache.qpid.collections.ReferenceMap; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; @@ -81,7 +76,8 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate // Used when generating a received message object protected AMQMessageDelegate_0_8(long deliveryTag, BasicContentHeaderProperties contentHeader, AMQShortString exchange, - AMQShortString routingKey) + AMQShortString routingKey, AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache, + AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache) { this(contentHeader, deliveryTag); @@ -95,10 +91,10 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate switch (type.intValue()) { case AMQDestination.QUEUE_TYPE: - dest = new AMQQueue(exchange, routingKey, routingKey); + dest = queueDestinationCache.getDestination(exchange, routingKey); break; case AMQDestination.TOPIC_TYPE: - dest = new AMQTopic(exchange, routingKey, null); + dest = topicDestinationCache.getDestination(exchange, routingKey); break; default: // Use the generateDestination method @@ -133,10 +129,66 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate { if (messageId != null) { - getContentHeaderProperties().setMessageId("ID:" + messageId); + getContentHeaderProperties().setMessageId(asShortStringMsgId(messageId)); } } + private static final byte[] HEX_DIGITS = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x61,0x62,0x63,0x64,0x65,0x66}; + + private static AMQShortString asShortStringMsgId(UUID messageId) + { + long msb = messageId.getMostSignificantBits(); + long lsb = messageId.getLeastSignificantBits(); + + byte[] messageIdBytes = new byte[39]; + messageIdBytes[0] = (byte) 'I'; + messageIdBytes[1] = (byte) 'D'; + messageIdBytes[2] = (byte) ':'; + + messageIdBytes[3] = HEX_DIGITS[(int)((msb >> 60) & 0xFl)]; + messageIdBytes[4] = HEX_DIGITS[(int)((msb >> 56) & 0xFl)]; + messageIdBytes[5] = HEX_DIGITS[(int)((msb >> 52) & 0xFl)]; + messageIdBytes[6] = HEX_DIGITS[(int)((msb >> 48) & 0xFl)]; + messageIdBytes[7] = HEX_DIGITS[(int)((msb >> 44) & 0xFl)]; + messageIdBytes[8] = HEX_DIGITS[(int)((msb >> 40) & 0xFl)]; + messageIdBytes[9] = HEX_DIGITS[(int)((msb >> 36) & 0xFl)]; + messageIdBytes[10] = HEX_DIGITS[(int)((msb >> 32) & 0xFl)]; + + messageIdBytes[11] = (byte) '-'; + messageIdBytes[12] = HEX_DIGITS[(int)((msb >> 28) & 0xFl)]; + messageIdBytes[13] = HEX_DIGITS[(int)((msb >> 24) & 0xFl)]; + messageIdBytes[14] = HEX_DIGITS[(int)((msb >> 20) & 0xFl)]; + messageIdBytes[15] = HEX_DIGITS[(int)((msb >> 16) & 0xFl)]; + messageIdBytes[16] = (byte) '-'; + messageIdBytes[17] = HEX_DIGITS[(int)((msb >> 12) & 0xFl)]; + messageIdBytes[18] = HEX_DIGITS[(int)((msb >> 8) & 0xFl)]; + messageIdBytes[19] = HEX_DIGITS[(int)((msb >> 4) & 0xFl)]; + messageIdBytes[20] = HEX_DIGITS[(int)(msb & 0xFl)]; + messageIdBytes[21] = (byte) '-'; + + messageIdBytes[22] = HEX_DIGITS[(int)((lsb >> 60) & 0xFl)]; + messageIdBytes[23] = HEX_DIGITS[(int)((lsb >> 56) & 0xFl)]; + messageIdBytes[24] = HEX_DIGITS[(int)((lsb >> 52) & 0xFl)]; + messageIdBytes[25] = HEX_DIGITS[(int)((lsb >> 48) & 0xFl)]; + + messageIdBytes[26] = (byte) '-'; + + messageIdBytes[27] = HEX_DIGITS[(int)((lsb >> 44) & 0xFl)]; + messageIdBytes[28] = HEX_DIGITS[(int)((lsb >> 40) & 0xFl)]; + messageIdBytes[29] = HEX_DIGITS[(int)((lsb >> 36) & 0xFl)]; + messageIdBytes[30] = HEX_DIGITS[(int)((lsb >> 32) & 0xFl)]; + messageIdBytes[31] = HEX_DIGITS[(int)((lsb >> 28) & 0xFl)]; + messageIdBytes[32] = HEX_DIGITS[(int)((lsb >> 24) & 0xFl)]; + messageIdBytes[33] = HEX_DIGITS[(int)((lsb >> 20) & 0xFl)]; + messageIdBytes[34] = HEX_DIGITS[(int)((lsb >> 16) & 0xFl)]; + messageIdBytes[35] = HEX_DIGITS[(int)((lsb >> 12) & 0xFl)]; + messageIdBytes[36] = HEX_DIGITS[(int)((lsb >> 8) & 0xFl)]; + messageIdBytes[37] = HEX_DIGITS[(int)((lsb >> 4) & 0xFl)]; + messageIdBytes[38] = HEX_DIGITS[(int)(lsb & 0xFl)]; + + return new AMQShortString(messageIdBytes,0,39); + } public long getJMSTimestamp() throws JMSException { @@ -413,7 +465,7 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate } checkWritableProperties(); - getJmsHeaders().setByte(propertyName, new Byte(b)); + getJmsHeaders().setByte(propertyName, b); } public void setShortProperty(String propertyName, short i) throws JMSException @@ -424,13 +476,13 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate } checkWritableProperties(); - getJmsHeaders().setShort(propertyName, new Short(i)); + getJmsHeaders().setShort(propertyName, i); } public void setIntProperty(String propertyName, int i) throws JMSException { checkWritableProperties(); - getJmsHeaders().setInteger(propertyName, new Integer(i)); + getJmsHeaders().setInteger(propertyName, i); } public void setLongProperty(String propertyName, long l) throws JMSException @@ -441,7 +493,7 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate } checkWritableProperties(); - getJmsHeaders().setLong(propertyName, new Long(l)); + getJmsHeaders().setLong(propertyName, l); } public void setFloatProperty(String propertyName, float f) throws JMSException @@ -452,7 +504,7 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate } checkWritableProperties(); - getJmsHeaders().setFloat(propertyName, new Float(f)); + getJmsHeaders().setFloat(propertyName, f); } public void setDoubleProperty(String propertyName, double v) throws JMSException diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java index 967a1fb49f..16b71db77e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java @@ -21,6 +21,9 @@ package org.apache.qpid.client.message; import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession_0_8; +import org.apache.qpid.client.AMQTopic; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentBody; import org.apache.qpid.framing.ContentHeaderBody; @@ -44,7 +47,9 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory protected AbstractJMSMessage create08MessageWithBody(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange, AMQShortString routingKey, - List bodies) throws AMQException + List bodies, + AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache, + AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache) throws AMQException { ByteBuffer data; final boolean debug = _logger.isDebugEnabled(); @@ -99,7 +104,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory AMQMessageDelegate delegate = new AMQMessageDelegate_0_8(messageNbr, (BasicContentHeaderProperties) contentHeader.getProperties(), - exchange, routingKey); + exchange, routingKey, queueDestinationCache, topicDestinationCache); return createMessage(delegate, data); } @@ -149,10 +154,12 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory public AbstractJMSMessage createMessage(long messageNbr, boolean redelivered, ContentHeaderBody contentHeader, - AMQShortString exchange, AMQShortString routingKey, List bodies) + AMQShortString exchange, AMQShortString routingKey, List bodies, + AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache, + AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache) throws JMSException, AMQException { - final AbstractJMSMessage msg = create08MessageWithBody(messageNbr, contentHeader, exchange, routingKey, bodies); + final AbstractJMSMessage msg = create08MessageWithBody(messageNbr, contentHeader, exchange, routingKey, bodies, queueDestinationCache, topicDestinationCache); msg.setJMSRedelivered(redelivered); msg.setReceivedFromServer(); return msg; diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java index f3d96cd855..93c2872b2e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java @@ -25,6 +25,9 @@ import java.util.List; import javax.jms.JMSException; import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession_0_8; +import org.apache.qpid.client.AMQTopic; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.transport.DeliveryProperties; @@ -36,7 +39,7 @@ public interface MessageFactory AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered, ContentHeaderBody contentHeader, AMQShortString exchange, AMQShortString routingKey, - List bodies) + List bodies, AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache, AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache) throws JMSException, AMQException; AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered, diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java index cdb75fc9a9..15ad3ed89f 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java @@ -28,6 +28,9 @@ import java.nio.ByteBuffer; import javax.jms.JMSException; import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession_0_8; +import org.apache.qpid.client.AMQTopic; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; @@ -93,15 +96,19 @@ public class MessageFactoryRegistry * Create a message. This looks up the MIME type from the content header and instantiates the appropriate * concrete message type. * + * * @param deliveryTag the AMQ message id * @param redelivered true if redelivered * @param contentHeader the content header that was received * @param bodies a list of ContentBody instances @return the message. - * @throws AMQException + * @param queueDestinationCache + *@param topicDestinationCache @throws AMQException * @throws JMSException */ public AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered, AMQShortString exchange, - AMQShortString routingKey, ContentHeaderBody contentHeader, List bodies) + AMQShortString routingKey, ContentHeaderBody contentHeader, List bodies, + AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache, + AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache) throws AMQException, JMSException { BasicContentHeaderProperties properties = (BasicContentHeaderProperties) contentHeader.getProperties(); @@ -118,13 +125,13 @@ public class MessageFactoryRegistry mf = _default; } - return mf.createMessage(deliveryTag, redelivered, contentHeader, exchange, routingKey, bodies); + return mf.createMessage(deliveryTag, redelivered, contentHeader, exchange, routingKey, bodies, queueDestinationCache, topicDestinationCache); } public AbstractJMSMessage createMessage(MessageTransfer transfer) throws AMQException, JMSException { - MessageProperties mprop = transfer.getHeader().get(MessageProperties.class); + MessageProperties mprop = transfer.getHeader().getMessageProperties(); String messageType = ""; if ( mprop == null || mprop.getContentType() == null) { @@ -143,7 +150,7 @@ public class MessageFactoryRegistry boolean redelivered = false; DeliveryProperties deliverProps; - if((deliverProps = transfer.getHeader().get(DeliveryProperties.class)) != null) + if((deliverProps = transfer.getHeader().getDeliveryProperties()) != null) { redelivered = deliverProps.getRedelivered(); } diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 284954edba..8911d4ee3e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.client.protocol; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -409,10 +410,10 @@ public class AMQProtocolHandler implements ProtocolEngine final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); // Decode buffer - - for (AMQDataBlock message : dataBlocks) + int size = dataBlocks.size(); + for (int i = 0; i < size; i++) { - + AMQDataBlock message = dataBlocks.get(i); if (PROTOCOL_DEBUG) { _protocolLogger.info(String.format("RECV: [%s] %s", this, message)); @@ -420,10 +421,10 @@ public class AMQProtocolHandler implements ProtocolEngine if(message instanceof AMQFrame) { - final boolean debug = _logger.isDebugEnabled(); + final long msgNumber = ++_messageReceivedCount; - if (debug && ((msgNumber % 1000) == 0)) + if (((msgNumber % 1000) == 0) && _logger.isDebugEnabled()) { _logger.debug("Received " + _messageReceivedCount + " protocol messages"); } @@ -514,12 +515,20 @@ public class AMQProtocolHandler implements ProtocolEngine return getStateManager().createWaiter(states); } - public synchronized void writeFrame(AMQDataBlock frame) + public void writeFrame(AMQDataBlock frame) + { + writeFrame(frame, true); + } + + public synchronized void writeFrame(AMQDataBlock frame, boolean flush) { final ByteBuffer buf = asByteBuffer(frame); _writtenBytes += buf.remaining(); _sender.send(buf); - _sender.flush(); + if(flush) + { + _sender.flush(); + } if (PROTOCOL_DEBUG) { @@ -539,35 +548,51 @@ public class AMQProtocolHandler implements ProtocolEngine } + private static final int REUSABLE_BYTE_BUFFER_CAPACITY = 65 * 1024; + private final byte[] _reusableBytes = new byte[REUSABLE_BYTE_BUFFER_CAPACITY]; + private final ByteBuffer _reusableByteBuffer = ByteBuffer.wrap(_reusableBytes); + private final BytesDataOutput _reusableDataOutput = new BytesDataOutput(_reusableBytes); + private ByteBuffer asByteBuffer(AMQDataBlock block) { - final ByteBuffer buf = ByteBuffer.allocate((int) block.getSize()); + final int size = (int) block.getSize(); - try - { - block.writePayload(new DataOutputStream(new OutputStream() - { + final byte[] data; - @Override - public void write(int b) throws IOException - { - buf.put((byte) b); - } + if(size > REUSABLE_BYTE_BUFFER_CAPACITY) + { + data= new byte[size]; + } + else + { - @Override - public void write(byte[] b, int off, int len) throws IOException - { - buf.put(b, off, len); - } - })); + data = _reusableBytes; + } + _reusableDataOutput.setBuffer(data); + + try + { + block.writePayload(_reusableDataOutput); } catch (IOException e) { throw new RuntimeException(e); } - buf.flip(); + final ByteBuffer buf; + + if(size < REUSABLE_BYTE_BUFFER_CAPACITY) + { + buf = _reusableByteBuffer; + buf.position(0); + } + else + { + buf = ByteBuffer.wrap(data); + } + buf.limit(_reusableDataOutput.length()); + return buf; } @@ -840,4 +865,160 @@ public class AMQProtocolHandler implements ProtocolEngine return _suggestedProtocolVersion; } + private static class BytesDataOutput implements DataOutput + { + int _pos = 0; + byte[] _buf; + + public BytesDataOutput(byte[] buf) + { + _buf = buf; + } + + public void setBuffer(byte[] buf) + { + _buf = buf; + _pos = 0; + } + + public void reset() + { + _pos = 0; + } + + public int length() + { + return _pos; + } + + public void write(int b) + { + _buf[_pos++] = (byte) b; + } + + public void write(byte[] b) + { + System.arraycopy(b, 0, _buf, _pos, b.length); + _pos+=b.length; + } + + + public void write(byte[] b, int off, int len) + { + System.arraycopy(b, off, _buf, _pos, len); + _pos+=len; + + } + + public void writeBoolean(boolean v) + { + _buf[_pos++] = v ? (byte) 1 : (byte) 0; + } + + public void writeByte(int v) + { + _buf[_pos++] = (byte) v; + } + + public void writeShort(int v) + { + _buf[_pos++] = (byte) (v >>> 8); + _buf[_pos++] = (byte) v; + } + + public void writeChar(int v) + { + _buf[_pos++] = (byte) (v >>> 8); + _buf[_pos++] = (byte) v; + } + + public void writeInt(int v) + { + _buf[_pos++] = (byte) (v >>> 24); + _buf[_pos++] = (byte) (v >>> 16); + _buf[_pos++] = (byte) (v >>> 8); + _buf[_pos++] = (byte) v; + } + + public void writeLong(long v) + { + _buf[_pos++] = (byte) (v >>> 56); + _buf[_pos++] = (byte) (v >>> 48); + _buf[_pos++] = (byte) (v >>> 40); + _buf[_pos++] = (byte) (v >>> 32); + _buf[_pos++] = (byte) (v >>> 24); + _buf[_pos++] = (byte) (v >>> 16); + _buf[_pos++] = (byte) (v >>> 8); + _buf[_pos++] = (byte)v; + } + + public void writeFloat(float v) + { + writeInt(Float.floatToIntBits(v)); + } + + public void writeDouble(double v) + { + writeLong(Double.doubleToLongBits(v)); + } + + public void writeBytes(String s) + { + int len = s.length(); + for (int i = 0 ; i < len ; i++) + { + _buf[_pos++] = ((byte)s.charAt(i)); + } + } + + public void writeChars(String s) + { + int len = s.length(); + for (int i = 0 ; i < len ; i++) + { + int v = s.charAt(i); + _buf[_pos++] = (byte) (v >>> 8); + _buf[_pos++] = (byte) v; + } + } + + public void writeUTF(String s) + { + int strlen = s.length(); + + int pos = _pos; + _pos+=2; + + + for (int i = 0; i < strlen; i++) + { + int c = s.charAt(i); + if ((c >= 0x0001) && (c <= 0x007F)) + { + c = s.charAt(i); + _buf[_pos++] = (byte) c; + + } + else if (c > 0x07FF) + { + _buf[_pos++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); + _buf[_pos++] = (byte) (0x80 | ((c >> 6) & 0x3F)); + _buf[_pos++] = (byte) (0x80 | (c & 0x3F)); + } + else + { + _buf[_pos++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); + _buf[_pos++] = (byte) (0x80 | (c & 0x3F)); + } + } + + int len = _pos - (pos + 2); + + _buf[pos++] = (byte) (len >>> 8); + _buf[pos] = (byte) len; + } + + } + + } diff --git a/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java index 10fd8d2a80..2f1eda6ef2 100644 --- a/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java +++ b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java @@ -49,19 +49,9 @@ public class MessagePartListenerAdapter implements MessagePartListener { _currentMsg = new ByteBufferMessage(xfr.getId()); - for (Struct st : xfr.getHeader().getStructs()) - { - if(st instanceof DeliveryProperties) - { - _currentMsg.setDeliveryProperties((DeliveryProperties)st); - - } - else if(st instanceof MessageProperties) - { - _currentMsg.setMessageProperties((MessageProperties)st); - } - - } + Header header = xfr.getHeader(); + _currentMsg.setDeliveryProperties(header.getDeliveryProperties()); + _currentMsg.setMessageProperties(header.getMessageProperties()); ByteBuffer body = xfr.getBody(); diff --git a/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java b/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java index d8d94ba40e..02089cc382 100644 --- a/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java +++ b/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java @@ -46,8 +46,9 @@ public class BasicMessageConsumer_0_8_Test extends TestCase AMQBindingURL burl = new AMQBindingURL(url); AMQDestination queue = new AMQQueue(burl); - AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> testSession = new TestAMQSession(conn); - BasicMessageConsumer_0_8 consumer = new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + TestAMQSession testSession = new TestAMQSession(conn); + BasicMessageConsumer_0_8 consumer = + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.SERVER, consumer.getRejectBehaviour()); } @@ -65,8 +66,9 @@ public class BasicMessageConsumer_0_8_Test extends TestCase final AMQBindingURL burl = new AMQBindingURL(url); final AMQDestination queue = new AMQQueue(burl); - final AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> testSession = new TestAMQSession(conn); - final BasicMessageConsumer_0_8 consumer = new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + final TestAMQSession testSession = new TestAMQSession(conn); + final BasicMessageConsumer_0_8 consumer = + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.NORMAL, consumer.getRejectBehaviour()); } @@ -90,8 +92,9 @@ public class BasicMessageConsumer_0_8_Test extends TestCase assertNull("Reject behaviour should have been null", queue.getRejectBehaviour()); - AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> testSession = new TestAMQSession(conn); - BasicMessageConsumer_0_8 consumer = new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + TestAMQSession testSession = new TestAMQSession(conn); + BasicMessageConsumer_0_8 consumer = + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.NORMAL, consumer.getRejectBehaviour()); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java index 06d0f4a3f9..4c3e9c2390 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java @@ -29,12 +29,7 @@ import javax.jms.Topic; import javax.jms.TopicSubscriber; import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.BasicMessageConsumer_0_8; -import org.apache.qpid.client.BasicMessageProducer_0_8; -import org.apache.qpid.client.MockAMQConnection; +import org.apache.qpid.client.*; import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.message.AMQMessageDelegateFactory; import org.apache.qpid.client.protocol.AMQProtocolHandler; @@ -42,7 +37,7 @@ import org.apache.qpid.filter.MessageFilter; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8> +public class TestAMQSession extends AMQSession_0_8 { public TestAMQSession(AMQConnection connection) @@ -92,7 +87,7 @@ public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMe return null; } - protected void sendRecover() throws AMQException, FailoverException + public void sendRecover() throws AMQException, FailoverException { } diff --git a/java/common/Composite.tpl b/java/common/Composite.tpl index 350dd893c8..2cbd6830f6 100644 --- a/java/common/Composite.tpl +++ b/java/common/Composite.tpl @@ -245,6 +245,11 @@ if segments: return this; } + public int getBodySize() + { + return this.body == null ? 0 : this.body.remaining(); + } + public final ByteBuffer getBody() { if (this.body == null) { diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java index 69bf73bb49..1d196534b2 100644 --- a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java +++ b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java @@ -24,12 +24,7 @@ import java.io.*; import java.nio.ByteBuffer; import java.util.*; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQDataBlockDecoder; -import org.apache.qpid.framing.AMQFrameDecodingException; -import org.apache.qpid.framing.AMQMethodBodyFactory; -import org.apache.qpid.framing.AMQProtocolVersionException; -import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.framing.*; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; /** @@ -193,24 +188,41 @@ public class AMQDecoder } } + private static class SimpleDataInputStream extends DataInputStream implements MarkableDataInput + { + public SimpleDataInputStream(InputStream in) + { + super(in); + } + + public AMQShortString readAMQShortString() throws IOException + { + return EncodingUtils.readAMQShortString(this); + } + + } + public ArrayList<AMQDataBlock> decodeBuffer(ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { // get prior remaining data from accumulator ArrayList<AMQDataBlock> dataBlocks = new ArrayList<AMQDataBlock>(); - DataInputStream msg; + MarkableDataInput msg; - ByteArrayInputStream bais = new ByteArrayInputStream(buf.array(),buf.arrayOffset()+buf.position(), buf.remaining()); + ByteArrayInputStream bais; + DataInput di; if(!_remainingBufs.isEmpty()) { + bais = new ByteArrayInputStream(buf.array(),buf.arrayOffset()+buf.position(), buf.remaining()); _remainingBufs.add(bais); - msg = new DataInputStream(new RemainingByteArrayInputStream()); + msg = new SimpleDataInputStream(new RemainingByteArrayInputStream()); } else { - msg = new DataInputStream(bais); + bais = null; + msg = new ByteArrayDataInput(buf.array(),buf.arrayOffset()+buf.position(), buf.remaining()); } boolean enoughData = true; @@ -245,11 +257,24 @@ public class AMQDecoder iterator.remove(); } } - if(bais.available()!=0) + + if(bais == null) + { + if(msg.available()!=0) + { + byte[] remaining = new byte[msg.available()]; + msg.read(remaining); + _remainingBufs.add(new ByteArrayInputStream(remaining)); + } + } + else { - byte[] remaining = new byte[bais.available()]; - bais.read(remaining); - _remainingBufs.add(new ByteArrayInputStream(remaining)); + if(bais.available()!=0) + { + byte[] remaining = new byte[bais.available()]; + bais.read(remaining); + _remainingBufs.add(new ByteArrayInputStream(remaining)); + } } } } diff --git a/java/common/src/main/java/org/apache/qpid/codec/MarkableDataInput.java b/java/common/src/main/java/org/apache/qpid/codec/MarkableDataInput.java new file mode 100644 index 0000000000..2a243a810d --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/codec/MarkableDataInput.java @@ -0,0 +1,21 @@ +package org.apache.qpid.codec; + +import org.apache.qpid.framing.AMQShortString; + +import java.io.DataInput; +import java.io.IOException; + +public interface MarkableDataInput extends DataInput +{ + public void mark(int pos); + public void reset() throws IOException; + + int available() throws IOException; + + long skip(long i) throws IOException; + + int read(byte[] b) throws IOException; + + public AMQShortString readAMQShortString() throws IOException; + +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java index ebdad12178..363d9f1ccc 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.framing; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -36,7 +37,7 @@ public interface AMQBody */ public abstract int getSize(); - public void writePayload(DataOutputStream buffer) throws IOException; + public void writePayload(DataOutput buffer) throws IOException; void handle(final int channelId, final AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java index 00c1f5aae5..e77e5942e3 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java @@ -21,6 +21,7 @@ package org.apache.qpid.framing; import java.io.DataInputStream; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -42,6 +43,6 @@ public abstract class AMQDataBlock implements EncodableAMQDataBlock * Writes the datablock to the specified buffer. * @param buffer */ - public abstract void writePayload(DataOutputStream buffer) throws IOException; + public abstract void writePayload(DataOutput buffer) throws IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java index 2165cadd14..b6f2fb18ea 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.framing; +import org.apache.qpid.codec.MarkableDataInput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +44,7 @@ public class AMQDataBlockDecoder public AMQDataBlockDecoder() { } - public boolean decodable(DataInputStream in) throws AMQFrameDecodingException, IOException + public boolean decodable(MarkableDataInput in) throws AMQFrameDecodingException, IOException { final int remainingAfterAttributes = in.available() - (1 + 2 + 4 + 1); // type, channel, body length and end byte @@ -65,7 +66,7 @@ public class AMQDataBlockDecoder } - public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, DataInputStream in) + public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, MarkableDataInput in) throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { final byte type = in.readByte(); diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java index 6acf60a5b3..9b5699e8ff 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java @@ -20,9 +20,10 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import org.apache.qpid.codec.MarkableDataInput; + +import java.io.*; +import java.io.DataOutput; public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock { @@ -38,7 +39,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock _bodyFrame = bodyFrame; } - public AMQFrame(final DataInputStream in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException, IOException + public AMQFrame(final MarkableDataInput in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException, IOException { this._channel = channel; this._bodyFrame = bodyFactory.createBody(in,bodySize); @@ -55,7 +56,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { buffer.writeByte(_bodyFrame.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, _channel); @@ -79,7 +80,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock return "Frame channelId: " + _channel + ", bodyFrame: " + String.valueOf(_bodyFrame); } - public static void writeFrame(DataOutputStream buffer, final int channel, AMQBody body) throws IOException + public static void writeFrame(DataOutput buffer, final int channel, AMQBody body) throws IOException { buffer.writeByte(body.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); @@ -89,7 +90,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock } - public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2) throws IOException + public static void writeFrames(DataOutput buffer, final int channel, AMQBody body1, AMQBody body2) throws IOException { buffer.writeByte(body1.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); @@ -104,7 +105,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock } - public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3) throws IOException + public static void writeFrames(DataOutput buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3) throws IOException { buffer.writeByte(body1.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java index a076d0e5a1..2170ebf992 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java @@ -25,6 +25,7 @@ import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -45,12 +46,12 @@ public interface AMQMethodBody extends AMQBody /** @return unsigned short */ public int getMethod(); - public void writeMethodPayload(DataOutputStream buffer) throws IOException; + public void writeMethodPayload(DataOutput buffer) throws IOException; public int getSize(); - public void writePayload(DataOutputStream buffer) throws IOException; + public void writePayload(DataOutput buffer) throws IOException; //public abstract void populateMethodBodyFromBuffer(ByteBuffer buffer) throws AMQFrameDecodingException; diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java index 7fceb082ee..ec6d662726 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java @@ -20,11 +20,13 @@ */ package org.apache.qpid.framing; +import org.apache.qpid.codec.MarkableDataInput; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; @@ -39,7 +41,7 @@ public class AMQMethodBodyFactory implements BodyFactory _protocolSession = protocolSession; } - public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException + public AMQBody createBody(MarkableDataInput in, long bodySize) throws AMQFrameDecodingException, IOException { return _protocolSession.getMethodRegistry().convertToBody(in, bodySize); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java index c73c1df701..d6f518b123 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java @@ -24,11 +24,12 @@ package org.apache.qpid.framing; import org.apache.qpid.AMQChannelException; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; +import org.apache.qpid.codec.MarkableDataInput; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; public abstract class AMQMethodBodyImpl implements AMQMethodBody @@ -101,7 +102,7 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return 2 + 2 + getBodySize(); } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { EncodingUtils.writeUnsignedShort(buffer, getClazz()); EncodingUtils.writeUnsignedShort(buffer, getMethod()); @@ -109,14 +110,15 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody } - protected byte readByte(DataInputStream buffer) throws IOException + protected byte readByte(DataInput buffer) throws IOException { return buffer.readByte(); } - protected AMQShortString readAMQShortString(DataInputStream buffer) throws IOException + protected AMQShortString readAMQShortString(MarkableDataInput buffer) throws IOException { - return EncodingUtils.readAMQShortString(buffer); + AMQShortString str = buffer.readAMQShortString(); + return str == null ? null : str.intern(false); } protected int getSizeOf(AMQShortString string) @@ -124,27 +126,27 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return EncodingUtils.encodedShortStringLength(string); } - protected void writeByte(DataOutputStream buffer, byte b) throws IOException + protected void writeByte(DataOutput buffer, byte b) throws IOException { buffer.writeByte(b); } - protected void writeAMQShortString(DataOutputStream buffer, AMQShortString string) throws IOException + protected void writeAMQShortString(DataOutput buffer, AMQShortString string) throws IOException { EncodingUtils.writeShortStringBytes(buffer, string); } - protected int readInt(DataInputStream buffer) throws IOException + protected int readInt(DataInput buffer) throws IOException { return buffer.readInt(); } - protected void writeInt(DataOutputStream buffer, int i) throws IOException + protected void writeInt(DataOutput buffer, int i) throws IOException { buffer.writeInt(i); } - protected FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException + protected FieldTable readFieldTable(DataInput buffer) throws AMQFrameDecodingException, IOException { return EncodingUtils.readFieldTable(buffer); } @@ -154,17 +156,17 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates. } - protected void writeFieldTable(DataOutputStream buffer, FieldTable table) throws IOException + protected void writeFieldTable(DataOutput buffer, FieldTable table) throws IOException { EncodingUtils.writeFieldTableBytes(buffer, table); } - protected long readLong(DataInputStream buffer) throws IOException + protected long readLong(DataInput buffer) throws IOException { return buffer.readLong(); } - protected void writeLong(DataOutputStream buffer, long l) throws IOException + protected void writeLong(DataOutput buffer, long l) throws IOException { buffer.writeLong(l); } @@ -174,27 +176,27 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return (response == null) ? 4 : response.length + 4; } - protected void writeBytes(DataOutputStream buffer, byte[] data) throws IOException + protected void writeBytes(DataOutput buffer, byte[] data) throws IOException { EncodingUtils.writeBytes(buffer,data); } - protected byte[] readBytes(DataInputStream buffer) throws IOException + protected byte[] readBytes(DataInput buffer) throws IOException { return EncodingUtils.readBytes(buffer); } - protected short readShort(DataInputStream buffer) throws IOException + protected short readShort(DataInput buffer) throws IOException { return EncodingUtils.readShort(buffer); } - protected void writeShort(DataOutputStream buffer, short s) throws IOException + protected void writeShort(DataOutput buffer, short s) throws IOException { EncodingUtils.writeShort(buffer, s); } - protected Content readContent(DataInputStream buffer) + protected Content readContent(DataInput buffer) { return null; } @@ -204,56 +206,56 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return 0; } - protected void writeContent(DataOutputStream buffer, Content body) + protected void writeContent(DataOutput buffer, Content body) { } - protected byte readBitfield(DataInputStream buffer) throws IOException + protected byte readBitfield(DataInput buffer) throws IOException { return readByte(buffer); } - protected int readUnsignedShort(DataInputStream buffer) throws IOException + protected int readUnsignedShort(DataInput buffer) throws IOException { return buffer.readUnsignedShort(); } - protected void writeBitfield(DataOutputStream buffer, byte bitfield0) throws IOException + protected void writeBitfield(DataOutput buffer, byte bitfield0) throws IOException { buffer.writeByte(bitfield0); } - protected void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException + protected void writeUnsignedShort(DataOutput buffer, int s) throws IOException { EncodingUtils.writeUnsignedShort(buffer, s); } - protected long readUnsignedInteger(DataInputStream buffer) throws IOException + protected long readUnsignedInteger(DataInput buffer) throws IOException { return EncodingUtils.readUnsignedInteger(buffer); } - protected void writeUnsignedInteger(DataOutputStream buffer, long i) throws IOException + protected void writeUnsignedInteger(DataOutput buffer, long i) throws IOException { EncodingUtils.writeUnsignedInteger(buffer, i); } - protected short readUnsignedByte(DataInputStream buffer) throws IOException + protected short readUnsignedByte(DataInput buffer) throws IOException { return (short) buffer.readUnsignedByte(); } - protected void writeUnsignedByte(DataOutputStream buffer, short unsignedByte) throws IOException + protected void writeUnsignedByte(DataOutput buffer, short unsignedByte) throws IOException { EncodingUtils.writeUnsignedByte(buffer, unsignedByte); } - protected long readTimestamp(DataInputStream buffer) throws IOException + protected long readTimestamp(DataInput buffer) throws IOException { return EncodingUtils.readTimestamp(buffer); } - protected void writeTimestamp(DataOutputStream buffer, long t) throws IOException + protected void writeTimestamp(DataOutput buffer, long t) throws IOException { EncodingUtils.writeTimestamp(buffer, t); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java index df4d8bdcb6..88b1ca7189 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java @@ -21,11 +21,12 @@ package org.apache.qpid.framing; -import java.io.DataInputStream; +import org.apache.qpid.codec.MarkableDataInput; + import java.io.IOException; public abstract interface AMQMethodBodyInstanceFactory { - public AMQMethodBody newInstance(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException; + public AMQMethodBody newInstance(MarkableDataInput buffer, long size) throws AMQFrameDecodingException, IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java index cc9a33f4cf..4ff7827d7f 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java @@ -24,8 +24,9 @@ package org.apache.qpid.framing; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import java.util.*; import java.lang.ref.WeakReference; @@ -93,22 +94,44 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt private AMQShortString substring(final int from, final int to) { - return new AMQShortString(_data, from+_offset, to+_offset); + return new AMQShortString(_data, from+_offset, to-from); } - private static final ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>> _localInternMap = - new ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>>() + private static final int LOCAL_INTERN_CACHE_SIZE = 2048; + + private static final ThreadLocal<Map<AMQShortString, AMQShortString>> _localInternMap = + new ThreadLocal<Map<AMQShortString, AMQShortString>>() { - protected Map<AMQShortString, WeakReference<AMQShortString>> initialValue() + protected Map<AMQShortString, AMQShortString> initialValue() { - return new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>(); + return new LinkedHashMap<AMQShortString, AMQShortString>() + { + + protected boolean removeEldestEntry(Map.Entry<AMQShortString, AMQShortString> eldest) + { + return size() > LOCAL_INTERN_CACHE_SIZE; + } + }; }; }; private static final Map<AMQShortString, WeakReference<AMQShortString>> _globalInternMap = new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>(); + + private static final ThreadLocal<Map<String, WeakReference<AMQShortString>>> _localStringMap = + new ThreadLocal<Map<String, WeakReference<AMQShortString>>>() + { + protected Map<String, WeakReference<AMQShortString>> initialValue() + { + return new WeakHashMap<String, WeakReference<AMQShortString>>(); + }; + }; + + private static final Map<String, WeakReference<AMQShortString>> _globalStringMap = + new WeakHashMap<String, WeakReference<AMQShortString>>(); + private static final Logger _logger = LoggerFactory.getLogger(AMQShortString.class); private final byte[] _data; @@ -200,32 +223,32 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt } - private AMQShortString(DataInputStream data, final int length) throws IOException + private AMQShortString(DataInput data, final int length) throws IOException { if (length > MAX_LENGTH) { throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); } byte[] dataBytes = new byte[length]; - data.read(dataBytes); + data.readFully(dataBytes); _data = dataBytes; _offset = 0; _length = length; } - private AMQShortString(final byte[] data, final int from, final int to) + public AMQShortString(byte[] data, final int offset, final int length) { - if (data == null) - { - throw new NullPointerException("Cannot create AMQShortString with null data[]"); - } - int length = to - from; if (length > MAX_LENGTH) { throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); } - _offset = from; + if (data == null) + { + throw new NullPointerException("Cannot create AMQShortString with null data[]"); + } + + _offset = offset; _length = length; _data = data; } @@ -234,9 +257,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { if(_data.length != _length) { - byte[] dataBytes = new byte[_length]; - System.arraycopy(_data,_offset,dataBytes,0,_length); - return new AMQShortString(dataBytes,0,_length); + return copy(); } else { @@ -265,7 +286,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return new CharSubSequence(start, end); } - public static AMQShortString readFromBuffer(DataInputStream buffer) throws IOException + public static AMQShortString readFromBuffer(DataInput buffer) throws IOException { final int length = buffer.readUnsignedByte(); if (length == 0) @@ -293,12 +314,12 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt } } - public void writeToBuffer(DataOutputStream buffer) throws IOException + public void writeToBuffer(DataOutput buffer) throws IOException { final int size = length(); //buffer.setAutoExpand(true); - buffer.write((byte) size); + buffer.writeByte(size); buffer.write(_data, _offset, size); } @@ -420,7 +441,17 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { if (_asString == null) { - _asString = new String(asChars()); + AMQShortString intern = intern(); + + if(intern == this) + { + _asString = new String(asChars()); + } + else + { + _asString = intern.asString(); + } + } return _asString; } @@ -609,42 +640,51 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt public AMQShortString intern() { + return intern(true); + } + + public AMQShortString intern(boolean keep) + { hashCode(); - Map<AMQShortString, WeakReference<AMQShortString>> localMap = + Map<AMQShortString, AMQShortString> localMap = _localInternMap.get(); - WeakReference<AMQShortString> ref = localMap.get(this); - AMQShortString internString; + AMQShortString internString = localMap.get(this); - if(ref != null) + + if(internString != null) { - internString = ref.get(); - if(internString != null) - { - return internString; - } + return internString; } + WeakReference<AMQShortString> ref; synchronized(_globalInternMap) { ref = _globalInternMap.get(this); if((ref == null) || ((internString = ref.get()) == null)) { - internString = shrink(); + internString = keep ? shrink() : copy(); ref = new WeakReference(internString); _globalInternMap.put(internString, ref); } } - localMap.put(internString, ref); + localMap.put(internString, internString); return internString; } + private AMQShortString copy() + { + byte[] dataBytes = new byte[_length]; + System.arraycopy(_data,_offset,dataBytes,0,_length); + return new AMQShortString(dataBytes,0,_length); + } + private int occurences(final byte delim) { int count = 0; @@ -761,7 +801,46 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt public static AMQShortString valueOf(Object obj) { - return obj == null ? null : new AMQShortString(String.valueOf(obj)); + return obj == null ? null : AMQShortString.valueOf(String.valueOf(obj)); + } + + public static AMQShortString valueOf(String obj) + { + if(obj == null) + { + return null; + } + + Map<String, WeakReference<AMQShortString>> localMap = + _localStringMap.get(); + + WeakReference<AMQShortString> ref = localMap.get(obj); + AMQShortString internString; + + if(ref != null) + { + internString = ref.get(); + if(internString != null) + { + return internString; + } + } + + + synchronized(_globalStringMap) + { + + ref = _globalStringMap.get(obj); + if((ref == null) || ((internString = ref.get()) == null)) + { + internString = (new AMQShortString(obj)).intern(); + ref = new WeakReference<AMQShortString>(internString); + _globalStringMap.put(obj, ref); + } + + } + localMap.put(obj, ref); + return internString; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java index f3da64e639..5c89af09c4 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java @@ -20,8 +20,8 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.math.BigDecimal; @@ -61,12 +61,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -107,12 +107,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeUnsignedInteger(buffer, (Long) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readUnsignedInteger(buffer); } @@ -138,7 +138,7 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { BigDecimal bd = (BigDecimal) value; @@ -151,7 +151,7 @@ public enum AMQType EncodingUtils.writeInteger(buffer, unscaled); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { byte places = EncodingUtils.readByte(buffer); @@ -183,12 +183,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLong(buffer, (Long) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLong(buffer); } @@ -247,7 +247,7 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { // Ensure that the value is a FieldTable. if (!(value instanceof FieldTable)) @@ -268,7 +268,7 @@ public enum AMQType * * @return An instance of the type. */ - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { try { @@ -302,10 +302,10 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) + public void writeValueImpl(Object value, DataOutput buffer) { } - public Object readValueFromBuffer(DataInputStream buffer) + public Object readValueFromBuffer(DataInput buffer) { return null; } @@ -331,12 +331,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLongstr(buffer, (byte[]) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLongstr(buffer); } @@ -361,12 +361,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -392,12 +392,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -427,12 +427,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeBoolean(buffer, (Boolean) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readBoolean(buffer); } @@ -462,12 +462,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeChar(buffer, (Character) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readChar(buffer); } @@ -497,12 +497,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeByte(buffer, (Byte) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readByte(buffer); } @@ -536,12 +536,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeShort(buffer, (Short) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readShort(buffer); } @@ -578,12 +578,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeInteger(buffer, (Integer) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readInteger(buffer); } @@ -596,6 +596,22 @@ public enum AMQType return EncodingUtils.encodedLongLength(); } + public int getEncodingSize(long value) + { + return EncodingUtils.encodedLongLength(); + } + + public AMQTypedValue asTypedValue(long value) + { + return AMQTypedValue.createAMQTypedValue(value); + } + + public void writeToBuffer(long value, DataOutput buffer) throws IOException + { + buffer.writeByte(identifier()); + EncodingUtils.writeLong(buffer, value); + } + public Object toNativeValue(Object value) { if (value instanceof Long) @@ -625,12 +641,18 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeLong(buffer, (Long) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public long readLongFromBuffer(DataInput buffer) throws IOException + { + return EncodingUtils.readLong(buffer); + } + + + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readLong(buffer); } @@ -660,12 +682,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeFloat(buffer, (Float) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readFloat(buffer); } @@ -699,12 +721,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException + public void writeValueImpl(Object value, DataOutput buffer) throws IOException { EncodingUtils.writeDouble(buffer, (Double) value); } - public Object readValueFromBuffer(DataInputStream buffer) throws IOException + public Object readValueFromBuffer(DataInput buffer) throws IOException { return EncodingUtils.readDouble(buffer); } @@ -761,7 +783,7 @@ public enum AMQType */ public AMQTypedValue asTypedValue(Object value) { - return new AMQTypedValue(this, toNativeValue(value)); + return AMQTypedValue.createAMQTypedValue(this, toNativeValue(value)); } /** @@ -771,7 +793,7 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - public void writeToBuffer(Object value, DataOutputStream buffer) throws IOException + public void writeToBuffer(Object value, DataOutput buffer) throws IOException { buffer.writeByte(identifier()); writeValueImpl(value, buffer); @@ -783,7 +805,7 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - abstract void writeValueImpl(Object value, DataOutputStream buffer) throws IOException; + abstract void writeValueImpl(Object value, DataOutput buffer) throws IOException; /** * Reads an instance of the type from a specified byte buffer. @@ -792,5 +814,5 @@ public enum AMQType * * @return An instance of the type. */ - abstract Object readValueFromBuffer(DataInputStream buffer) throws IOException; + abstract Object readValueFromBuffer(DataInput buffer) throws IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java index 1dbedca362..84e4056f4d 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java @@ -20,9 +20,7 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import java.util.Date; import java.util.Map; import java.math.BigDecimal; @@ -42,81 +40,218 @@ import java.math.BigDecimal; * <tr><td> Extract the value from a fully typed AMQP value. * </table> */ -public class AMQTypedValue +public abstract class AMQTypedValue { - /** The type of the value. */ - private final AMQType _type; - /** The Java native representation of the AMQP typed value. */ - private final Object _value; + public abstract AMQType getType(); - public AMQTypedValue(AMQType type, Object value) + public abstract Object getValue(); + + public abstract void writeToBuffer(DataOutput buffer) throws IOException; + + public abstract int getEncodingSize(); + + + private static final class GenericTypedValue extends AMQTypedValue { - if (type == null) + /** The type of the value. */ + private final AMQType _type; + + /** The Java native representation of the AMQP typed value. */ + private final Object _value; + + private GenericTypedValue(AMQType type, Object value) { - throw new NullPointerException("Cannot create a typed value with null type"); + if (type == null) + { + throw new NullPointerException("Cannot create a typed value with null type"); + } + + _type = type; + _value = type.toNativeValue(value); } - _type = type; - _value = type.toNativeValue(value); - } + private GenericTypedValue(AMQType type, DataInput buffer) throws IOException + { + _type = type; + _value = type.readValueFromBuffer(buffer); + } + + + public AMQType getType() + { + return _type; + } + + public Object getValue() + { + return _value; + } + + public void writeToBuffer(DataOutput buffer) throws IOException + { + _type.writeToBuffer(_value, buffer); + } + + public int getEncodingSize() + { + return _type.getEncodingSize(_value); + } + + + public String toString() + { + return "[" + getType() + ": " + getValue() + "]"; + } + + + public boolean equals(Object o) + { + if(o instanceof GenericTypedValue) + { + GenericTypedValue other = (GenericTypedValue) o; + return _type == other._type && (_value == null ? other._value == null : _value.equals(other._value)); + } + else + { + return false; + } + } + + public int hashCode() + { + return _type.hashCode() ^ (_value == null ? 0 : _value.hashCode()); + } - private AMQTypedValue(AMQType type, DataInputStream buffer) throws IOException - { - _type = type; - _value = type.readValueFromBuffer(buffer); } - public AMQType getType() + private static final class LongTypedValue extends AMQTypedValue { - return _type; + + private final long _value; + + private LongTypedValue(long value) + { + _value = value; + } + + public LongTypedValue(DataInput buffer) throws IOException + { + _value = EncodingUtils.readLong(buffer); + } + + public AMQType getType() + { + return AMQType.LONG; + } + + + public Object getValue() + { + return _value; + } + + public void writeToBuffer(DataOutput buffer) throws IOException + { + EncodingUtils.writeByte(buffer,AMQType.LONG.identifier()); + EncodingUtils.writeLong(buffer,_value); + } + + + public int getEncodingSize() + { + return EncodingUtils.encodedLongLength(); + } } - public Object getValue() + private static final class IntTypedValue extends AMQTypedValue { - return _value; + + private final int _value; + + public IntTypedValue(int value) + { + _value = value; + } + + public AMQType getType() + { + return AMQType.INT; + } + + + public Object getValue() + { + return _value; + } + + public void writeToBuffer(DataOutput buffer) throws IOException + { + EncodingUtils.writeByte(buffer,AMQType.INT.identifier()); + EncodingUtils.writeInteger(buffer, _value); + } + + + public int getEncodingSize() + { + return EncodingUtils.encodedIntegerLength(); + } } - public void writeToBuffer(DataOutputStream buffer) throws IOException + + public static AMQTypedValue readFromBuffer(DataInput buffer) throws IOException { - _type.writeToBuffer(_value, buffer); + AMQType type = AMQTypeMap.getType(buffer.readByte()); + + switch(type) + { + case LONG: + return new LongTypedValue(buffer); + + case INT: + int value = EncodingUtils.readInteger(buffer); + return createAMQTypedValue(value); + + default: + return new GenericTypedValue(type, buffer); + } + } - public int getEncodingSize() + private static final AMQTypedValue[] INT_VALUES = new AMQTypedValue[16]; + static { - return _type.getEncodingSize(_value); + for(int i = 0 ; i < 16; i ++) + { + INT_VALUES[i] = new IntTypedValue(i); + } } - public static AMQTypedValue readFromBuffer(DataInputStream buffer) throws IOException + public static AMQTypedValue createAMQTypedValue(int i) { - AMQType type = AMQTypeMap.getType(buffer.readByte()); - - return new AMQTypedValue(type, buffer); + return (i & 0x0f) == i ? INT_VALUES[i] : new IntTypedValue(i); } - public String toString() + + public static AMQTypedValue createAMQTypedValue(long value) { - return "[" + getType() + ": " + getValue() + "]"; + return new LongTypedValue(value); } - - public boolean equals(Object o) + public static AMQTypedValue createAMQTypedValue(AMQType type, Object value) { - if(o instanceof AMQTypedValue) + switch(type) { - AMQTypedValue other = (AMQTypedValue) o; - return _type == other._type && (_value == null ? other._value == null : _value.equals(other._value)); - } - else - { - return false; + case LONG: + return new LongTypedValue((Long) AMQType.LONG.toNativeValue(value)); + case INT: + return new IntTypedValue((Integer) AMQType.INT.toNativeValue(value)); + + default: + return new GenericTypedValue(type, value); } } - public int hashCode() - { - return _type.hashCode() ^ (_value == null ? 0 : _value.hashCode()); - } public static AMQTypedValue toTypedValue(Object val) diff --git a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java index 57622b5054..2739f7d14b 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java +++ b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java @@ -20,8 +20,9 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.slf4j.Logger; @@ -80,6 +81,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti private static final int USER_ID_MASK = 1 << 4; private static final int APPLICATION_ID_MASK = 1 << 3; private static final int CLUSTER_ID_MASK = 1 << 2; + private byte[] _encodedForm; public BasicContentHeaderProperties() @@ -87,6 +89,12 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public int getPropertyListSize() { + if(_encodedForm != null && (_headers == null || _headers.isClean())) + { + return _encodedForm.length; + } + else + { int size = 0; if ((_propertyFlags & (CONTENT_TYPE_MASK)) > 0) @@ -167,6 +175,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti } return size; + } } public void setPropertyFlags(int propertyFlags) @@ -179,87 +188,94 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti return _propertyFlags; } - public void writePropertyListPayload(DataOutputStream buffer) throws IOException + public void writePropertyListPayload(DataOutput buffer) throws IOException { - if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) + if(_encodedForm != null && (_headers == null || !_headers.isClean())) { - EncodingUtils.writeShortStringBytes(buffer, _contentType); + buffer.write(_encodedForm); } - - if ((_propertyFlags & ENCODING_MASK) != 0) + else { - EncodingUtils.writeShortStringBytes(buffer, _encoding); - } + if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _contentType); + } - if ((_propertyFlags & HEADERS_MASK) != 0) - { - EncodingUtils.writeFieldTableBytes(buffer, _headers); - } + if ((_propertyFlags & ENCODING_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _encoding); + } - if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) - { - buffer.writeByte(_deliveryMode); - } + if ((_propertyFlags & HEADERS_MASK) != 0) + { + EncodingUtils.writeFieldTableBytes(buffer, _headers); + } - if ((_propertyFlags & PRIORITY_MASK) != 0) - { - buffer.writeByte(_priority); - } + if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) + { + buffer.writeByte(_deliveryMode); + } - if ((_propertyFlags & CORRELATION_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _correlationId); - } + if ((_propertyFlags & PRIORITY_MASK) != 0) + { + buffer.writeByte(_priority); + } - if ((_propertyFlags & REPLY_TO_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _replyTo); - } + if ((_propertyFlags & CORRELATION_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _correlationId); + } - if ((_propertyFlags & EXPIRATION_MASK) != 0) - { - if (_expiration == 0L) + if ((_propertyFlags & REPLY_TO_MASK) != 0) { - EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING); + EncodingUtils.writeShortStringBytes(buffer, _replyTo); } - else + + if ((_propertyFlags & EXPIRATION_MASK) != 0) { - EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration)); + if (_expiration == 0L) + { + EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING); + } + else + { + EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration)); + } } - } - if ((_propertyFlags & MESSAGE_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _messageId); - } + if ((_propertyFlags & MESSAGE_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _messageId); + } - if ((_propertyFlags & TIMESTAMP_MASK) != 0) - { - EncodingUtils.writeTimestamp(buffer, _timestamp); - } + if ((_propertyFlags & TIMESTAMP_MASK) != 0) + { + EncodingUtils.writeTimestamp(buffer, _timestamp); + } - if ((_propertyFlags & TYPE_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _type); - } + if ((_propertyFlags & TYPE_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _type); + } - if ((_propertyFlags & USER_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _userId); - } + if ((_propertyFlags & USER_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _userId); + } - if ((_propertyFlags & APPLICATION_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _appId); - } + if ((_propertyFlags & APPLICATION_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _appId); + } - if ((_propertyFlags & CLUSTER_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _clusterId); + if ((_propertyFlags & CLUSTER_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _clusterId); + } } } - public void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException + public void populatePropertiesFromBuffer(DataInput buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException { _propertyFlags = propertyFlags; @@ -268,26 +284,40 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti _logger.debug("Property flags: " + _propertyFlags); } - decode(buffer); + _encodedForm = new byte[size]; + buffer.readFully(_encodedForm); + + ByteArrayDataInput input = new ByteArrayDataInput(_encodedForm); + + decode(input); + } - private void decode(DataInputStream buffer) throws IOException, AMQFrameDecodingException + private void decode(ByteArrayDataInput buffer) throws IOException, AMQFrameDecodingException { // ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); + int headersOffset = 0; + if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) { - _contentType = EncodingUtils.readAMQShortString(buffer); + _contentType = buffer.readAMQShortString(); + headersOffset += EncodingUtils.encodedShortStringLength(_contentType); } if ((_propertyFlags & ENCODING_MASK) != 0) { - _encoding = EncodingUtils.readAMQShortString(buffer); + _encoding = buffer.readAMQShortString(); + headersOffset += EncodingUtils.encodedShortStringLength(_encoding); } if ((_propertyFlags & HEADERS_MASK) != 0) { - _headers = EncodingUtils.readFieldTable(buffer); + long length = EncodingUtils.readUnsignedInteger(buffer); + + _headers = new FieldTable(_encodedForm, headersOffset+4, (int)length); + + buffer.skipBytes((int)length); } if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) @@ -302,12 +332,12 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti if ((_propertyFlags & CORRELATION_ID_MASK) != 0) { - _correlationId = EncodingUtils.readAMQShortString(buffer); + _correlationId = buffer.readAMQShortString(); } if ((_propertyFlags & REPLY_TO_MASK) != 0) { - _replyTo = EncodingUtils.readAMQShortString(buffer); + _replyTo = buffer.readAMQShortString(); } if ((_propertyFlags & EXPIRATION_MASK) != 0) @@ -317,7 +347,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti if ((_propertyFlags & MESSAGE_ID_MASK) != 0) { - _messageId = EncodingUtils.readAMQShortString(buffer); + _messageId = buffer.readAMQShortString(); } if ((_propertyFlags & TIMESTAMP_MASK) != 0) @@ -327,22 +357,22 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti if ((_propertyFlags & TYPE_MASK) != 0) { - _type = EncodingUtils.readAMQShortString(buffer); + _type = buffer.readAMQShortString(); } if ((_propertyFlags & USER_ID_MASK) != 0) { - _userId = EncodingUtils.readAMQShortString(buffer); + _userId = buffer.readAMQShortString(); } if ((_propertyFlags & APPLICATION_ID_MASK) != 0) { - _appId = EncodingUtils.readAMQShortString(buffer); + _appId = buffer.readAMQShortString(); } if ((_propertyFlags & CLUSTER_ID_MASK) != 0) { - _clusterId = EncodingUtils.readAMQShortString(buffer); + _clusterId = buffer.readAMQShortString(); } @@ -363,11 +393,12 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= (CONTENT_TYPE_MASK); _contentType = contentType; + _encodedForm = null; } public void setContentType(String contentType) { - setContentType((contentType == null) ? null : new AMQShortString(contentType)); + setContentType((contentType == null) ? null : AMQShortString.valueOf(contentType)); } public String getEncodingAsString() @@ -384,13 +415,15 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setEncoding(String encoding) { _propertyFlags |= ENCODING_MASK; - _encoding = (encoding == null) ? null : new AMQShortString(encoding); + _encoding = (encoding == null) ? null : AMQShortString.valueOf(encoding); + _encodedForm = null; } public void setEncoding(AMQShortString encoding) { _propertyFlags |= ENCODING_MASK; _encoding = encoding; + _encodedForm = null; } public FieldTable getHeaders() @@ -407,6 +440,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= HEADERS_MASK; _headers = headers; + _encodedForm = null; } public byte getDeliveryMode() @@ -418,6 +452,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= DELIVERY_MODE_MASK; _deliveryMode = deliveryMode; + _encodedForm = null; } public byte getPriority() @@ -429,6 +464,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= PRIORITY_MASK; _priority = priority; + _encodedForm = null; } public AMQShortString getCorrelationId() @@ -443,13 +479,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setCorrelationId(String correlationId) { - setCorrelationId((correlationId == null) ? null : new AMQShortString(correlationId)); + setCorrelationId((correlationId == null) ? null : AMQShortString.valueOf(correlationId)); } public void setCorrelationId(AMQShortString correlationId) { _propertyFlags |= CORRELATION_ID_MASK; _correlationId = correlationId; + _encodedForm = null; } public String getReplyToAsString() @@ -464,13 +501,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setReplyTo(String replyTo) { - setReplyTo((replyTo == null) ? null : new AMQShortString(replyTo)); + setReplyTo((replyTo == null) ? null : AMQShortString.valueOf(replyTo)); } public void setReplyTo(AMQShortString replyTo) { _propertyFlags |= REPLY_TO_MASK; _replyTo = replyTo; + _encodedForm = null; } public long getExpiration() @@ -482,6 +520,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= EXPIRATION_MASK; _expiration = expiration; + _encodedForm = null; } public AMQShortString getMessageId() @@ -498,12 +537,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= MESSAGE_ID_MASK; _messageId = (messageId == null) ? null : new AMQShortString(messageId); + _encodedForm = null; } public void setMessageId(AMQShortString messageId) { _propertyFlags |= MESSAGE_ID_MASK; _messageId = messageId; + _encodedForm = null; } public long getTimestamp() @@ -515,6 +556,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _propertyFlags |= TIMESTAMP_MASK; _timestamp = timestamp; + _encodedForm = null; } public String getTypeAsString() @@ -529,13 +571,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setType(String type) { - setType((type == null) ? null : new AMQShortString(type)); + setType((type == null) ? null : AMQShortString.valueOf(type)); } public void setType(AMQShortString type) { _propertyFlags |= TYPE_MASK; _type = type; + _encodedForm = null; } public String getUserIdAsString() @@ -550,13 +593,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setUserId(String userId) { - setUserId((userId == null) ? null : new AMQShortString(userId)); + setUserId((userId == null) ? null : AMQShortString.valueOf(userId)); } public void setUserId(AMQShortString userId) { _propertyFlags |= USER_ID_MASK; _userId = userId; + _encodedForm = null; } public String getAppIdAsString() @@ -571,13 +615,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setAppId(String appId) { - setAppId((appId == null) ? null : new AMQShortString(appId)); + setAppId((appId == null) ? null : AMQShortString.valueOf(appId)); } public void setAppId(AMQShortString appId) { _propertyFlags |= APPLICATION_ID_MASK; _appId = appId; + _encodedForm = null; } public String getClusterIdAsString() @@ -592,13 +637,14 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setClusterId(String clusterId) { - setClusterId((clusterId == null) ? null : new AMQShortString(clusterId)); + setClusterId((clusterId == null) ? null : AMQShortString.valueOf(clusterId)); } public void setClusterId(AMQShortString clusterId) { _propertyFlags |= CLUSTER_ID_MASK; _clusterId = clusterId; + _encodedForm = null; } public String toString() diff --git a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java index f9580d82b1..554e9373d8 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; +import org.apache.qpid.codec.MarkableDataInput; + import java.io.IOException; /** @@ -28,5 +29,5 @@ import java.io.IOException; */ public interface BodyFactory { - AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException; + AMQBody createBody(MarkableDataInput in, long bodySize) throws AMQFrameDecodingException, IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ByteArrayDataInput.java b/java/common/src/main/java/org/apache/qpid/framing/ByteArrayDataInput.java new file mode 100644 index 0000000000..656185629b --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/framing/ByteArrayDataInput.java @@ -0,0 +1,174 @@ +package org.apache.qpid.framing; + +import org.apache.qpid.codec.MarkableDataInput; + +import java.io.IOException; + +public class ByteArrayDataInput implements ExtendedDataInput, MarkableDataInput +{ + private byte[] _data; + private int _offset; + private int _length; + private int _origin; + private int _mark; + + public ByteArrayDataInput(byte[] data) + { + this(data,0, data.length); + } + + public ByteArrayDataInput(byte[] data, int offset, int length) + { + _data = data; + _offset = offset; + _length = length; + _origin = offset; + _mark = 0; + } + + public void readFully(byte[] b) + { + System.arraycopy(_data,_offset,b,0,b.length); + _offset+=b.length; + } + + public void readFully(byte[] b, int off, int len) + { + System.arraycopy(_data,_offset,b,off,len); + _offset+=len; + } + + public int skipBytes(int n) + { + return _offset+=n; + } + + public boolean readBoolean() + { + return _data[_offset++] != 0; + } + + public byte readByte() + { + return _data[_offset++]; + } + + public int readUnsignedByte() + { + return ((int)_data[_offset++]) & 0xFF; + } + + public short readShort() + { + return (short) (((((int)_data[_offset++]) << 8) & 0xFF00) | (((int)_data[_offset++]) & 0xFF)); + } + + public int readUnsignedShort() + { + return (((((int)_data[_offset++]) << 8) & 0xFF00) | (((int)_data[_offset++]) & 0xFF)); + } + + public char readChar() + { + return (char) (((((int)_data[_offset++]) << 8) & 0xFF00) | (((int)_data[_offset++]) & 0xFF)); + } + + public int readInt() + { + return ((((int)_data[_offset++]) << 24) & 0xFF000000) + | ((((int)_data[_offset++]) << 16) & 0xFF0000) + | ((((int)_data[_offset++]) << 8) & 0xFF00) + | (((int)_data[_offset++]) & 0xFF); + } + + public long readLong() + { + return ((((long)_data[_offset++]) << 56) & 0xFF00000000000000L) + | ((((long)_data[_offset++]) << 48) & 0xFF000000000000L) + | ((((long)_data[_offset++]) << 40) & 0xFF0000000000L) + | ((((long)_data[_offset++]) << 32) & 0xFF00000000L) + | ((((long)_data[_offset++]) << 24) & 0xFF000000L) + | ((((long)_data[_offset++]) << 16) & 0xFF0000L) + | ((((long)_data[_offset++]) << 8) & 0xFF00L) + | (((long)_data[_offset++]) & 0xFFL); + } + + public float readFloat() + { + return Float.intBitsToFloat(readInt()); + } + + public double readDouble() + { + return Double.longBitsToDouble(readLong()); + } + + public AMQShortString readAMQShortString() + { + int length = _data[_offset++] & 0xff; + if(length == 0) + { + return null; + } + else + { + final AMQShortString amqShortString = new AMQShortString(_data, _offset, length); + _offset+=length; + return amqShortString; + } + } + + public String readLine() + { + throw new UnsupportedOperationException(); + } + + public String readUTF() + { + throw new UnsupportedOperationException(); + } + + public int available() + { + return (_origin+_length)-_offset; + } + + + public long skip(long i) + { + _offset+=i; + return i; + } + + public int read(byte[] b) + { + readFully(b); + return b.length; + } + + public int position() + { + return _offset - _origin; + } + + public void position(int position) + { + _offset = position + _origin; + } + + public int length() + { + return _length; + } + + + public void mark(int readAhead) + { + _mark = _offset-_origin; + } + + public void reset() + { + _offset = _origin + _mark; + } +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java index 15bc20c52d..098e3652ad 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.framing; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock @@ -50,7 +50,7 @@ public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQD return frameSize; } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { for (int i = 0; i < _blocks.length; i++) { diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java index aedb35f92a..541d104dc9 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java @@ -20,9 +20,11 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; +import java.nio.ByteBuffer; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.AMQException; @@ -37,10 +39,10 @@ public class ContentBody implements AMQBody { } - public ContentBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException + public ContentBody(DataInput buffer, long size) throws AMQFrameDecodingException, IOException { _payload = new byte[(int)size]; - buffer.read(_payload); + buffer.readFully(_payload); } @@ -59,7 +61,7 @@ public class ContentBody implements AMQBody return _payload == null ? 0 : _payload.length; } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { buffer.write(_payload); } @@ -84,11 +86,62 @@ public class ContentBody implements AMQBody { } + private static class BufferContentBody implements AMQBody + { + private final int _length; + private final int _offset; + private final ByteBuffer _buf; + + private BufferContentBody( ByteBuffer buf, int offset, int length) + { + _length = length; + _offset = offset; + _buf = buf; + } + + public byte getFrameType() + { + return TYPE; + } + + + public int getSize() + { + return _length; + } + public void writePayload(DataOutput buffer) throws IOException + { + if(_buf.hasArray()) + { + buffer.write(_buf.array(), _buf.arrayOffset() + _offset, _length); + } + else + { + byte[] data = new byte[_length]; + ByteBuffer buf = _buf.duplicate(); + + buf.position(_offset); + buf.limit(_offset+_length); + buf.get(data); + buffer.write(data); + } + } + + + public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException + { + throw new RuntimeException("Buffered Body only to be used for outgoing data"); + } + } + + public static AMQFrame createAMQFrame(int channelId, ByteBuffer buf, int offset, int length) + { + return new AMQFrame(channelId, new BufferContentBody(buf, offset, length)); + } public static AMQFrame createAMQFrame(int channelId, ContentBody body) { - final AMQFrame frame = new AMQFrame(channelId, body); - return frame; + return new AMQFrame(channelId, body); } } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java index a0b030ab6b..de2ffe9755 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java @@ -20,9 +20,9 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; import java.io.IOException; +import org.apache.qpid.codec.MarkableDataInput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +42,7 @@ public class ContentBodyFactory implements BodyFactory _log.debug("Creating content body factory"); } - public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException + public AMQBody createBody(MarkableDataInput in, long bodySize) throws AMQFrameDecodingException, IOException { return new ContentBody(in, bodySize); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java index 18d0f26152..8a2ad53157 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java @@ -20,8 +20,9 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; @@ -45,7 +46,7 @@ public class ContentHeaderBody implements AMQBody { } - public ContentHeaderBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException + public ContentHeaderBody(DataInput buffer, long size) throws AMQFrameDecodingException, IOException { classId = buffer.readUnsignedShort(); weight = buffer.readUnsignedShort(); @@ -106,7 +107,7 @@ public class ContentHeaderBody implements AMQBody return 2 + 2 + 8 + 2 + properties.getPropertyListSize(); } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { EncodingUtils.writeUnsignedShort(buffer, classId); EncodingUtils.writeUnsignedShort(buffer, weight); diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java index a474e337b7..c3e4c69ec0 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java @@ -20,9 +20,9 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; import java.io.IOException; +import org.apache.qpid.codec.MarkableDataInput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +42,7 @@ public class ContentHeaderBodyFactory implements BodyFactory _log.debug("Creating content header body factory"); } - public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException + public AMQBody createBody(MarkableDataInput in, long bodySize) throws AMQFrameDecodingException, IOException { // all content headers are the same - it is only the properties that differ. // the content header body further delegates construction of properties diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java index 237929f9a3..ea8358a538 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java @@ -20,8 +20,9 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; @@ -35,7 +36,7 @@ public interface ContentHeaderProperties * Writes the property list to the buffer, in a suitably encoded form. * @param buffer The buffer to write to */ - void writePropertyListPayload(DataOutputStream buffer) throws IOException; + void writePropertyListPayload(DataOutput buffer) throws IOException; /** * Populates the properties from buffer. @@ -43,7 +44,7 @@ public interface ContentHeaderProperties * @param propertyFlags he property flags. * @throws AMQFrameDecodingException when the buffer does not contain valid data */ - void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size) + void populatePropertiesFromBuffer(DataInput buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException; /** diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java index 43ee8cd1f1..48bd52858d 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; @@ -39,7 +40,7 @@ public class ContentHeaderPropertiesFactory } public ContentHeaderProperties createContentHeaderProperties(int classId, int propertyFlags, - DataInputStream buffer, int size) + DataInput buffer, int size) throws AMQFrameDecodingException, IOException { ContentHeaderProperties properties; diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java index 2d7e27405c..e018407509 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java +++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java @@ -219,7 +219,7 @@ public class EncodingUtils return 0; } - public static void writeShortStringBytes(DataOutputStream buffer, String s) throws IOException + public static void writeShortStringBytes(DataOutput buffer, String s) throws IOException { if (s != null) { @@ -243,7 +243,7 @@ public class EncodingUtils } } - public static void writeShortStringBytes(DataOutputStream buffer, AMQShortString s) throws IOException + public static void writeShortStringBytes(DataOutput buffer, AMQShortString s) throws IOException { if (s != null) { @@ -257,7 +257,7 @@ public class EncodingUtils } } - public static void writeLongStringBytes(DataOutputStream buffer, String s) throws IOException + public static void writeLongStringBytes(DataOutput buffer, String s) throws IOException { assert (s == null) || (s.length() <= 0xFFFE); if (s != null) @@ -279,7 +279,7 @@ public class EncodingUtils } } - public static void writeLongStringBytes(DataOutputStream buffer, char[] s) throws IOException + public static void writeLongStringBytes(DataOutput buffer, char[] s) throws IOException { assert (s == null) || (s.length <= 0xFFFE); if (s != null) @@ -300,7 +300,7 @@ public class EncodingUtils } } - public static void writeLongStringBytes(DataOutputStream buffer, byte[] bytes) throws IOException + public static void writeLongStringBytes(DataOutput buffer, byte[] bytes) throws IOException { assert (bytes == null) || (bytes.length <= 0xFFFE); if (bytes != null) @@ -314,13 +314,13 @@ public class EncodingUtils } } - public static void writeUnsignedByte(DataOutputStream buffer, short b) throws IOException + public static void writeUnsignedByte(DataOutput buffer, short b) throws IOException { byte bv = (byte) b; buffer.write(bv); } - public static void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException + public static void writeUnsignedShort(DataOutput buffer, int s) throws IOException { // TODO: Is this comparison safe? Do I need to cast RHS to long? if (s < Short.MAX_VALUE) @@ -340,7 +340,7 @@ public class EncodingUtils return 4; } - public static void writeUnsignedInteger(DataOutputStream buffer, long l) throws IOException + public static void writeUnsignedInteger(DataOutput buffer, long l) throws IOException { // TODO: Is this comparison safe? Do I need to cast RHS to long? if (l < Integer.MAX_VALUE) @@ -360,7 +360,7 @@ public class EncodingUtils } } - public static void writeFieldTableBytes(DataOutputStream buffer, FieldTable table) throws IOException + public static void writeFieldTableBytes(DataOutput buffer, FieldTable table) throws IOException { if (table != null) { @@ -372,12 +372,12 @@ public class EncodingUtils } } - public static void writeContentBytes(DataOutputStream buffer, Content content) + public static void writeContentBytes(DataOutput buffer, Content content) { // TODO: New Content class required for AMQP 0-9. } - public static void writeBooleans(DataOutputStream buffer, boolean[] values) throws IOException + public static void writeBooleans(DataOutput buffer, boolean[] values) throws IOException { byte packedValue = 0; for (int i = 0; i < values.length; i++) @@ -391,13 +391,13 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value) throws IOException + public static void writeBooleans(DataOutput buffer, boolean value) throws IOException { buffer.write(value ? (byte) 1 : (byte) 0); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1) throws IOException + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -409,7 +409,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2) throws IOException + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -426,7 +426,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3) throws IOException + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2, boolean value3) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -448,7 +448,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2, boolean value3, boolean value4) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -476,7 +476,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2, boolean value3, boolean value4, boolean value5) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -509,7 +509,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2, boolean value3, boolean value4, boolean value5, boolean value6) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -547,7 +547,7 @@ public class EncodingUtils buffer.write(packedValue); } - public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + public static void writeBooleans(DataOutput buffer, boolean value0, boolean value1, boolean value2, boolean value3, boolean value4, boolean value5, boolean value6, boolean value7) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -596,7 +596,7 @@ public class EncodingUtils * @param buffer * @param data */ - public static void writeLongstr(DataOutputStream buffer, byte[] data) throws IOException + public static void writeLongstr(DataOutput buffer, byte[] data) throws IOException { if (data != null) { @@ -609,12 +609,12 @@ public class EncodingUtils } } - public static void writeTimestamp(DataOutputStream buffer, long timestamp) throws IOException + public static void writeTimestamp(DataOutput buffer, long timestamp) throws IOException { writeLong(buffer, timestamp); } - public static boolean[] readBooleans(DataInputStream buffer) throws IOException + public static boolean[] readBooleans(DataInput buffer) throws IOException { final byte packedValue = buffer.readByte(); if (packedValue == 0) @@ -641,7 +641,7 @@ public class EncodingUtils return result; } - public static FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException + public static FieldTable readFieldTable(DataInput buffer) throws AMQFrameDecodingException, IOException { long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) @@ -654,19 +654,19 @@ public class EncodingUtils } } - public static Content readContent(DataInputStream buffer) throws AMQFrameDecodingException + public static Content readContent(DataInput buffer) throws AMQFrameDecodingException { // TODO: New Content class required for AMQP 0-9. return null; } - public static AMQShortString readAMQShortString(DataInputStream buffer) throws IOException + public static AMQShortString readAMQShortString(DataInput buffer) throws IOException { return AMQShortString.readFromBuffer(buffer); } - public static String readShortString(DataInputStream buffer) throws IOException + public static String readShortString(DataInput buffer) throws IOException { short length = (short) (((short)buffer.readByte()) & 0xFF); if (length == 0) @@ -681,7 +681,7 @@ public class EncodingUtils // this approach here is valid since we know that all the chars are // ASCII (0-127) byte[] stringBytes = new byte[length]; - buffer.read(stringBytes, 0, length); + buffer.readFully(stringBytes, 0, length); char[] stringChars = new char[length]; for (int i = 0; i < stringChars.length; i++) { @@ -692,7 +692,7 @@ public class EncodingUtils } } - public static String readLongString(DataInputStream buffer) throws IOException + public static String readLongString(DataInput buffer) throws IOException { long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) @@ -707,7 +707,7 @@ public class EncodingUtils // this approach here is valid since we know that all the chars are // ASCII (0-127) byte[] stringBytes = new byte[(int) length]; - buffer.read(stringBytes, 0, (int) length); + buffer.readFully(stringBytes, 0, (int) length); char[] stringChars = new char[(int) length]; for (int i = 0; i < stringChars.length; i++) { @@ -718,7 +718,7 @@ public class EncodingUtils } } - public static byte[] readLongstr(DataInputStream buffer) throws IOException + public static byte[] readLongstr(DataInput buffer) throws IOException { long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) @@ -728,13 +728,13 @@ public class EncodingUtils else { byte[] result = new byte[(int) length]; - buffer.read(result); + buffer.readFully(result); return result; } } - public static long readTimestamp(DataInputStream buffer) throws IOException + public static long readTimestamp(DataInput buffer) throws IOException { // Discard msb from AMQ timestamp // buffer.getUnsignedInt(); @@ -818,12 +818,12 @@ public class EncodingUtils // AMQP_BOOLEAN_PROPERTY_PREFIX - public static void writeBoolean(DataOutputStream buffer, Boolean aBoolean) throws IOException + public static void writeBoolean(DataOutput buffer, boolean aBoolean) throws IOException { buffer.write(aBoolean ? 1 : 0); } - public static boolean readBoolean(DataInputStream buffer) throws IOException + public static boolean readBoolean(DataInput buffer) throws IOException { byte packedValue = buffer.readByte(); @@ -836,12 +836,12 @@ public class EncodingUtils } // AMQP_BYTE_PROPERTY_PREFIX - public static void writeByte(DataOutputStream buffer, Byte aByte) throws IOException + public static void writeByte(DataOutput buffer, byte aByte) throws IOException { buffer.writeByte(aByte); } - public static byte readByte(DataInputStream buffer) throws IOException + public static byte readByte(DataInput buffer) throws IOException { return buffer.readByte(); } @@ -852,12 +852,12 @@ public class EncodingUtils } // AMQP_SHORT_PROPERTY_PREFIX - public static void writeShort(DataOutputStream buffer, Short aShort) throws IOException + public static void writeShort(DataOutput buffer, short aShort) throws IOException { buffer.writeShort(aShort); } - public static short readShort(DataInputStream buffer) throws IOException + public static short readShort(DataInput buffer) throws IOException { return buffer.readShort(); } @@ -868,12 +868,12 @@ public class EncodingUtils } // INTEGER_PROPERTY_PREFIX - public static void writeInteger(DataOutputStream buffer, Integer aInteger) throws IOException + public static void writeInteger(DataOutput buffer, int aInteger) throws IOException { buffer.writeInt(aInteger); } - public static int readInteger(DataInputStream buffer) throws IOException + public static int readInteger(DataInput buffer) throws IOException { return buffer.readInt(); } @@ -884,12 +884,12 @@ public class EncodingUtils } // AMQP_LONG_PROPERTY_PREFIX - public static void writeLong(DataOutputStream buffer, Long aLong) throws IOException + public static void writeLong(DataOutput buffer, long aLong) throws IOException { buffer.writeLong(aLong); } - public static long readLong(DataInputStream buffer) throws IOException + public static long readLong(DataInput buffer) throws IOException { return buffer.readLong(); } @@ -900,12 +900,12 @@ public class EncodingUtils } // Float_PROPERTY_PREFIX - public static void writeFloat(DataOutputStream buffer, Float aFloat) throws IOException + public static void writeFloat(DataOutput buffer, float aFloat) throws IOException { buffer.writeFloat(aFloat); } - public static float readFloat(DataInputStream buffer) throws IOException + public static float readFloat(DataInput buffer) throws IOException { return buffer.readFloat(); } @@ -916,12 +916,12 @@ public class EncodingUtils } // Double_PROPERTY_PREFIX - public static void writeDouble(DataOutputStream buffer, Double aDouble) throws IOException + public static void writeDouble(DataOutput buffer, Double aDouble) throws IOException { buffer.writeDouble(aDouble); } - public static double readDouble(DataInputStream buffer) throws IOException + public static double readDouble(DataInput buffer) throws IOException { return buffer.readDouble(); } @@ -931,7 +931,7 @@ public class EncodingUtils return 8; } - public static byte[] readBytes(DataInputStream buffer) throws IOException + public static byte[] readBytes(DataInput buffer) throws IOException { long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) @@ -941,13 +941,13 @@ public class EncodingUtils else { byte[] dataBytes = new byte[(int)length]; - buffer.read(dataBytes, 0, (int) length); + buffer.readFully(dataBytes, 0, (int) length); return dataBytes; } } - public static void writeBytes(DataOutputStream buffer, byte[] data) throws IOException + public static void writeBytes(DataOutput buffer, byte[] data) throws IOException { if (data != null) { @@ -969,19 +969,19 @@ public class EncodingUtils return encodedByteLength(); } - public static char readChar(DataInputStream buffer) throws IOException + public static char readChar(DataInput buffer) throws IOException { // This is valid as we know that the Character is ASCII 0..127 - return (char) buffer.read(); + return (char) buffer.readByte(); } - public static void writeChar(DataOutputStream buffer, char character) throws IOException + public static void writeChar(DataOutput buffer, char character) throws IOException { // This is valid as we know that the Character is ASCII 0..127 writeByte(buffer, (byte) character); } - public static long readLongAsShortString(DataInputStream buffer) throws IOException + public static long readLongAsShortString(DataInput buffer) throws IOException { short length = (short) buffer.readUnsignedByte(); short pos = 0; @@ -1018,7 +1018,7 @@ public class EncodingUtils return result; } - public static long readUnsignedInteger(DataInputStream buffer) throws IOException + public static long readUnsignedInteger(DataInput buffer) throws IOException { long l = 0xFF & buffer.readByte(); l <<= 8; diff --git a/java/common/src/main/java/org/apache/qpid/framing/ExtendedDataInput.java b/java/common/src/main/java/org/apache/qpid/framing/ExtendedDataInput.java new file mode 100644 index 0000000000..c789d9275e --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/framing/ExtendedDataInput.java @@ -0,0 +1,14 @@ +package org.apache.qpid.framing; + +import java.io.DataInput; + +public interface ExtendedDataInput extends DataInput +{ + AMQShortString readAMQShortString(); + + int available(); + + int position(); + + void position(int position); +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java index 4a126b8504..863e363b87 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java +++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java @@ -25,11 +25,7 @@ import org.slf4j.LoggerFactory; import org.apache.qpid.AMQPInvalidClassException; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import java.math.BigDecimal; import java.util.Collections; import java.util.Enumeration; @@ -44,18 +40,27 @@ import java.util.Set; public class FieldTable { private static final Logger _logger = LoggerFactory.getLogger(FieldTable.class); - private static final String STRICT_AMQP = "STRICT_AMQP"; - private final boolean _strictAMQP = Boolean.valueOf(System.getProperty(STRICT_AMQP, "false")); + private static final String STRICT_AMQP_NAME = "STRICT_AMQP"; + private static final boolean STRICT_AMQP = Boolean.valueOf(System.getProperty(STRICT_AMQP_NAME, "false")); private byte[] _encodedForm; + private int _encodedFormOffset; private LinkedHashMap<AMQShortString, AMQTypedValue> _properties = null; private long _encodedSize; private static final int INITIAL_HASHMAP_CAPACITY = 16; private static final int INITIAL_ENCODED_FORM_SIZE = 256; + private final boolean _strictAMQP; public FieldTable() { + this(STRICT_AMQP); + } + + + public FieldTable(boolean strictAMQP) + { super(); + _strictAMQP = strictAMQP; } /** @@ -64,14 +69,28 @@ public class FieldTable * @param buffer the buffer from which to read data. The length byte must be read already * @param length the length of the field table. Must be > 0. */ - public FieldTable(DataInputStream buffer, long length) throws IOException + public FieldTable(DataInput buffer, long length) throws IOException { this(); _encodedForm = new byte[(int) length]; - buffer.read(_encodedForm); + buffer.readFully(_encodedForm); _encodedSize = length; } + public FieldTable(byte[] encodedForm, int offset, int length) throws IOException + { + this(); + _encodedForm = encodedForm; + _encodedFormOffset = offset; + _encodedSize = length; + } + + + public boolean isClean() + { + return _encodedForm != null; + } + public AMQTypedValue getProperty(AMQShortString string) { checkPropertyName(string); @@ -181,7 +200,7 @@ public class FieldTable public Boolean getBoolean(String string) { - return getBoolean(new AMQShortString(string)); + return getBoolean(AMQShortString.valueOf(string)); } public Boolean getBoolean(AMQShortString string) @@ -199,7 +218,7 @@ public class FieldTable public Byte getByte(String string) { - return getByte(new AMQShortString(string)); + return getByte(AMQShortString.valueOf(string)); } public Byte getByte(AMQShortString string) @@ -217,7 +236,7 @@ public class FieldTable public Short getShort(String string) { - return getShort(new AMQShortString(string)); + return getShort(AMQShortString.valueOf(string)); } public Short getShort(AMQShortString string) @@ -235,7 +254,7 @@ public class FieldTable public Integer getInteger(String string) { - return getInteger(new AMQShortString(string)); + return getInteger(AMQShortString.valueOf(string)); } public Integer getInteger(AMQShortString string) @@ -253,7 +272,7 @@ public class FieldTable public Long getLong(String string) { - return getLong(new AMQShortString(string)); + return getLong(AMQShortString.valueOf(string)); } public Long getLong(AMQShortString string) @@ -271,7 +290,7 @@ public class FieldTable public Float getFloat(String string) { - return getFloat(new AMQShortString(string)); + return getFloat(AMQShortString.valueOf(string)); } public Float getFloat(AMQShortString string) @@ -289,7 +308,7 @@ public class FieldTable public Double getDouble(String string) { - return getDouble(new AMQShortString(string)); + return getDouble(AMQShortString.valueOf(string)); } public Double getDouble(AMQShortString string) @@ -307,7 +326,7 @@ public class FieldTable public String getString(String string) { - return getString(new AMQShortString(string)); + return getString(AMQShortString.valueOf(string)); } public String getString(AMQShortString string) @@ -330,7 +349,7 @@ public class FieldTable public Character getCharacter(String string) { - return getCharacter(new AMQShortString(string)); + return getCharacter(AMQShortString.valueOf(string)); } public Character getCharacter(AMQShortString string) @@ -348,7 +367,7 @@ public class FieldTable public byte[] getBytes(String string) { - return getBytes(new AMQShortString(string)); + return getBytes(AMQShortString.valueOf(string)); } public byte[] getBytes(AMQShortString string) @@ -374,7 +393,7 @@ public class FieldTable */ public FieldTable getFieldTable(String string) { - return getFieldTable(new AMQShortString(string)); + return getFieldTable(AMQShortString.valueOf(string)); } /** @@ -401,7 +420,7 @@ public class FieldTable public Object getObject(String string) { - return getObject(new AMQShortString(string)); + return getObject(AMQShortString.valueOf(string)); } public Object getObject(AMQShortString string) @@ -447,7 +466,7 @@ public class FieldTable // ************ Setters public Object setBoolean(String string, Boolean b) { - return setBoolean(new AMQShortString(string), b); + return setBoolean(AMQShortString.valueOf(string), b); } public Object setBoolean(AMQShortString string, Boolean b) @@ -457,7 +476,7 @@ public class FieldTable public Object setByte(String string, Byte b) { - return setByte(new AMQShortString(string), b); + return setByte(AMQShortString.valueOf(string), b); } public Object setByte(AMQShortString string, Byte b) @@ -467,7 +486,7 @@ public class FieldTable public Object setShort(String string, Short i) { - return setShort(new AMQShortString(string), i); + return setShort(AMQShortString.valueOf(string), i); } public Object setShort(AMQShortString string, Short i) @@ -475,29 +494,29 @@ public class FieldTable return setProperty(string, AMQType.SHORT.asTypedValue(i)); } - public Object setInteger(String string, Integer i) + public Object setInteger(String string, int i) { - return setInteger(new AMQShortString(string), i); + return setInteger(AMQShortString.valueOf(string), i); } - public Object setInteger(AMQShortString string, Integer i) + public Object setInteger(AMQShortString string, int i) { - return setProperty(string, AMQType.INT.asTypedValue(i)); + return setProperty(string, AMQTypedValue.createAMQTypedValue(i)); } - public Object setLong(String string, Long l) + public Object setLong(String string, long l) { - return setLong(new AMQShortString(string), l); + return setLong(AMQShortString.valueOf(string), l); } - public Object setLong(AMQShortString string, Long l) + public Object setLong(AMQShortString string, long l) { - return setProperty(string, AMQType.LONG.asTypedValue(l)); + return setProperty(string, AMQTypedValue.createAMQTypedValue(l)); } public Object setFloat(String string, Float f) { - return setFloat(new AMQShortString(string), f); + return setFloat(AMQShortString.valueOf(string), f); } public Object setFloat(AMQShortString string, Float v) @@ -507,7 +526,7 @@ public class FieldTable public Object setDouble(String string, Double d) { - return setDouble(new AMQShortString(string), d); + return setDouble(AMQShortString.valueOf(string), d); } public Object setDouble(AMQShortString string, Double v) @@ -517,7 +536,7 @@ public class FieldTable public Object setString(String string, String s) { - return setString(new AMQShortString(string), s); + return setString(AMQShortString.valueOf(string), s); } public Object setAsciiString(AMQShortString string, String value) @@ -546,7 +565,7 @@ public class FieldTable public Object setChar(String string, char c) { - return setChar(new AMQShortString(string), c); + return setChar(AMQShortString.valueOf(string), c); } public Object setChar(AMQShortString string, char c) @@ -556,7 +575,7 @@ public class FieldTable public Object setBytes(String string, byte[] b) { - return setBytes(new AMQShortString(string), b); + return setBytes(AMQShortString.valueOf(string), b); } public Object setBytes(AMQShortString string, byte[] bytes) @@ -566,7 +585,7 @@ public class FieldTable public Object setBytes(String string, byte[] bytes, int start, int length) { - return setBytes(new AMQShortString(string), bytes, start, length); + return setBytes(AMQShortString.valueOf(string), bytes, start, length); } public Object setBytes(AMQShortString string, byte[] bytes, int start, int length) @@ -579,7 +598,7 @@ public class FieldTable public Object setObject(String string, Object o) { - return setObject(new AMQShortString(string), o); + return setObject(AMQShortString.valueOf(string), o); } public Object setTimestamp(AMQShortString string, long datetime) @@ -617,7 +636,7 @@ public class FieldTable */ public Object setFieldTable(String string, FieldTable ftValue) { - return setFieldTable(new AMQShortString(string), ftValue); + return setFieldTable(AMQShortString.valueOf(string), ftValue); } /** @@ -681,7 +700,7 @@ public class FieldTable public boolean isNullStringValue(String name) { - AMQTypedValue value = getProperty(new AMQShortString(name)); + AMQTypedValue value = getProperty(AMQShortString.valueOf(name)); return (value != null) && (value.getType() == AMQType.VOID); } @@ -713,7 +732,7 @@ public class FieldTable public boolean itemExists(String string) { - return itemExists(new AMQShortString(string)); + return itemExists(AMQShortString.valueOf(string)); } public String toString() @@ -769,7 +788,7 @@ public class FieldTable // ************************* Byte Buffer Processing - public void writeToBuffer(DataOutputStream buffer) throws IOException + public void writeToBuffer(DataOutput buffer) throws IOException { final boolean trace = _logger.isDebugEnabled(); @@ -919,7 +938,7 @@ public class FieldTable public boolean containsKey(String key) { - return containsKey(new AMQShortString(key)); + return containsKey(AMQShortString.valueOf(key)); } public Set<String> keys() @@ -942,7 +961,7 @@ public class FieldTable public Object get(String key) { - return get(new AMQShortString(key)); + return get(AMQShortString.valueOf(key)); } public Object get(AMQShortString key) @@ -958,7 +977,7 @@ public class FieldTable public Object remove(String key) { - return remove(new AMQShortString(key)); + return remove(AMQShortString.valueOf(key)); } @@ -1005,12 +1024,12 @@ public class FieldTable return _properties.keySet(); } - private void putDataInBuffer(DataOutputStream buffer) throws IOException + private void putDataInBuffer(DataOutput buffer) throws IOException { if (_encodedForm != null) { - buffer.write(_encodedForm); + buffer.write(_encodedForm,_encodedFormOffset,(int)_encodedSize); } else if (_properties != null) { @@ -1039,9 +1058,8 @@ public class FieldTable private void setFromBuffer() throws AMQFrameDecodingException, IOException { - final ByteArrayInputStream in = new ByteArrayInputStream(_encodedForm); - DataInputStream buffer = new DataInputStream(in); - final boolean trace = _logger.isDebugEnabled(); + ByteArrayDataInput baid = new ByteArrayDataInput(_encodedForm, _encodedFormOffset, (int)_encodedSize); + if (_encodedSize > 0) { @@ -1051,12 +1069,12 @@ public class FieldTable do { - final AMQShortString key = EncodingUtils.readAMQShortString(buffer); - AMQTypedValue value = AMQTypedValue.readFromBuffer(buffer); + final AMQShortString key = baid.readAMQShortString(); + AMQTypedValue value = AMQTypedValue.readFromBuffer(baid); _properties.put(key, value); } - while (in.available() > 0); + while (baid.available() > 0); } @@ -1101,7 +1119,7 @@ public class FieldTable FieldTable table = new FieldTable(); for(Map.Entry<String,Object> entry : map.entrySet()) { - table.put(new AMQShortString(entry.getKey()), entry.getValue()); + table.put(AMQShortString.valueOf(entry.getKey()), entry.getValue()); } return table; diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java index 438a46f28b..af0c5b845c 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.framing; +import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; @@ -30,7 +31,7 @@ public class FieldTableFactory return new FieldTable(); } - public static FieldTable newFieldTable(DataInputStream byteBuffer, long length) throws AMQFrameDecodingException, IOException + public static FieldTable newFieldTable(DataInput byteBuffer, long length) throws AMQFrameDecodingException, IOException { return new FieldTable(byteBuffer, length); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java index a6ce721a50..95b6246717 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java @@ -21,7 +21,7 @@ package org.apache.qpid.framing; import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; @@ -56,7 +56,7 @@ public class HeartbeatBody implements AMQBody return 0;//heartbeats we generate have no payload } - public void writePayload(DataOutputStream buffer) + public void writePayload(DataOutput buffer) { } diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java index dfc49c6167..971caca41a 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java @@ -20,12 +20,13 @@ */ package org.apache.qpid.framing; -import java.io.DataInputStream; +import org.apache.qpid.codec.MarkableDataInput; public class HeartbeatBodyFactory implements BodyFactory { - public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException + public AMQBody createBody(MarkableDataInput in, long bodySize) throws AMQFrameDecodingException { return new HeartbeatBody(); } + } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java index 8c018316f0..2925724dc2 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java @@ -21,13 +21,10 @@ package org.apache.qpid.framing; import org.apache.qpid.AMQException; +import org.apache.qpid.codec.MarkableDataInput; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; import java.util.Arrays; public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQDataBlock @@ -66,7 +63,7 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData pv.equals(ProtocolVersion.v0_91) ? 1 : pv.getMinorVersion()); } - public ProtocolInitiation(DataInputStream in) throws IOException + public ProtocolInitiation(MarkableDataInput in) throws IOException { _protocolHeader = new byte[4]; in.read(_protocolHeader); @@ -82,7 +79,7 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData return 4 + 1 + 1 + 1 + 1; } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { buffer.write(_protocolHeader); @@ -143,7 +140,7 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData * @return true if we have enough data to decode the PI frame fully, false if more * data is required */ - public boolean decodable(DataInputStream in) throws IOException + public boolean decodable(MarkableDataInput in) throws IOException { return (in.available() >= 8); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java index d2925d13a8..dd854dd498 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java @@ -21,7 +21,7 @@ package org.apache.qpid.framing; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; public class SmallCompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock @@ -69,7 +69,7 @@ public class SmallCompositeAMQDataBlock extends AMQDataBlock implements Encodabl return frameSize; } - public void writePayload(DataOutputStream buffer) throws IOException + public void writePayload(DataOutput buffer) throws IOException { if (_firstFrame != null) { diff --git a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java index ed9136f7c9..e770fdd7e4 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java +++ b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java @@ -23,6 +23,7 @@ package org.apache.qpid.framing; import java.io.DataInputStream; import java.io.IOException; +import org.apache.qpid.codec.MarkableDataInput; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; import org.slf4j.Logger; @@ -145,7 +146,7 @@ public class VersionSpecificRegistry } - public AMQMethodBody get(short classID, short methodID, DataInputStream in, long size) throws AMQFrameDecodingException, IOException + public AMQMethodBody get(short classID, short methodID, MarkableDataInput in, long size) throws AMQFrameDecodingException, IOException { AMQMethodBodyInstanceFactory bodyFactory; try diff --git a/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/java/common/src/main/java/org/apache/qpid/transport/Connection.java index b78433052c..dee5f696b9 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Connection.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java @@ -383,13 +383,19 @@ public class Connection extends ConnectionInvoker public void received(ProtocolEvent event) { - log.debug("RECV: [%s] %s", this, event); + if(log.isDebugEnabled()) + { + log.debug("RECV: [%s] %s", this, event); + } event.delegate(this, delegate); } public void send(ProtocolEvent event) { - log.debug("SEND: [%s] %s", this, event); + if(log.isDebugEnabled()) + { + log.debug("SEND: [%s] %s", this, event); + } Sender s = sender; if (s == null) { @@ -400,8 +406,15 @@ public class Connection extends ConnectionInvoker public void flush() { - log.debug("FLUSH: [%s]", this); - sender.flush(); + if(log.isDebugEnabled()) + { + log.debug("FLUSH: [%s]", this); + } + final Sender<ProtocolEvent> theSender = sender; + if(theSender != null) + { + theSender.flush(); + } } protected void invoke(Method method) diff --git a/java/common/src/main/java/org/apache/qpid/transport/Header.java b/java/common/src/main/java/org/apache/qpid/transport/Header.java index 9439e5e0de..543856ca39 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Header.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Header.java @@ -20,13 +20,7 @@ */ package org.apache.qpid.transport; -import org.apache.qpid.transport.network.Frame; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.LinkedHashMap; -import java.nio.ByteBuffer; +import java.util.*; /** @@ -35,45 +29,87 @@ import java.nio.ByteBuffer; * @author Rafael H. Schloming */ -public class Header { +public class Header +{ - private final Struct[] structs; + private final DeliveryProperties _deliveryProps; + private final MessageProperties _messageProps; + private final List<Struct> _nonStandardProps; - public Header(List<Struct> structs) + public Header(DeliveryProperties deliveryProps, MessageProperties messageProps) { - this(structs.toArray(new Struct[structs.size()])); + this(deliveryProps, messageProps, null); } - public Header(Struct ... structs) + public Header(DeliveryProperties deliveryProps, MessageProperties messageProps, List<Struct> nonStandardProps) { - this.structs = structs; + _deliveryProps = deliveryProps; + _messageProps = messageProps; + _nonStandardProps = nonStandardProps; } public Struct[] getStructs() { + int size = 0; + if(_deliveryProps != null) + { + size++; + } + if(_messageProps != null) + { + size++; + } + if(_nonStandardProps != null) + { + size+=_nonStandardProps.size(); + } + Struct[] structs = new Struct[size]; + int index = 0; + if(_deliveryProps != null) + { + structs[index++] = _deliveryProps; + } + if(_messageProps != null) + { + structs[index++] = _messageProps; + } + if(_nonStandardProps != null) + { + for(Struct struct : _nonStandardProps) + { + structs[index++] = struct; + } + } + return structs; } + public DeliveryProperties getDeliveryProperties() + { + return _deliveryProps; + } - public <T> T get(Class<T> klass) + public MessageProperties getMessageProperties() { - for (Struct st : structs) - { - if (klass.isInstance(st)) - { - return (T) st; - } - } + return _messageProps; + } - return null; + public List<Struct> getNonStandardProperties() + { + return _nonStandardProps; } public String toString() { - StringBuffer str = new StringBuffer(); + StringBuilder str = new StringBuilder(); str.append(" Header("); boolean first = true; - for (Struct s : structs) + if(_deliveryProps !=null) + { + first=false; + str.append(_deliveryProps); + } + if(_messageProps != null) { if (first) { @@ -83,9 +119,24 @@ public class Header { { str.append(", "); } - str.append(s); + str.append(_messageProps); + } + if(_nonStandardProps != null) + { + for (Struct s : _nonStandardProps) + { + if (first) + { + first = false; + } + else + { + str.append(", "); + } + str.append(s); + } } - str.append(")"); + str.append(')'); return str.toString(); } diff --git a/java/common/src/main/java/org/apache/qpid/transport/Range.java b/java/common/src/main/java/org/apache/qpid/transport/Range.java index f4335dc8a6..f976337788 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Range.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Range.java @@ -21,6 +21,8 @@ package org.apache.qpid.transport; import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import static org.apache.qpid.util.Serial.*; @@ -32,94 +34,259 @@ import static org.apache.qpid.util.Serial.*; * @author Rafael H. Schloming */ -public final class Range +public abstract class Range implements RangeSet { - private final int lower; - private final int upper; + public static Range newInstance(int point) + { + return new PointImpl(point); + } + + public static Range newInstance(int lower, int upper) + { + return lower == upper ? new PointImpl(lower) : new RangeImpl(lower, upper); + } + + public abstract int getLower(); + + public abstract int getUpper(); + + public abstract boolean includes(int value); + + public abstract boolean includes(Range range); + + public abstract boolean intersects(Range range); + + public abstract boolean touches(Range range); + + public abstract Range span(Range range); + + public abstract List<Range> subtract(Range range); + + + public Range intersect(Range range) + { + int l = max(getLower(), range.getLower()); + int r = min(getUpper(), range.getUpper()); + if (gt(l, r)) + { + return null; + } + else + { + return newInstance(l, r); + } + } + + + + public int size() + { + return 1; + } - public Range(int lower, int upper) + public Iterator<Range> iterator() { - this.lower = lower; - this.upper = upper; + return new RangeIterator(); } - public int getLower() + public Range getFirst() { - return lower; + return this; } - public int getUpper() + public Range getLast() { - return upper; + return this; } - public boolean includes(int value) + public void add(Range range) { - return le(lower, value) && le(value, upper); + throw new UnsupportedOperationException(); } - public boolean includes(Range range) + public void add(int lower, int upper) { - return includes(range.lower) && includes(range.upper); + throw new UnsupportedOperationException(); } - public boolean intersects(Range range) + public void add(int value) { - return (includes(range.lower) || includes(range.upper) || - range.includes(lower) || range.includes(upper)); + throw new UnsupportedOperationException(); } - public boolean touches(Range range) + public void clear() { - return (intersects(range) || - includes(range.upper + 1) || includes(range.lower - 1) || - range.includes(upper + 1) || range.includes(lower - 1)); + throw new UnsupportedOperationException(); } - public Range span(Range range) + public RangeSet copy() { - return new Range(min(lower, range.lower), max(upper, range.upper)); + RangeSet rangeSet = RangeSetFactory.createRangeSet(); + rangeSet.add(this); + return rangeSet; } - public List<Range> subtract(Range range) + private static class PointImpl extends Range { - List<Range> result = new ArrayList<Range>(); + private final int point; + + private PointImpl(int point) + { + this.point = point; + } + + public int getLower() + { + return point; + } + + public int getUpper() + { + return point; + } + + public boolean includes(int value) + { + return value == point; + } + + + public boolean includes(Range range) + { + return range.getLower() == point && range.getUpper() == point; + } + + public boolean intersects(Range range) + { + return range.includes(point); + } - if (includes(range.lower) && le(lower, range.lower - 1)) + public boolean touches(Range range) { - result.add(new Range(lower, range.lower - 1)); + return intersects(range) || + includes(range.getUpper() + 1) || includes(range.getLower() - 1) || + range.includes(point + 1) || range.includes(point - 1); } - if (includes(range.upper) && le(range.upper + 1, upper)) + public Range span(Range range) { - result.add(new Range(range.upper + 1, upper)); + return newInstance(min(point, range.getLower()), max(point, range.getUpper())); } - if (result.isEmpty() && !range.includes(this)) + public List<Range> subtract(Range range) { - result.add(this); + if(range.includes(point)) + { + return Collections.emptyList(); + } + else + { + return Collections.singletonList((Range) this); + } } - return result; } - public Range intersect(Range range) + private static class RangeImpl extends Range { - int l = max(lower, range.lower); - int r = min(upper, range.upper); - if (gt(l, r)) + private final int lower; + private final int upper; + + private RangeImpl(int lower, int upper) { - return null; + this.lower = lower; + this.upper = upper; } - else + + public int getLower() + { + return lower; + } + + public int getUpper() + { + return upper; + } + + public boolean includes(int value) + { + return le(lower, value) && le(value, upper); + } + + public boolean includes(Range range) + { + return includes(range.getLower()) && includes(range.getUpper()); + } + + public boolean intersects(Range range) + { + return (includes(range.getLower()) || includes(range.getUpper()) || + range.includes(lower) || range.includes(upper)); + } + + public boolean touches(Range range) + { + return (intersects(range) || + includes(range.getUpper() + 1) || includes(range.getLower() - 1) || + range.includes(upper + 1) || range.includes(lower - 1)); + } + + public Range span(Range range) + { + return newInstance(min(lower, range.getLower()), max(upper, range.getUpper())); + } + + public List<Range> subtract(Range range) + { + List<Range> result = new ArrayList<Range>(); + + if (includes(range.getLower()) && le(lower, range.getLower() - 1)) + { + result.add(newInstance(lower, range.getLower() - 1)); + } + + if (includes(range.getUpper()) && le(range.getUpper() + 1, upper)) + { + result.add(newInstance(range.getUpper() + 1, upper)); + } + + if (result.isEmpty() && !range.includes(this)) + { + result.add(this); + } + + return result; + } + + + public String toString() { - return new Range(l, r); + return "[" + lower + ", " + upper + "]"; } } - public String toString() + + private class RangeIterator implements Iterator<Range> { - return "[" + lower + ", " + upper + "]"; - } + private boolean atFirst = true; + + public boolean hasNext() + { + return atFirst; + } + + public Range next() + { + + Range range = atFirst ? Range.this : null; + atFirst = false; + return range; + } + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java index 3850dc162b..34ebd02777 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java +++ b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java @@ -20,9 +20,7 @@ */ package org.apache.qpid.transport; -import java.util.Iterator; -import java.util.ListIterator; -import java.util.LinkedList; +import java.util.*; import static org.apache.qpid.util.Serial.*; @@ -32,121 +30,29 @@ import static org.apache.qpid.util.Serial.*; * @author Rafael H. Schloming */ -public final class RangeSet implements Iterable<Range> +public interface RangeSet extends Iterable<Range> { - private LinkedList<Range> ranges = new LinkedList<Range>(); - - public int size() - { - return ranges.size(); - } - - public Iterator<Range> iterator() - { - return ranges.iterator(); - } - - public Range getFirst() - { - return ranges.getFirst(); - } - - public Range getLast() - { - return ranges.getLast(); - } - - public boolean includes(Range range) - { - for (Range r : this) - { - if (r.includes(range)) - { - return true; - } - } - - return false; - } - - public boolean includes(int n) - { - for (Range r : this) - { - if (r.includes(n)) - { - return true; - } - } - - return false; - } - - public void add(Range range) - { - ListIterator<Range> it = ranges.listIterator(); - - while (it.hasNext()) - { - Range next = it.next(); - if (range.touches(next)) - { - it.remove(); - range = range.span(next); - } - else if (lt(range.getUpper(), next.getLower())) - { - it.previous(); - it.add(range); - return; - } - } - - it.add(range); - } - - public void add(int lower, int upper) - { - add(new Range(lower, upper)); - } - - public void add(int value) - { - add(value, value); - } - - public void clear() - { - ranges.clear(); - } - - public RangeSet copy() - { - RangeSet copy = new RangeSet(); - copy.ranges.addAll(ranges); - return copy; - } - - public String toString() - { - StringBuffer str = new StringBuffer(); - str.append("{"); - boolean first = true; - for (Range range : ranges) - { - if (first) - { - first = false; - } - else - { - str.append(", "); - } - str.append(range); - } - str.append("}"); - return str.toString(); - } + int size(); + + Iterator<Range> iterator(); + + Range getFirst(); + + Range getLast(); + + boolean includes(Range range); + + boolean includes(int n); + + void add(Range range); + + void add(int lower, int upper); + + void add(int value); + + void clear(); + + RangeSet copy(); } diff --git a/java/common/src/main/java/org/apache/qpid/transport/RangeSetFactory.java b/java/common/src/main/java/org/apache/qpid/transport/RangeSetFactory.java new file mode 100644 index 0000000000..0f19d7e2b2 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/RangeSetFactory.java @@ -0,0 +1,34 @@ +/* + * + * 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.transport; + +public class RangeSetFactory +{ + public static RangeSet createRangeSet() + { + return new RangeSetImpl(); + } + + public static RangeSet createRangeSet(int size) + { + return new RangeSetImpl(size); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/RangeSetImpl.java b/java/common/src/main/java/org/apache/qpid/transport/RangeSetImpl.java new file mode 100644 index 0000000000..f2540afb40 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/RangeSetImpl.java @@ -0,0 +1,178 @@ +/* + * + * 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.transport; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import static org.apache.qpid.util.Serial.lt; + +public class RangeSetImpl implements RangeSet +{ + + private List<Range> ranges; + + public RangeSetImpl() + { + ranges = new ArrayList<Range>(); + } + + public RangeSetImpl(int size) + { + ranges = new ArrayList<Range>(size); + } + + + public RangeSetImpl(org.apache.qpid.transport.RangeSetImpl copy) + { + ranges = new ArrayList<Range>(copy.ranges); + } + + public int size() + { + return ranges.size(); + } + + public Iterator<Range> iterator() + { + return ranges.iterator(); + } + + public Range getFirst() + { + return ranges.get(0); + } + + public Range getLast() + { + return ranges.get(ranges.size() - 1); + } + + public boolean includes(Range range) + { + for (Range r : this) + { + if (r.includes(range)) + { + return true; + } + } + + return false; + } + + public boolean includes(int n) + { + for (Range r : this) + { + if (r.includes(n)) + { + return true; + } + } + + return false; + } + + public void add(Range range) + { + ListIterator<Range> it = ranges.listIterator(); + + while (it.hasNext()) + { + Range next = it.next(); + if (range.touches(next)) + { + it.remove(); + range = range.span(next); + } + else if (lt(range.getUpper(), next.getLower())) + { + it.previous(); + it.add(range); + return; + } + } + + it.add(range); + } + + public void add(int lower, int upper) + { + switch(ranges.size()) + { + case 0: + ranges.add(Range.newInstance(lower, upper)); + break; + + case 1: + Range first = ranges.get(0); + if(first.getUpper() + 1 >= lower && upper >= first.getUpper()) + { + ranges.set(0, Range.newInstance(first.getLower(), upper)); + break; + } + + default: + add(Range.newInstance(lower, upper)); + } + + + } + + public void add(int value) + { + add(value, value); + } + + public void clear() + { + ranges.clear(); + } + + public RangeSet copy() + { + return new org.apache.qpid.transport.RangeSetImpl(this); + } + + public String toString() + { + StringBuffer str = new StringBuffer(); + str.append("{"); + boolean first = true; + for (Range range : ranges) + { + if (first) + { + first = false; + } + else + { + str.append(", "); + } + str.append(range); + } + str.append("}"); + return str.toString(); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java index 321e5256b2..3e823ba6fe 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Session.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java @@ -247,7 +247,7 @@ public class Session extends SessionInvoker synchronized (processedLock) { incomingInit = false; - processed = new RangeSet(); + processed = RangeSetFactory.createRangeSet(); } } @@ -276,22 +276,22 @@ public class Session extends SessionInvoker else if (m instanceof MessageTransfer) { MessageTransfer xfr = (MessageTransfer)m; - - if (xfr.getHeader() != null) + + Header header = xfr.getHeader(); + + if (header != null) { - if (xfr.getHeader().get(DeliveryProperties.class) != null) + if (header.getDeliveryProperties() != null) { - xfr.getHeader().get(DeliveryProperties.class).setRedelivered(true); + header.getDeliveryProperties().setRedelivered(true); } else { - Struct[] structs = xfr.getHeader().getStructs(); DeliveryProperties deliveryProps = new DeliveryProperties(); deliveryProps.setRedelivered(true); - - List<Struct> list = Arrays.asList(structs); - list.add(deliveryProps); - xfr.setHeader(new Header(list)); + + xfr.setHeader(new Header(deliveryProps, header.getMessageProperties(), + header.getNonStandardProperties())); } } @@ -299,7 +299,7 @@ public class Session extends SessionInvoker { DeliveryProperties deliveryProps = new DeliveryProperties(); deliveryProps.setRedelivered(true); - xfr.setHeader(new Header(deliveryProps)); + xfr.setHeader(new Header(deliveryProps, null, null)); } } sessionCommandPoint(m.getId(), 0); @@ -394,38 +394,46 @@ public class Session extends SessionInvoker public void processed(int command) { - processed(new Range(command, command)); + processed(command, command); } - public void processed(int lower, int upper) + public void processed(Range range) { - processed(new Range(lower, upper)); + processed(range.getLower(), range.getUpper()); } - public void processed(Range range) + public void processed(int lower, int upper) { - log.debug("%s processed(%s) %s %s", this, range, syncPoint, maxProcessed); + if(log.isDebugEnabled()) + { + log.debug("%s processed([%d,%d]) %s %s", this, lower, upper, syncPoint, maxProcessed); + } boolean flush; synchronized (processedLock) { - log.debug("%s", processed); + if(log.isDebugEnabled()) + { + log.debug("%s", processed); + } - if (ge(range.getUpper(), commandsIn)) + if (ge(upper, commandsIn)) { throw new IllegalArgumentException - ("range exceeds max received command-id: " + range); + ("range exceeds max received command-id: " + Range.newInstance(lower, upper)); } - processed.add(range); + processed.add(lower, upper); + Range first = processed.getFirst(); - int lower = first.getLower(); - int upper = first.getUpper(); + + int flower = first.getLower(); + int fupper = first.getUpper(); int old = maxProcessed; - if (le(lower, maxProcessed + 1)) + if (le(flower, maxProcessed + 1)) { - maxProcessed = max(maxProcessed, upper); + maxProcessed = max(maxProcessed, fupper); } boolean synced = ge(maxProcessed, syncPoint); flush = lt(old, syncPoint) && synced; @@ -442,7 +450,7 @@ public class Session extends SessionInvoker void flushExpected() { - RangeSet rs = new RangeSet(); + RangeSet rs = RangeSetFactory.createRangeSet(); synchronized (processedLock) { if (incomingInit) @@ -478,7 +486,7 @@ public class Session extends SessionInvoker { synchronized (processedLock) { - RangeSet newProcessed = new RangeSet(); + RangeSet newProcessed = RangeSetFactory.createRangeSet(); for (Range pr : processed) { for (Range kr : kc) @@ -534,7 +542,12 @@ public class Session extends SessionInvoker { maxComplete = max(maxComplete, upper); } - log.debug("%s commands remaining: %s", this, commandsOut - maxComplete); + + if(log.isDebugEnabled()) + { + log.debug("%s commands remaining: %s", this, commandsOut - maxComplete); + } + commands.notifyAll(); return gt(maxComplete, old); } diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java index 3341149e5f..028b912ba1 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java @@ -91,21 +91,38 @@ public class SessionDelegate { RangeSet ranges = cmp.getCommands(); RangeSet known = null; - if (cmp.getTimelyReply()) - { - known = new RangeSet(); - } if (ranges != null) { - for (Range range : ranges) + if(ranges.size() == 1) { + Range range = ranges.getFirst(); boolean advanced = ssn.complete(range.getLower(), range.getUpper()); - if (advanced && known != null) + + if(advanced && cmp.getTimelyReply()) { - known.add(range); + known = range; } } + else + { + if (cmp.getTimelyReply()) + { + known = RangeSetFactory.createRangeSet(); + } + for (Range range : ranges) + { + boolean advanced = ssn.complete(range.getLower(), range.getUpper()); + if (advanced && known != null) + { + known.add(range); + } + } + } + } + else if (cmp.getTimelyReply()) + { + known = RangeSetFactory.createRangeSet(); } if (known != null) diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java index 09ce6a7eb1..6ff3b21400 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java @@ -29,12 +29,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.qpid.transport.Binary; -import org.apache.qpid.transport.RangeSet; -import org.apache.qpid.transport.Struct; -import org.apache.qpid.transport.Type; - -import static org.apache.qpid.transport.util.Functions.*; +import org.apache.qpid.transport.*; /** @@ -194,18 +189,19 @@ abstract class AbstractDecoder implements Decoder public RangeSet readSequenceSet() { int count = readUint16()/8; - if (count == 0) + switch(count) { - return null; - } - else - { - RangeSet ranges = new RangeSet(); - for (int i = 0; i < count; i++) - { - ranges.add(readSequenceNo(), readSequenceNo()); - } - return ranges; + case 0: + return null; + case 1: + return Range.newInstance(readSequenceNo(), readSequenceNo()); + default: + RangeSet ranges = RangeSetFactory.createRangeSet(count); + for (int i = 0; i < count; i++) + { + ranges.add(readSequenceNo(), readSequenceNo()); + } + return ranges; } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java index 4486b03a67..d9150bed65 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java @@ -70,6 +70,16 @@ public final class BBEncoder extends AbstractEncoder return slice; } + public int position() + { + return out.position(); + } + + public ByteBuffer underlyingBuffer() + { + return out; + } + private void grow(int size) { ByteBuffer old = out; diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java index 1a85ab88a5..8cd5c29f6d 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java @@ -26,13 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.qpid.transport.Header; -import org.apache.qpid.transport.Method; -import org.apache.qpid.transport.ProtocolError; -import org.apache.qpid.transport.ProtocolEvent; -import org.apache.qpid.transport.ProtocolHeader; -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.Struct; +import org.apache.qpid.transport.*; import org.apache.qpid.transport.codec.BBDecoder; /** @@ -198,12 +192,33 @@ public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate break; case HEADER: command = getIncompleteCommand(channel); - List<Struct> structs = new ArrayList<Struct>(2); + List<Struct> structs = null; + DeliveryProperties deliveryProps = null; + MessageProperties messageProps = null; + while (dec.hasRemaining()) { - structs.add(dec.readStruct32()); + Struct struct = dec.readStruct32(); + if(struct instanceof DeliveryProperties && deliveryProps == null) + { + deliveryProps = (DeliveryProperties) struct; + } + else if(struct instanceof MessageProperties && messageProps == null) + { + messageProps = (MessageProperties) struct; + } + else + { + if(structs == null) + { + structs = new ArrayList<Struct>(2); + } + structs.add(struct); + } + } - command.setHeader(new Header(structs)); + command.setHeader(new Header(deliveryProps,messageProps,structs)); + if (frame.isLastSegment()) { setIncompleteCommand(channel, null); diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java index 685034d1a9..6ac9df9bc3 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java @@ -87,27 +87,35 @@ public final class Disassembler implements Sender<ProtocolEvent>, ProtocolDelega } } + private final ByteBuffer _frameHeader = ByteBuffer.allocate(HEADER_SIZE); + + { + _frameHeader.order(ByteOrder.BIG_ENDIAN); + } + private void frame(byte flags, byte type, byte track, int channel, int size, ByteBuffer buf) { synchronized (sendlock) { - ByteBuffer data = ByteBuffer.allocate(size + HEADER_SIZE); - data.order(ByteOrder.BIG_ENDIAN); + ByteBuffer data = _frameHeader; + _frameHeader.rewind(); + data.put(0, flags); data.put(1, type); data.putShort(2, (short) (size + HEADER_SIZE)); data.put(5, track); data.putShort(6, (short) channel); - data.position(HEADER_SIZE); + int limit = buf.limit(); buf.limit(buf.position() + size); - data.put(buf); - buf.limit(limit); - + data.rewind(); sender.send(data); + sender.send(buf); + buf.limit(limit); + } } @@ -179,7 +187,7 @@ public final class Disassembler implements Sender<ProtocolEvent>, ProtocolDelega } } method.write(enc); - ByteBuffer methodSeg = enc.segment(); + int methodLimit = enc.position(); byte flags = FIRST_SEG; @@ -189,29 +197,44 @@ public final class Disassembler implements Sender<ProtocolEvent>, ProtocolDelega flags |= LAST_SEG; } - ByteBuffer headerSeg = null; + int headerLimit = -1; if (payload) { final Header hdr = method.getHeader(); if (hdr != null) { - final Struct[] structs = hdr.getStructs(); - - for (Struct st : structs) + if(hdr.getDeliveryProperties() != null) + { + enc.writeStruct32(hdr.getDeliveryProperties()); + } + if(hdr.getMessageProperties() != null) + { + enc.writeStruct32(hdr.getMessageProperties()); + } + if(hdr.getNonStandardProperties() != null) { - enc.writeStruct32(st); + for (Struct st : hdr.getNonStandardProperties()) + { + enc.writeStruct32(st); + } } } - headerSeg = enc.segment(); + headerLimit = enc.position(); } synchronized (sendlock) { - fragment(flags, type, method, methodSeg); + ByteBuffer buf = enc.underlyingBuffer(); + buf.position(0); + buf.limit(methodLimit); + + fragment(flags, type, method, buf); if (payload) { ByteBuffer body = method.getBody(); - fragment(body == null ? LAST_SEG : 0x0, SegmentType.HEADER, method, headerSeg); + buf.limit(headerLimit); + buf.position(methodLimit); + fragment(body == null ? LAST_SEG : 0x0, SegmentType.HEADER, method, buf); if (body != null) { fragment(LAST_SEG, SegmentType.BODY, method, body); diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java index bd189feb1c..cb9a9468bb 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java @@ -581,10 +581,10 @@ public class PropertyFieldTableTest extends TestCase table.setBytes("bytes", bytes); table.setChar("char", 'c'); - table.setDouble("double", Double.MAX_VALUE); - table.setFloat("float", Float.MAX_VALUE); table.setInteger("int", Integer.MAX_VALUE); table.setLong("long", Long.MAX_VALUE); + table.setDouble("double", Double.MAX_VALUE); + table.setFloat("float", Float.MAX_VALUE); table.setShort("short", Short.MAX_VALUE); table.setString("string", "hello"); table.setString("null-string", null); @@ -823,9 +823,7 @@ public class PropertyFieldTableTest extends TestCase */ public void testCheckPropertyNamehasMaxLength() { - String oldVal = System.getProperty("STRICT_AMQP"); - System.setProperty("STRICT_AMQP", "true"); - FieldTable table = new FieldTable(); + FieldTable table = new FieldTable(true); StringBuffer longPropertyName = new StringBuffer(129); @@ -845,14 +843,6 @@ public class PropertyFieldTableTest extends TestCase } // so length should be zero Assert.assertEquals(0, table.getEncodedSize()); - if (oldVal != null) - { - System.setProperty("STRICT_AMQP", oldVal); - } - else - { - System.clearProperty("STRICT_AMQP"); - } } /** @@ -860,9 +850,7 @@ public class PropertyFieldTableTest extends TestCase */ public void testCheckPropertyNameStartCharacterIsLetter() { - String oldVal = System.getProperty("STRICT_AMQP"); - System.setProperty("STRICT_AMQP", "true"); - FieldTable table = new FieldTable(); + FieldTable table = new FieldTable(true); // Try a name that starts with a number try @@ -876,14 +864,6 @@ public class PropertyFieldTableTest extends TestCase } // so length should be zero Assert.assertEquals(0, table.getEncodedSize()); - if (oldVal != null) - { - System.setProperty("STRICT_AMQP", oldVal); - } - else - { - System.clearProperty("STRICT_AMQP"); - } } /** @@ -891,9 +871,7 @@ public class PropertyFieldTableTest extends TestCase */ public void testCheckPropertyNameStartCharacterIsHashorDollar() { - String oldVal = System.getProperty("STRICT_AMQP"); - System.setProperty("STRICT_AMQP", "true"); - FieldTable table = new FieldTable(); + FieldTable table = new FieldTable(true); // Try a name that starts with a number try @@ -906,14 +884,6 @@ public class PropertyFieldTableTest extends TestCase fail("property name are allowed to start with # and $s"); } - if (oldVal != null) - { - System.setProperty("STRICT_AMQP", oldVal); - } - else - { - System.clearProperty("STRICT_AMQP"); - } } /** diff --git a/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java index ad45d00e46..889250e004 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java +++ b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java @@ -60,7 +60,7 @@ public class RangeSetTest extends TestCase public void test1() { - RangeSet ranges = new RangeSet(); + RangeSet ranges = RangeSetFactory.createRangeSet(); ranges.add(5, 10); check(ranges); ranges.add(15, 20); @@ -77,7 +77,7 @@ public class RangeSetTest extends TestCase public void test2() { - RangeSet rs = new RangeSet(); + RangeSet rs = RangeSetFactory.createRangeSet(); check(rs); rs.add(1); @@ -128,7 +128,7 @@ public class RangeSetTest extends TestCase public void testAddSelf() { - RangeSet a = new RangeSet(); + RangeSet a = RangeSetFactory.createRangeSet(); a.add(0, 8); check(a); a.add(0, 8); @@ -141,8 +141,8 @@ public class RangeSetTest extends TestCase public void testIntersect1() { - Range a = new Range(0, 10); - Range b = new Range(9, 20); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(9, 20); Range i1 = a.intersect(b); Range i2 = b.intersect(a); assertEquals(i1.getUpper(), 10); @@ -153,16 +153,16 @@ public class RangeSetTest extends TestCase public void testIntersect2() { - Range a = new Range(0, 10); - Range b = new Range(11, 20); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(11, 20); assertNull(a.intersect(b)); assertNull(b.intersect(a)); } public void testIntersect3() { - Range a = new Range(0, 10); - Range b = new Range(3, 5); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(3, 5); Range i1 = a.intersect(b); Range i2 = b.intersect(a); assertEquals(i1.getUpper(), 5); @@ -173,14 +173,14 @@ public class RangeSetTest extends TestCase public void testSubtract1() { - Range a = new Range(0, 10); + Range a = Range.newInstance(0, 10); assertTrue(a.subtract(a).isEmpty()); } public void testSubtract2() { - Range a = new Range(0, 10); - Range b = new Range(20, 30); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(20, 30); List<Range> ranges = a.subtract(b); assertEquals(ranges.size(), 1); Range d = ranges.get(0); @@ -190,8 +190,8 @@ public class RangeSetTest extends TestCase public void testSubtract3() { - Range a = new Range(20, 30); - Range b = new Range(0, 10); + Range a = Range.newInstance(20, 30); + Range b = Range.newInstance(0, 10); List<Range> ranges = a.subtract(b); assertEquals(ranges.size(), 1); Range d = ranges.get(0); @@ -201,8 +201,8 @@ public class RangeSetTest extends TestCase public void testSubtract4() { - Range a = new Range(0, 10); - Range b = new Range(3, 5); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(3, 5); List<Range> ranges = a.subtract(b); assertEquals(ranges.size(), 2); Range low = ranges.get(0); @@ -215,8 +215,8 @@ public class RangeSetTest extends TestCase public void testSubtract5() { - Range a = new Range(0, 10); - Range b = new Range(3, 20); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(3, 20); List<Range> ranges = a.subtract(b); assertEquals(ranges.size(), 1); Range d = ranges.get(0); @@ -226,8 +226,8 @@ public class RangeSetTest extends TestCase public void testSubtract6() { - Range a = new Range(0, 10); - Range b = new Range(-10, 5); + Range a = Range.newInstance(0, 10); + Range b = Range.newInstance(-10, 5); List<Range> ranges = a.subtract(b); assertEquals(ranges.size(), 1); Range d = ranges.get(0); diff --git a/java/common/templates/method/version/MethodBodyClass.vm b/java/common/templates/method/version/MethodBodyClass.vm index ce8a453eeb..0e444b87df 100644 --- a/java/common/templates/method/version/MethodBodyClass.vm +++ b/java/common/templates/method/version/MethodBodyClass.vm @@ -46,8 +46,9 @@ package org.apache.qpid.framing.amqp_$version.getMajor()_$version.getMinor(); -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import org.apache.qpid.codec.MarkableDataInput; +import java.io.DataOutput; import java.io.IOException; import java.util.HashMap; @@ -58,7 +59,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version { private static final AMQMethodBodyInstanceFactory FACTORY_INSTANCE = new AMQMethodBodyInstanceFactory() { - public AMQMethodBody newInstance(DataInputStream in, long size) throws AMQFrameDecodingException, IOException + public AMQMethodBody newInstance(MarkableDataInput in, long size) throws AMQFrameDecodingException, IOException { return new ${javaClassName}(in); } @@ -86,7 +87,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version // Constructor - public ${javaClassName}(DataInputStream buffer) throws AMQFrameDecodingException, IOException + public ${javaClassName}(MarkableDataInput buffer) throws AMQFrameDecodingException, IOException { #foreach( $field in $method.ConsolidatedFields ) _$field.Name = read$field.getEncodingType()( buffer ); @@ -171,7 +172,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version return size; } - public void writeMethodPayload(DataOutputStream buffer) throws IOException + public void writeMethodPayload(DataOutput buffer) throws IOException { #foreach( $field in $method.ConsolidatedFields ) write$field.getEncodingType()( buffer, _$field.Name ); diff --git a/java/common/templates/model/MethodRegistryClass.vm b/java/common/templates/model/MethodRegistryClass.vm index 8258175ce7..f8a55f245a 100644 --- a/java/common/templates/model/MethodRegistryClass.vm +++ b/java/common/templates/model/MethodRegistryClass.vm @@ -30,10 +30,10 @@ package org.apache.qpid.framing; -import java.io.DataInputStream; import java.io.IOException; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; +import org.apache.qpid.codec.MarkableDataInput; import java.util.Map; import java.util.HashMap; @@ -54,7 +54,7 @@ public abstract class MethodRegistry #end - public abstract AMQMethodBody convertToBody(DataInputStream in, long size) + public abstract AMQMethodBody convertToBody(MarkableDataInput in, long size) throws AMQFrameDecodingException, IOException; public abstract int getMaxClassId(); diff --git a/java/common/templates/model/version/MethodRegistryClass.vm b/java/common/templates/model/version/MethodRegistryClass.vm index 79553f7748..ab5db0ea38 100644 --- a/java/common/templates/model/version/MethodRegistryClass.vm +++ b/java/common/templates/model/version/MethodRegistryClass.vm @@ -35,10 +35,10 @@ import org.apache.qpid.protocol.AMQConstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.DataInputStream; import java.io.IOException; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; +import org.apache.qpid.codec.MarkableDataInput; public class MethodRegistry_$version.getMajor()_$version.getMinor() extends MethodRegistry @@ -87,7 +87,7 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth } - public AMQMethodBody convertToBody(DataInputStream in, long size) + public AMQMethodBody convertToBody(MarkableDataInput in, long size) throws AMQFrameDecodingException, IOException { int classId = in.readUnsignedShort(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java index a5c38e7e33..fb5cf8b3c6 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java @@ -22,11 +22,11 @@ package org.apache.qpid.server.store; import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.logging.LogSubject; @@ -35,7 +35,7 @@ import java.util.HashMap; import java.util.Iterator; import java.nio.ByteBuffer; -public class SlowMessageStore implements MessageStore +public class SlowMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger _logger = Logger.getLogger(SlowMessageStore.class); private static final String DELAYS = "delays"; @@ -43,6 +43,7 @@ public class SlowMessageStore implements MessageStore private HashMap<String, Long> _postDelays = new HashMap<String, Long>(); private long _defaultDelay = 0L; private MessageStore _realStore = new MemoryMessageStore(); + private DurableConfigurationStore _durableConfigurationStore = (MemoryMessageStore) _realStore; private static final String PRE = "pre"; private static final String POST = "post"; private String DEFAULT_DELAY = "default"; @@ -80,12 +81,13 @@ public class SlowMessageStore implements MessageStore " does not."); } _realStore = (MessageStore) o; - _realStore.configureConfigStore(name, recoveryHandler, config, logSubject); - } - else - { - _realStore.configureConfigStore(name, recoveryHandler, config, logSubject); + if(o instanceof DurableConfigurationStore) + { + _durableConfigurationStore = (DurableConfigurationStore)o; + } } + _durableConfigurationStore.configureConfigStore(name, recoveryHandler, config, logSubject); + } private void configureDelays(Configuration config) @@ -178,28 +180,28 @@ public class SlowMessageStore implements MessageStore public void createExchange(Exchange exchange) throws AMQStoreException { doPreDelay("createExchange"); - _realStore.createExchange(exchange); + _durableConfigurationStore.createExchange(exchange); doPostDelay("createExchange"); } public void removeExchange(Exchange exchange) throws AMQStoreException { doPreDelay("removeExchange"); - _realStore.removeExchange(exchange); + _durableConfigurationStore.removeExchange(exchange); doPostDelay("removeExchange"); } public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException { doPreDelay("bindQueue"); - _realStore.bindQueue(exchange, routingKey, queue, args); + _durableConfigurationStore.bindQueue(exchange, routingKey, queue, args); doPostDelay("bindQueue"); } public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException { doPreDelay("unbindQueue"); - _realStore.unbindQueue(exchange, routingKey, queue, args); + _durableConfigurationStore.unbindQueue(exchange, routingKey, queue, args); doPostDelay("unbindQueue"); } @@ -211,14 +213,14 @@ public class SlowMessageStore implements MessageStore public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException { doPreDelay("createQueue"); - _realStore.createQueue(queue, arguments); + _durableConfigurationStore.createQueue(queue, arguments); doPostDelay("createQueue"); } public void removeQueue(AMQQueue queue) throws AMQStoreException { doPreDelay("removeQueue"); - _realStore.removeQueue(queue); + _durableConfigurationStore.removeQueue(queue); doPostDelay("removeQueue"); } @@ -268,19 +270,19 @@ public class SlowMessageStore implements MessageStore _underlying = underlying; } - public void enqueueMessage(TransactionLogResource queue, Long messageId) + public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { doPreDelay("enqueueMessage"); - _underlying.enqueueMessage(queue, messageId); + _underlying.enqueueMessage(queue, message); doPostDelay("enqueueMessage"); } - public void dequeueMessage(TransactionLogResource queue, Long messageId) + public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { doPreDelay("dequeueMessage"); - _underlying.dequeueMessage(queue, messageId); + _underlying.dequeueMessage(queue, message); doPostDelay("dequeueMessage"); } @@ -313,7 +315,7 @@ public class SlowMessageStore implements MessageStore public void updateQueue(AMQQueue queue) throws AMQStoreException { doPreDelay("updateQueue"); - _realStore.updateQueue(queue); + _durableConfigurationStore.updateQueue(queue); doPostDelay("updateQueue"); } |