예제 #1
0
        /// <summary>
        /// Creates a request queue for this socket operation
        /// </summary>
        private void CreateRequestQueue()
        {
            // Allocate completion from completion queue
            if (!RioNative.AllocateRIOCompletion((uint)InitialCqRoom))
            {
                var socketException = new SocketException();
                logger.LogError(
                    "AllocateRIOCompletion() failed to allocate completions to this socket. Returns error {0}",
                    socketException.ErrorCode);
                throw socketException;
            }

            // Create the RQ for this socket.
            connectionId = GenerateUniqueKey();
            while (!RioNative.ConnectionTable.TryAdd(connectionId, this))
            {
                connectionId = GenerateUniqueKey();
            }

            rioRqHandle = RioNative.CreateRIORequestQueue(SockHandle, rqReservedSize >> 1, rqReservedSize >> 1, connectionId);
            if (rioRqHandle != IntPtr.Zero)
            {
                return;
            }

            // Error Handling
            var sockException = new SocketException();

            RioNative.ReleaseRIOCompletion((uint)InitialCqRoom);
            RioSocketWrapper sock;

            RioNative.ConnectionTable.TryRemove(connectionId, out sock);
            logger.LogError("CreateRIORequestQueue() returns error {0}", sockException.ErrorCode);
            throw sockException;
        }
예제 #2
0
        private int AllocateRequest()
        {
            var newRqUsed = rqUsed + 1;

            if (newRqUsed > rqReservedSize)
            {
                var newRqReservedSize = rqReservedSize + rioRqGrowthFactor;
                if (!RioNative.AllocateRIOCompletion((uint)rioRqGrowthFactor))
                {
                    var errorCode = Marshal.GetLastWin32Error();
                    logger.LogError(
                        "Failed to allocate completions to this socket. AllocateRIOCompletion() returns error {0}",
                        errorCode);
                    return(errorCode);
                }

                // Resize the RQ.
                if (!RioNative.ResizeRIORequestQueue(rioRqHandle, (uint)newRqReservedSize >> 1, (uint)newRqReservedSize >> 1))
                {
                    var errorCode = Marshal.GetLastWin32Error();
                    logger.LogError("Failed to resize the request queue. ResizeRIORequestQueue() returns error {0}",
                                    errorCode);
                    RioNative.ReleaseRIOCompletion((uint)rioRqGrowthFactor);
                    return(errorCode);
                }

                // since it succeeded, update reserved with the new size
                rqReservedSize = (uint)newRqReservedSize;
            }

            // everything succeeded - update rqUsed with the new slots being used for this next IO
            rqUsed = newRqUsed;
            return(0);
        }
예제 #3
0
        private void Dispose(bool disposing)
        {
            // Mark this as disposed before changing anything else.
            var cleanedUp = isCleanedUp;

            isCleanedUp = true;
            if (!cleanedUp && disposing)
            {
                try
                {
                    // Release room back to Completion Queue
                    RioNative.ReleaseRIOCompletion((uint)InitialCqRoom);

                    // Remove this socket from the connected socket table.
                    RioSocketWrapper socket;
                    RioNative.ConnectionTable.TryRemove(connectionId, out socket);
                }
                catch (Exception)
                {
                    logger.LogDebug("RioNative default instance already disposed.");
                }

                // Remove all pending socket operations
                if (!requestContexts.IsEmpty)
                {
                    foreach (var keyValuePair in requestContexts)
                    {
                        // Release the data buffer of the pending operation
                        keyValuePair.Value.Data.Release();
                    }
                    requestContexts.Clear();
                }

                // Remove received Data from the queue, and release buffer back to byte pool.
                while (receivedDataQueue.Count > 0)
                {
                    ByteBuf data;
                    receivedDataQueue.TryTake(out data);
                    data.Release();
                }

                // Close the socket handle. No need to release Request Queue handle that
                // will be gone once the socket handle be closed.
                if (SockHandle != IntPtr.Zero)
                {
                    RioNative.closesocket(SockHandle);
                    SockHandle = IntPtr.Zero;
                }

                GC.SuppressFinalize(this);
            }

            isConnected = false;
            isListening = false;
        }