diff tango/tango/net/cluster/tina/ProtocolReader.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/tango/net/cluster/tina/ProtocolReader.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,157 @@
+/*******************************************************************************
+
+        copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
+
+        license:        BSD style: $(LICENSE)
+        
+        version:        July 2004: Initial release      
+        
+        author:         Kris
+
+*******************************************************************************/
+
+module tango.net.cluster.tina.ProtocolReader;
+
+private import  tango.io.protocol.Reader,
+                tango.io.protocol.Allocator,
+                tango.io.protocol.PickleProtocol;
+
+private import  tango.net.cluster.model.IMessage;
+
+private import  tango.net.cluster.NetworkRegistry;
+
+private import  tango.net.cluster.tina.ClusterTypes;
+
+/*******************************************************************************
+        
+        Objects passed around a cluster are prefixed with a header, so the 
+        receiver can pick them apart correctly. This header consists of:
+        ---
+                * the packet size, including the header (16 bits)
+                * a command code (8 bits)
+                * a version id (8 bits)
+                * a timestamp (64 bits)
+                * length of the channel name (32 bits)
+                * the channel name
+                * length of the key (32 bits)
+                * the key
+                * an optional payload (an IMessage instance)
+        ---
+
+        Everything is written in Network order (big endian).
+
+*******************************************************************************/
+
+class ProtocolReader : Reader
+{
+        /***********************************************************************
+        
+                Construct a ProtocolReader upon the given buffer. As
+                Objects are serialized their content is written to this
+                buffer. The buffer content is then typically flushed to 
+                some external conduit, such as a file or socket.
+
+                Note that arrays (such as text) are *always* sliced from
+                the buffer -- there's no heap activity involved. Thus it
+                may be necessary to .dup content where appropriate
+
+        ***********************************************************************/
+        
+        this (IBuffer buffer)
+        {
+                super (new BufferSlice (new PickleProtocol (buffer)));
+        }
+
+        /***********************************************************************
+
+                deserialize a payload into a provided host, or via
+                the registered instance of the incoming payload
+                        
+        ***********************************************************************/
+
+        IMessage thaw (IMessage host = null)
+        {
+                return thaw (NetworkRegistry.shared, host);                
+        }
+
+        /***********************************************************************
+
+                deserialize a payload into a provided host, or via
+                the registered instance of the incoming payload
+                        
+        ***********************************************************************/
+
+        IMessage thaw (NetworkRegistry registry, IMessage host = null)
+        {
+                return registry.thaw (this, host);                
+        }
+
+        /***********************************************************************
+        
+                Read the protocol header and return true if there's a 
+                payload available
+
+        ***********************************************************************/
+
+        bool getHeader (inout ubyte cmd, inout char[] channel, inout char[] element)
+        {
+                auto position = buffer.position;
+
+                long   time;
+                ushort size;
+                ubyte  versn;
+
+                get (size) (cmd) (versn) (time);
+
+                // avoid allocation for these two strings
+                get (channel) (element);
+
+                // is there a payload attached?
+                if (size > (buffer.position - position))
+                    return true;
+
+                return false;
+        }
+
+        /***********************************************************************
+        
+                Return an aliased slice of the buffer representing the 
+                recieved payload. This is a bit of a hack, but eliminates
+                a reasonable amount of overhead. Note that the channel/key
+                text is retained right at the start of the returned content, 
+                enabling the host to toss the whole thing back without any 
+                further munging. 
+
+        ***********************************************************************/
+
+        ClusterContent getPacket (inout ubyte cmd, inout char[] channel, inout char[] element, inout long time)
+        {
+                ushort  size;
+                ubyte   versn;
+
+                // load up the header
+                get (size) (cmd) (versn) (time);
+
+                //printf ("size: %d\n", cast(int) size);
+
+                // subtract header size
+                size -= buffer.position;
+                
+                // may throw an exception if the payload is too large to fit
+                // completely inside the buffer!
+                buffer.slice (size, false);
+
+                // slice the remaining packet (with channel/key text)
+                auto content = cast(ClusterContent) buffer.slice;
+
+                // get a slice upon the channel name
+                get (channel);
+
+                // get a slice upon the element name
+                get (element);
+
+                // return the aliased payload (including channel/key text)
+                return content;
+        }
+}
+