Page Created :
qpid :
Java Broker Design - Message Representation
Java Broker Design - Message Representation has been created by Martin Ritchie (Jun 16, 2009). Content:Message RepresentationFollowing on from the high level design this page will provide a more detailed design of the changes to the broker. OverviewCurrently the broker uses two implementations of AMQMessageHandle, one transient, one persistent, which actively stores and retrieves the underlying data. The AMQMessage class should provide immutable access to the message data (header and body) stored within the broker, there should be a 1:1 relationship between AMQMessage objects and messages delivered through the broker. Currently the AMQMessage is responsible for holding a count of references but the responsibility for maintaining this value is spread throughout the code base. This responsibility needs to be given to a single class so that we can more easily reason about and test its functionality. This work is part of the MessageStore refactoring. DesignAs part of the initial high level design the following interfaces were designed. Message Representation InterfaceMessage public interface Message<Header extends MessageHeader> { void addContent(ByteBuffer buffer); CompleteFuture contentComplete(); long getMessageID(); Header getHeader(); long writeContentToBuffer(long offset, long length, ByteBuffer buffer); MessageReference newReference(Object referer); MessageInterest newInterest(Object requestor); } The new Message interface unifies the current IncomingMessage, AMQMessage and the Store operations becoming a container for the ByteBuffers of data that make up the content of the Message. The Message becomes a proxy for the MessageStore allowing incoming ByteBuffers of content to be added and the ability to use a future to check that the data has been safely stored by the MessageStore. CompleteFuture public interface CompleteFuture { void complete(); boolean isComplete(); } To enable support for multiple protocols the type of MessageHeader will depend on the protocol of the publishing connection. In addition the Message will be responsible for writing its self to a given ByteBuffer. This allows the Framing layer to be responsible for setting up the ByteBuffer and then requesting that the Message fill in its data. Unified Reference Counting.Reference counting is performed in a number of locations in the code so the new Message interface provides a new approach to handling these references. The previous approach used an AtomicInteger count to know when a Message was no longer required this made debugging difficult and so the newReference call takes the object that is referring to this Message. This will allow for the potential to provide a list of what is referencing this Message. The returned MessageReference object will have a release() to relinquish the reference. However, by also using a the finalizer to automatically release the reference at GC time instances we do not explicitly need to call release(). This pattern is also going to be used for the new concept of Interest. MessageReference/Interest public abstract class MessageReference/Interest { abstract void release(); protected final void finalize() throws Throwable { release(); super.finalize(); } } Message InterestAs mentioned above in Reference Counting, Message Interest is a new concept for the Java Broker. This allows the running broker to provide a hint to the MessageStore that it is interested in the Message and is likely to use it shortly. This will enable the MessageStore to better control its memory usage. Messages that have interested parties could be safely removed from memory such as by a Flow to Disk routine. However, if Interest is requested then it would be a beneficial to load this message back in to memory or performance will suffer. Message Interests will follow the same pattern as MessageReference, interest will be requested by an Object and the resulting MessageInterest will allow that interest to be explicitly released. |
Unsubscribe or edit your notifications preferences