csharp/0ffffffffh/sozluk-cgi-revival/sozluk_backend/Core/Sys/Request/RequestBridge.cs

RequestBridge.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using sozluk_backend.Core.Sys.Logging;

namespace sozluk_backend.Core.Sys.Request
{
    static clast RequestBridge
    {
        static Thread[] waiters;
        static bool active;

        private static NamedPipeServerStream CreatePipe()
        {
            NamedPipeServerStream nps;

            try
            {
                nps = new NamedPipeServerStream(
                    "sozluk_request_bridge_pipe",
                    PipeDirection.InOut,
                    NamedPipeServerStream.MaxAllowedServerInstances,
                    PipeTransmissionMode.Byte
                    );

            }
            catch (Exception e)
            {
                Log.Error("Pipe create error. {0}", e.Message);
                return null;
            }

            Log.Info("Bridge pipe server created");

            return nps;
        }


        private static void RequestWaiter(object o)
        {
            NamedPipeServerStream nps = null;
            
            while (active)
            {
                nps = CreatePipe();

                if (nps == null)
                {
                    Thread.Sleep(1000);
                    continue;
                }

                try
                {
                    nps.WaitForConnection();

                    if (!active)
                    {
                        nps.Close();
                        nps.Dispose();
                        nps = null;
                    }
                }
                catch (Exception e)
                {
                    Log.Warning("pipe connection wait aborted. {0}", e.Message);
                    nps = null;
                }

                if (nps != null)
                    RegisterRequestReceiver(nps);

            }

            Log.Verbose("Pipe connection waiter Tid#{0} closed.", Thread.CurrentThread.ManagedThreadId);

        }

        private static void WaitIo(object obj)
        {
            uint totalBytes;
            int readLen = 0;
            byte[] buffer = new byte[32 * 1024];
            

            NamedPipeServerStream nps = (NamedPipeServerStream)obj;
            RequestObject reqObj;

            Log.Verbose("Thread#{0} waiting for available incoming data", 
                Thread.CurrentThread.ManagedThreadId);

            if (nps.Read(buffer, 0, 4) > 0)
            {
                totalBytes = BitConverter.ToUInt32(buffer, 0);
                
                readLen = nps.Read(buffer, 0, buffer.Length);
                
                reqObj = new RequestObject(nps, buffer, readLen);

                if (!reqObj.IsEnqueued)
                    reqObj = null;
            }
            else
            {
                nps.Disconnect();
                nps.Close();
                nps.Dispose();
                nps = null;
            }

            buffer = null;
        }

        public static bool RegisterRequestReceiver(NamedPipeServerStream nps)
        {
            return ThreadPool.QueueUserWorkItem(new WaitCallback(WaitIo), nps);
        }

        public static void CreatePipeServers(int waiterCount)
        {
            Log.Verbose("Creating '{0}' pipe(s) connection waiter", waiterCount);

            waiters = new Thread[waiterCount];

            active = true;

            for (int i = 0; i < waiters.Length; i++)
            {
                waiters[i] = new Thread(new ParameterizedThreadStart(RequestWaiter));
                waiters[i].Start(null);
            }
        }

        private static void AbortBlockingWaitOfPipeServer(int count)
        {
            for (int i = 0; i < count; i++)
            {
                NamedPipeClientStream nspc = new NamedPipeClientStream("sozluk_request_bridge_pipe");
                nspc.Connect();

                nspc.Close();
                nspc.Dispose();
            }
        }

        public static void Shutdown()
        {
            active = false;

            Log.Info("Bridge shutting down op signalled");

            AbortBlockingWaitOfPipeServer(waiters.Length);

            foreach (Thread tworker in waiters)
            {
                Log.Verbose("T#{0} Waiting worker to finish",tworker.ManagedThreadId);
                tworker.Join();
            }

            waiters = null;

        }
    }
}