diff tango/tango/net/cluster/tina/ProtocolWriter.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/ProtocolWriter.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,199 @@
+/*******************************************************************************
+
+        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.ProtocolWriter;
+
+private import  tango.io.protocol.Writer,
+                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 ProtocolWriter
+{
+        private Writer  emit;
+        package IBuffer buffer;
+        
+        const ubyte Version = 0x01;
+
+        /***********************************************************************
+        
+                protocol commands
+
+        ***********************************************************************/
+
+        enum Command : ubyte 
+             {
+             OK, 
+             Exception, 
+             Full, 
+             Locked, 
+             Add, 
+             Copy, 
+             Remove, 
+             Load, 
+             AddQueue, 
+             RemoveQueue, 
+             Call
+             }
+
+        /***********************************************************************
+        
+                Construct a ProtocolWriter 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 serialized data is always in Network order.
+
+        ***********************************************************************/
+        
+        this (IBuffer buffer)
+        {
+                assert (buffer);
+                emit = new Writer (new PickleProtocol(this.buffer = buffer));
+        }
+
+        /***********************************************************************
+        
+                Stuff the request into our output buffer. Note that this
+                protocol is prefixed by a 'size' value, requiring that
+                all messages can be contained within the buffer. This is
+                not considered a serious limitation, as the messages are
+                not intended to be "large" given that they're traversing 
+                the network.
+
+        ***********************************************************************/
+
+        ProtocolWriter put (Command cmd, char[] channel, char[] element = null, IMessage msg = null)
+        {
+                auto time = (msg ? msg.time : Time.init);
+        
+                // reset the buffer first!
+                buffer.clear;
+
+                auto content = cast(ubyte[]) buffer.getContent;
+                emit (cast(ushort) 0)
+                     (cast(ubyte) cmd)
+                     (cast(ubyte) Version)
+                     (cast(ulong) time.ticks)
+                     (channel)
+                     (element);
+
+                // is there a payload?
+                if (msg)
+                    NetworkRegistry.shared.freeze (emit, msg);
+
+                // go back and write the total number of bytes
+                auto size = buffer.limit;
+                content[0] = cast(ubyte) (size >> 8);
+                content[1] = cast(ubyte) (size & 0xff);
+                return this;
+        }
+
+        /***********************************************************************
+        
+                Emit a ClusterContent constructed by ProtocolReader.getPacket
+
+        ***********************************************************************/
+
+        ProtocolWriter reply (ClusterContent content)
+        {
+                uint empty = 0;
+
+                // reset the buffer first
+                buffer.clear;
+
+                // write the length, the ack, version, and timestamp
+                emit (cast(ushort) (content.length + ushort.sizeof + ubyte.sizeof + ubyte.sizeof + ulong.sizeof))
+                     (cast(ubyte) ProtocolWriter.Command.OK)
+                     (cast(ubyte) Version)
+                     (cast(ulong) ulong.init);
+
+                // and the payload (which includes both channel & element)
+                if (content.length)
+                    buffer.append (content);
+                else
+                   // or filler for an empty channel & element ...
+                   emit (empty) (empty);
+
+                return this;
+        }
+
+        /***********************************************************************
+        
+                Write an exception message
+
+        ***********************************************************************/
+
+        ProtocolWriter exception (char[] message)
+        {
+                return put (ProtocolWriter.Command.Exception, message);
+        }
+
+        /***********************************************************************
+                
+                Write an "OK" confirmation
+
+        ***********************************************************************/
+
+        ProtocolWriter success (char[] message = null)
+        {
+                return put (ProtocolWriter.Command.OK, message);
+        }
+
+        /***********************************************************************
+                
+                Indicate something has filled up
+
+        ***********************************************************************/
+
+        ProtocolWriter full (char[] message)
+        {
+                return put (ProtocolWriter.Command.Full, message);
+        }
+
+        /***********************************************************************
+                
+                Flush the output
+        
+        ***********************************************************************/
+
+        void flush () 
+        {
+                emit.flush;
+        }
+}
+