예제 #1
0
        unsafe void ProcessSendCompletes(object o)
        {
            const int         maxResults = 1024;
            RIO_RESULT *      results    = stackalloc RIO_RESULT[maxResults];
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];

            while (true)
            {
                RioStatic.Notify(SendCompletionQueue);
                if (Kernel32.GetQueuedCompletionStatus(SendCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(SendCompletionQueue, (IntPtr)results, maxResults);
                        WinSock.ThrowLastWSAError();
                        for (var i = 0; i < count; i++)
                        {
                            var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation];
                            if (buf.AutoFree)
                            {
                                buf.Dispose();
                            }
                        }
                    } while (count > 0);
                }
                else
                {
                    Kernel32.ThrowLastError();
                }
            }
        }
예제 #2
0
        internal int TryGetCompletionResults(CancellationToken cancellationToken, RIO_RESULT *results, int maxCompletionResults)
        {
            var completionQueue = QueueHandle;

            var spinwait = new SpinWait();

            while (!cancellationToken.IsCancellationRequested)
            {
                var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults);

                if (resultCount == 0)
                {
                    spinwait.SpinOnce();
                    continue;
                }

                if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ)
                {
                    WinSock.ThrowLastWsaError();
                    break;
                }

                return((int)resultCount);
            }

            return(0);
        }
예제 #3
0
 public SendCompletionProcessor(ZerioConfiguration configuration, RioCompletionQueue sendCompletionQueue)
 {
     _configuration            = configuration;
     _sendCompletionQueue      = sendCompletionQueue;
     _completionResults        = new RIO_RESULT[configuration.MaxSendCompletionResults];
     _completionResultsHandle  = GCHandle.Alloc(_completionResults, GCHandleType.Pinned);
     _completionResultsPointer = (RIO_RESULT *)_completionResultsHandle.AddrOfPinnedObject().ToPointer();
 }
예제 #4
0
        public SendCompletionProcessor(InternalZerioConfiguration configuration, IRioCompletionQueue sendCompletionQueue)
        {
            _sendCompletionQueue      = sendCompletionQueue;
            _completionResults        = new RIO_RESULT[configuration.MaxSendCompletionResults];
            _completionResultsHandle  = GCHandle.Alloc(_completionResults, GCHandleType.Pinned);
            _completionResultsPointer = (RIO_RESULT *)_completionResultsHandle.AddrOfPinnedObject().ToPointer();

            _waitStrategy = CompletionPollingWaitStrategyFactory.Create(configuration.SendCompletionPollingWaitStrategyType);
        }
예제 #5
0
        internal int TryGetCompletionResults(RIO_RESULT *results, int maxCompletionResults)
        {
            var completionQueue = QueueHandle;

            var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults);

            if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ)
            {
                WinSock.ThrowLastWsaError();
            }

            return((int)resultCount);
        }
예제 #6
0
        unsafe void ProcessReceiveCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)maxResults];
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];
            RIO_RESULT        result;
            RioBufferSegment  buf;

            while (true)
            {
                RioStatic.Notify(ReceiveCompletionQueue);

                if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }

                        for (var i = 0; i < count; i++)
                        {
                            result = results[i];
                            buf    = ReceiveBufferPool.AllSegments[result.RequestCorrelation];
                            buf.SegmentPointer->Length = (int)result.BytesTransferred;
                            buf.Set();
                        }
                    } while (count > 0);
                }
                else
                {
                    var error = Marshal.GetLastWin32Error();
                    if (error == 0 || error == 735)
                    {
                        break;
                    }
                    else if (error == 126)
                    {
                        continue;
                    }
                    else
                    {
                        throw new Win32Exception(error);
                    }
                }
            }
        }
예제 #7
0
        unsafe void ProcessReceiveCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)maxResults];
            RioSocket         connection;
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];
            RIO_RESULT        result;
            RioBufferSegment  buf;

            while (true)
            {
                RioStatic.Notify(ReceiveCompletionQueue);
                WinSock.ThrowLastWSAError();

                if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, (IntPtr)results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }

                        for (var i = 0; i < count; i++)
                        {
                            result = results[i];
                            buf    = ReceiveBufferPool.AllSegments[result.RequestCorrelation];
                            if (activeSockets.TryGetValue(result.ConnectionCorrelation, out connection))
                            {
                                buf.SegmentPointer->Length = (int)result.BytesTransferred;
                                connection.onIncommingSegment(connection, buf);
                            }
                            else
                            {
                                buf.Dispose();
                            }
                        }
                    } while (count > 0);
                }
                else
                {
                    Kernel32.ThrowLastError();
                }
            }
        }
예제 #8
0
        public unsafe int TryGetCompletionResults(RIO_RESULT *results, int maxCompletionResults)
        {
            if (!AvailableResults.TryDequeue(out var resultArray))
            {
                return(0);
            }

            var upperBound = Math.Min(resultArray.Length, maxCompletionResults);

            for (var i = 0; i < upperBound; i++)
            {
                results[i] = resultArray[i];
            }

            return(upperBound);
        }
예제 #9
0
        unsafe void ProcessSendCompletes(object o)
        {
            uint              maxResults = Math.Min(MaxOutstandingSend, int.MaxValue);
            RIO_RESULT *      results    = stackalloc RIO_RESULT[(int)maxResults];
            uint              count;
            IntPtr            key, bytes;
            NativeOverlapped *overlapped = stackalloc NativeOverlapped[1];

            while (true)
            {
                RioStatic.Notify(SendCompletionQueue);
                if (Kernel32.GetQueuedCompletionStatus(SendCompletionPort, out bytes, out key, out overlapped, -1) != 0)
                {
                    do
                    {
                        count = RioStatic.DequeueCompletion(SendCompletionQueue, results, maxResults);
                        if (count == 0xFFFFFFFF)
                        {
                            WinSock.ThrowLastWSAError();
                        }
                        for (var i = 0; i < count; i++)
                        {
                            var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation];
                            buf.Set();
                        }
                    } while (count > 0);
                }
                else
                {
                    var error = Marshal.GetLastWin32Error();

                    if (error != 0 && error != 735)
                    {
                        throw new Win32Exception(error);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
예제 #10
0
        private unsafe void Process(int id)
        {
            RIO_RESULT *      results = stackalloc RIO_RESULT[maxResults];
            uint              bytes, key;
            NativeOverlapped *overlapped;

            var worker = _workers[id];
            var completionPort = worker.completionPort;
            var cq     = worker.completionQueue;

            PooledSegment cachedOKBuffer = worker.bufferPool.GetBuffer();

            Buffer.BlockCopy(_okResponseBytes, 0, cachedOKBuffer.Buffer, cachedOKBuffer.Offset, _okResponseBytes.Length);
            cachedOKBuffer.RioBuffer.Length = (uint)_okResponseBytes.Length;
            worker.cachedOK = cachedOKBuffer.RioBuffer;

            PooledSegment cachedBusyBuffer = worker.bufferPool.GetBuffer();

            Buffer.BlockCopy(_busyResponseBytes, 0, cachedBusyBuffer.Buffer, cachedBusyBuffer.Offset, _busyResponseBytes.Length);
            cachedBusyBuffer.RioBuffer.Length = (uint)_busyResponseBytes.Length;
            worker.cachedBusy = cachedBusyBuffer.RioBuffer;

            uint       count;
            int        ret;
            RIO_RESULT result;

            while (!_token.IsCancellationRequested)
            {
                _rio.Notify(cq);
                var sucess = GetQueuedCompletionStatus(completionPort, out bytes, out key, out overlapped, -1);
                if (sucess)
                {
                    count = _rio.DequeueCompletion(cq, (IntPtr)results, maxResults);
                    ret   = _rio.Notify(cq);
                    for (var i = 0; i < count; i++)
                    {
                        result = results[i];
                        if (result.RequestCorrelation == RIO.CachedValue)
                        {
                            // cached send response, don't release buffer
                        }
                        else if (result.RequestCorrelation < 0)
                        {
                            // first send 2 buffers are cached responses
                            // so should next have a 0 for a send
                            //worker.bufferPool.ReleaseBuffer((int)-result.RequestCorrelation);
                        }
                        else
                        {
                            // receive
                            TcpConnection connection;
                            if (worker.connections.TryGetValue(result.ConnectionCorrelation, out connection))
                            {
                                connection.CompleteReceive(result.RequestCorrelation, result.BytesTransferred);
                            }
                        }
                    }
                }
                else
                {
                    var error = GetLastError();
                    if (error != 258)
                    {
                        throw new Exception(String.Format("ERROR: GetQueuedCompletionStatusEx returned {0}", error));
                    }
                }
            }
            cachedOKBuffer.Dispose();
            cachedBusyBuffer.Dispose();
        }