Mercurial > projects > ldc
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; + } +} +