view tango/tango/net/cluster/tina/ClusterThread.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 source

/*******************************************************************************

        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.ClusterThread;

private import  tango.core.Thread,
                tango.core.Runtime,
                tango.core.Exception;

private import  tango.io.Buffer,
                tango.io.GrowBuffer,
                tango.net.ServerSocket;

package import  tango.io.model.IBuffer,
                tango.io.model.IConduit;

private import  tango.text.convert.Sprint;

package import  tango.net.cluster.tina.Cluster,
                tango.net.cluster.tina.ProtocolReader,
                tango.net.cluster.tina.ProtocolWriter;

package import  tango.net.cluster.tina.util.AbstractServer;

/******************************************************************************

        Thread for handling client requests. Note that this remains alive
        until the client kills the socket

******************************************************************************/

class ClusterThread
{
        protected IBuffer         buffer;
        protected ProtocolReader  reader;
        protected ProtocolWriter  writer;
        protected Logger          logger;
        protected char[]          client;
        protected Thread          thread;
        protected Sprint!(char)   sprint;
        protected Cluster         cluster;
        protected IConduit        conduit;

        /**********************************************************************

                request handler

        **********************************************************************/

        abstract void dispatch ();

        /**********************************************************************

                Note that the conduit stays open until the client kills it.
                Also note that we use a GrowableBuffer here, which expands
                as necessary to contain larger payloads.

        **********************************************************************/

        this (AbstractServer server, IConduit conduit, Cluster cluster)
        {
                buffer = new GrowBuffer (1024 * 8);
                buffer.setConduit (conduit);

                // get client infomation
                client = server.remoteAddress(conduit).toString;

                // setup cluster protocol-transcoders
                writer = new ProtocolWriter (buffer);
                reader = new ProtocolReader (buffer);

                // grab a thread to execute within
                thread = new Thread (&run);

                // make a formatter for this thread
                sprint = new Sprint!(char);
                
                // save state
                logger = server.getLogger;
                this.conduit = conduit;
                this.cluster = cluster;
        }

        /**********************************************************************

                IRunnable method

        **********************************************************************/

        void execute ()
        {
                thread.start;
        }
        
        /**********************************************************************

                process client requests
                
        **********************************************************************/

        private void run ()
        {
                logger.info (sprint ("{} starting service handler", client));
                
                try {
                    while (true)
                          {
                          // start with a clear conscience
                          buffer.clear;

                          // wait for something to arrive before we try/catch
                          buffer.slice (1, false);

                          try {
                              dispatch;
                              } catch (Object x)
                                      {
                                      logger.error (sprint ("{} cluster request error '{}'", client, x));
                                      writer.exception (sprint ("cluster request error '{}'", x.toString));
                                      }

                          // send response back to client
                          buffer.flush;
                          }

                    } catch (IOException x)
                             if (! Runtime.isHalting)
                                   logger.trace (sprint ("{} cluster socket exception '{}'", client, x));

                      catch (Object x)
                             logger.fatal (sprint ("{} cluster runtime exception '{}'", client, x));

                // log our halt status
                logger.info (sprint ("{} halting service handler", client));

                // make sure we close the conduit
                conduit.detach;
        }
}