public TransportThread(IPEndPoint endPoint, IConnectionDispatcher connectionDispatcher, LinuxTransportOptions options, AcceptThread acceptThread, int threadId, int cpuId, ILoggerFactory loggerFactory)
 {
     if (connectionDispatcher == null)
     {
         throw new ArgumentNullException(nameof(connectionDispatcher));
     }
     ConnectionDispatcher = connectionDispatcher;
     ThreadId             = threadId;
     CpuId            = cpuId;
     EndPoint         = endPoint;
     TransportOptions = options;
     AcceptThread     = acceptThread;
     LoggerFactory    = loggerFactory;
 }
Ejemplo n.º 2
0
        private TransportThread[] CreateTransportThreads(IPEndPoint ipEndPoint, AcceptThread acceptThread)
        {
            var         threads         = new TransportThread[_transportOptions.ThreadCount];
            IList <int> preferredCpuIds = null;

            if (_transportOptions.SetThreadAffinity)
            {
                preferredCpuIds = GetPreferredCpuIds();
            }
            int cpuIdx = 0;

            for (int i = 0; i < _transportOptions.ThreadCount; i++)
            {
                int cpuId    = preferredCpuIds == null ? -1 : preferredCpuIds[cpuIdx++ % preferredCpuIds.Count];
                int threadId = Interlocked.Increment(ref s_threadId);
                var thread   = new TransportThread(ipEndPoint, _connectionDispatcher, _transportOptions, acceptThread, threadId, cpuId, _loggerFactory);
                threads[i] = thread;
            }
            return(threads);
        }
Ejemplo n.º 3
0
        public async Task BindAsync()
        {
            AcceptThread acceptThread;

            TransportThread[] transportThreads;
            lock (_gate)
            {
                if (_state != State.Created)
                {
                    ThrowInvalidOperation();
                }
                _state = State.Binding;

                IPEndPoint ipEndPoint;
                switch (_endPoint.Type)
                {
                case ListenType.IPEndPoint:
                    ipEndPoint       = _endPoint.IPEndPoint;
                    acceptThread     = null;
                    transportThreads = CreateTransportThreads(ipEndPoint, acceptThread);
                    break;

                case ListenType.SocketPath:
                case ListenType.FileHandle:
                    Socket socket;
                    if (_endPoint.Type == ListenType.SocketPath)
                    {
                        socket = Socket.Create(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified, blocking: false);
                        File.Delete(_endPoint.SocketPath);
                        socket.Bind(_endPoint.SocketPath);
                        socket.Listen(ListenBacklog);
                    }
                    else
                    {
                        socket = new Socket((int)_endPoint.FileHandle);
                    }
                    ipEndPoint       = null;
                    acceptThread     = new AcceptThread(socket);
                    transportThreads = CreateTransportThreads(ipEndPoint, acceptThread);
                    break;

                default:
                    throw new NotSupportedException($"Unknown ListenType: {_endPoint.Type}.");
                }

                _threads    = new ITransportActionHandler[transportThreads.Length + (acceptThread != null ? 1 : 0)];
                _threads[0] = acceptThread;
                for (int i = 0; i < transportThreads.Length; i++)
                {
                    _threads[i + (acceptThread == null ? 0 : 1)] = transportThreads[i];
                }

                _logger.LogDebug($@"BindAsync {_endPoint}: TC:{_transportOptions.ThreadCount} TA:{_transportOptions.SetThreadAffinity} IC:{_transportOptions.ReceiveOnIncomingCpu} DA:{_transportOptions.DeferAccept}");
            }

            var tasks = new Task[transportThreads.Length];

            for (int i = 0; i < transportThreads.Length; i++)
            {
                tasks[i] = transportThreads[i].BindAsync();
            }
            try
            {
                await Task.WhenAll(tasks);

                if (acceptThread != null)
                {
                    await acceptThread.BindAsync();
                }

                lock (_gate)
                {
                    if (_state == State.Binding)
                    {
                        _state = State.Bound;
                    }
                    else
                    {
                        ThrowInvalidOperation();
                    }
                }
            }
            catch
            {
                await StopAsync();

                throw;
            }
        }