THRIFT-2624: Add TServerEventHandler support to C#
Client: C#
Patch: ra

Adds the TServerEventHandler interface to the C# lib and adds
support in all C# servers.
diff --git a/lib/csharp/src/Server/TSimpleServer.cs b/lib/csharp/src/Server/TSimpleServer.cs
index 1099fc1..75f8241 100644
--- a/lib/csharp/src/Server/TSimpleServer.cs
+++ b/lib/csharp/src/Server/TSimpleServer.cs
@@ -27,122 +27,132 @@
 
 namespace Thrift.Server
 {
-	/// <summary>
-	/// Simple single-threaded server for testing
-	/// </summary>
-	public class TSimpleServer : TServer
-	{
-		private bool stop = false;
+  /// <summary>
+  /// Simple single-threaded server for testing
+  /// </summary>
+  public class TSimpleServer : TServer
+  {
+    private bool stop = false;
 
-		public TSimpleServer(TProcessor processor,
-						  TServerTransport serverTransport)
-			:base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
-		{
-		}
+    public TSimpleServer(TProcessor processor,
+              TServerTransport serverTransport)
+      : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
+    {
+    }
 
-		public TSimpleServer(TProcessor processor,
-							TServerTransport serverTransport,
-							LogDelegate logDel)
-			: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
-		{
-		}
+    public TSimpleServer(TProcessor processor,
+              TServerTransport serverTransport,
+              LogDelegate logDel)
+      : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
+    {
+    }
 
-		public TSimpleServer(TProcessor processor,
-						  TServerTransport serverTransport,
-						  TTransportFactory transportFactory)
-			:base(processor,
-				 serverTransport,
-				 transportFactory,
-				 transportFactory,
-				 new TBinaryProtocol.Factory(),
-				 new TBinaryProtocol.Factory(),
-			     DefaultLogDelegate)
-		{
-		}
+    public TSimpleServer(TProcessor processor,
+              TServerTransport serverTransport,
+              TTransportFactory transportFactory)
+      : base(processor,
+         serverTransport,
+         transportFactory,
+         transportFactory,
+         new TBinaryProtocol.Factory(),
+         new TBinaryProtocol.Factory(),
+           DefaultLogDelegate)
+    {
+    }
 
-		public TSimpleServer(TProcessor processor,
-						  TServerTransport serverTransport,
-						  TTransportFactory transportFactory,
-						  TProtocolFactory protocolFactory)
-			:base(processor,
-				 serverTransport,
-				 transportFactory,
-				 transportFactory,
-				 protocolFactory,
-				 protocolFactory,
-				 DefaultLogDelegate)
-		{
-		}
+    public TSimpleServer(TProcessor processor,
+              TServerTransport serverTransport,
+              TTransportFactory transportFactory,
+              TProtocolFactory protocolFactory)
+      : base(processor,
+         serverTransport,
+         transportFactory,
+         transportFactory,
+         protocolFactory,
+         protocolFactory,
+         DefaultLogDelegate)
+    {
+    }
 
-		public override void Serve()
-		{
-			try
-			{
-				serverTransport.Listen();
-			}
-			catch (TTransportException ttx)
-			{
-				logDelegate(ttx.ToString());
-				return;
-			}
+    public override void Serve()
+    {
+      try
+      {
+        serverTransport.Listen();
+      }
+      catch (TTransportException ttx)
+      {
+        logDelegate(ttx.ToString());
+        return;
+      }
 
-			while (!stop)
-			{
-				TTransport client = null;
-				TTransport inputTransport = null;
-				TTransport outputTransport = null;
-				TProtocol inputProtocol = null;
-				TProtocol outputProtocol = null;
-				try
-				{
-          using(client = serverTransport.Accept())
+      //Fire the preServe server event when server is up but before any client connections
+      if (serverEventHandler != null)
+        serverEventHandler.preServe();
+
+      while (!stop)
+      {
+        TTransport client = null;
+        TTransport inputTransport = null;
+        TTransport outputTransport = null;
+        TProtocol inputProtocol = null;
+        TProtocol outputProtocol = null;
+        Object connectionContext = null;
+        try
+        {
+          using (client = serverTransport.Accept())
           {
             if (client != null)
             {
-              using(inputTransport = inputTransportFactory.GetTransport(client))
+              using (inputTransport = inputTransportFactory.GetTransport(client))
               {
                 using (outputTransport = outputTransportFactory.GetTransport(client))
                 {
                   inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
                   outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
-                  while (processor.Process(inputProtocol, outputProtocol)) { }
+
+                  //Recover event handler (if any) and fire createContext server event when a client connects
+                  if (serverEventHandler != null)
+                    connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                  //Process client requests until client disconnects
+                  while (true)
+                  {
+                    //Fire processContext server event
+                    //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                    //That is to say it may be many minutes between the event firing and the client request
+                    //actually arriving or the client may hang up without ever makeing a request.
+                    if (serverEventHandler != null)
+                      serverEventHandler.processContext(connectionContext, inputTransport);
+                    //Process client request (blocks until transport is readable)
+                    if (!processor.Process(inputProtocol, outputProtocol))
+                      break;
+                  }
                 }
               }
             }
           }
         }
-        catch (TTransportException ttx)
+        catch (TTransportException)
         {
-          // Client died, just move on
-          if (stop)
-          {
-            logDelegate("TSimpleServer was shutting down, caught " + ttx.GetType().Name);
-          }
+          //Usually a client disconnect, expected
         }
         catch (Exception x)
         {
+          //Unexpected
           logDelegate(x.ToString());
         }
+
+        //Fire deleteContext server event after client disconnects
+        if (serverEventHandler != null)
+          serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
       }
+    }
 
-			if (stop)
-			{
-				try
-				{
-					serverTransport.Close();
-				}
-				catch (TTransportException ttx)
-				{
-					logDelegate("TServerTranport failed on close: " + ttx.Message);
-				}
-				stop = false;
-			}
-		}
-
-		public override void Stop()
-		{
-			stop = true;
-			serverTransport.Close();
-		}
-	}
+    public override void Stop()
+    {
+      stop = true;
+      serverTransport.Close();
+    }
+  }
 }