public DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, IEventExecutor executor, string name, IChannelHandler handler)
            : base(pipeline, executor, name, GetSkipPropagationFlags(handler))
        {
            Contract.Requires(handler != null);

            this.Handler = handler;
        }
            internal void Remove()
            {
                IEventExecutor executor = this.Executor;

                if (executor.InEventLoop)
                {
                    this.Remove0();
                }
                else
                {
                    executor.Execute(() => this.Remove0());
                }
            }
예제 #3
0
        private static void SetupServerLoop(IEventExecutor eventExecutor)
        {
            if (!_running)
            {
                return;
            }

            eventExecutor.Execute(() =>
            {
                eventExecutor.Schedule(() => { SetupServerLoop(eventExecutor); }, TimeSpan.FromMilliseconds(DelayBetweenTicks));
                Update();
            });
        }
예제 #4
0
        internal static void InvokeChannelUnregistered(FABHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelUnregistered();
            }
            else
            {
                nextExecutor.Execute(c => ((FABHandlerContext)c).InvokeChannelUnregistered(), next);
            }
        }
            internal void Remove()
            {
                IEventExecutor executor = Executor;

                if (executor.InEventLoop)
                {
                    Remove0();
                }
                else
                {
                    executor.Execute(s_removeAction, this);
                }
            }
        public Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress)
        {
            AbstractChannelHandlerContext next = this.FindContextOutbound();

            Contract.Requires(remoteAddress != null);
            // todo: check for cancellation

            IEventExecutor nextExecutor = next.Executor;

            return(nextExecutor.InEventLoop
                ? next.InvokeConnectAsync(remoteAddress, localAddress)
                : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeConnectAsync(remoteAddress, localAddress)));
        }
        internal static void InvokeChannelInactive(AbstractChannelHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelInactive();
            }
            else
            {
                nextExecutor.Execute(c => ((AbstractChannelHandlerContext)c).InvokeChannelInactive(), next);
            }
        }
        internal static void InvokeChannelWritabilityChanged(AbstractChannelHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelReadComplete();
            }
            else
            {
                // todo: consider caching task
                nextExecutor.Execute(InvokeChannelWritabilityChangedAction, next);
            }
        }
        internal static void InvokeUserEventTriggered(AbstractChannelHandlerContext next, object evt)
        {
            Contract.Requires(evt != null);
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeUserEventTriggered(evt);
            }
            else
            {
                nextExecutor.Execute(InvokeUserEventTriggeredAction, next, evt);
            }
        }
예제 #10
0
 private static void _NotifyListenerWithStackOverFlowProtection(IEventExecutor eventExecutor, IFuture <V> future, IFutureListener <V> listener)
 {
     if (eventExecutor.InEventLoop())
     {
         // @TODO: 增加对调用堆栈深度的保护(避免出现堆栈溢出)
         try
         {
             _NotifyListener(future, listener);
         }
         catch { }
         return;
     }
     _SafeExecute(eventExecutor, () => { _NotifyListener(future, listener); });
 }
예제 #11
0
        internal static void InvokeChannelReadComplete(FABHandlerContext next)
        {
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelReadComplete();
            }
            else
            {
                // todo: consider caching task
                nextExecutor.Execute(InvokeChannelReadCompleteAction, next);
            }
        }
        static Task SafeExecuteOutboundAsync(IEventExecutor executor, Func <Task> function)
        {
            var promise = new TaskCompletionSource();

            try
            {
                executor.Execute((p, func) => ((Func <Task>)func)().LinkOutcome((TaskCompletionSource)p), promise, function);
            }
            catch (Exception cause)
            {
                promise.TrySetException(cause);
            }
            return(promise.Task);
        }
예제 #13
0
        public DefaultChannelGroup(string name, IEventExecutor executor, bool stayClosed)
        {
            if (name is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.name);
            }

            _nonServerChannels = new ConcurrentDictionary <IChannelId, IChannel>(ChannelIdComparer.Default);
            _serverChannels    = new ConcurrentDictionary <IChannelId, IChannel>(ChannelIdComparer.Default);

            Name        = name;
            _executor   = executor;
            _stayClosed = stayClosed;
        }
        public Task DisconnectAsync()
        {
            if (!this.Channel.Metadata.HasDisconnect)
            {
                return(this.CloseAsync());
            }

            // todo: check for cancellation
            AbstractChannelHandlerContext next = this.FindContextOutbound();
            IEventExecutor nextExecutor        = next.Executor;

            return(nextExecutor.InEventLoop
                ? next.InvokeDisconnectAsync()
                : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeDisconnectAsync()));
        }
        public IChannelHandlerContext Flush()
        {
            AbstractChannelHandlerContext next = this.FindContextOutbound();
            IEventExecutor nextExecutor        = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeFlush();
            }
            else
            {
                nextExecutor.Execute(InvokeFlushAction, next);
            }
            return(this);
        }
예제 #16
0
        /// <summary>
        /// Creates a new <see cref="FixedChannelPool"/> instance.
        /// </summary>
        /// <param name="bootstrap">The <see cref="Bootstrap"/> that is used for connections.</param>
        /// <param name="handler">
        /// The <see cref="IChannelPoolHandler"/> that will be notified for the different pool actions.
        /// </param>
        /// <param name="healthChecker">
        /// The <see cref="IChannelHealthChecker"/> that will be used to check if a <see cref="IChannel"/> is still
        /// healthy when obtained from the <see cref="IChannelPool"/>.
        /// </param>
        /// <param name="action">
        /// The <see cref="AcquireTimeoutAction"/> to use or <c>null</c> if none should be used. In this case,
        /// <paramref name="acquireTimeout"/> must also be <c>null</c>.
        /// </param>
        /// <param name="acquireTimeout">
        /// A <see cref="TimeSpan"/> after which an pending acquire must complete, or the
        /// <see cref="AcquireTimeoutAction"/> takes place.
        /// </param>
        /// <param name="maxConnections">
        /// The number of maximal active connections. Once this is reached, new attempts to acquire an
        /// <see cref="IChannel"/> will be delayed until a connection is returned to the pool again.
        /// </param>
        /// <param name="maxPendingAcquires">
        /// The maximum number of pending acquires. Once this is exceeded, acquire attempts will be failed.
        /// </param>
        /// <param name="releaseHealthCheck">If <c>true</c>, will check channel health before offering it back.</param>
        /// <param name="lastRecentUsed">
        /// If <c>true</c>, <see cref="IChannel"/> selection will be LIFO. If <c>false</c>, it will be FIFO.
        /// </param>
        public FixedChannelPool(Bootstrap bootstrap, IChannelPoolHandler handler, IChannelHealthChecker healthChecker, AcquireTimeoutAction action, TimeSpan acquireTimeout, int maxConnections, int maxPendingAcquires, bool releaseHealthCheck, bool lastRecentUsed)
            : base(bootstrap, handler, healthChecker, releaseHealthCheck, lastRecentUsed)
        {
            if ((uint)(maxConnections - 1) > SharedConstants.TooBigOrNegative)
            {
                ThrowHelper.ThrowArgumentException_MaxConnections(maxConnections);
            }
            if ((uint)(maxPendingAcquires - 1) > SharedConstants.TooBigOrNegative)
            {
                ThrowHelper.ThrowArgumentException_MaxPendingAcquires(maxPendingAcquires);
            }

            _acquireTimeout = acquireTimeout;
            if (action == AcquireTimeoutAction.None && acquireTimeout == Timeout.InfiniteTimeSpan)
            {
                _timeoutTask = null;
            }
            else if (action == AcquireTimeoutAction.None && acquireTimeout != Timeout.InfiniteTimeSpan)
            {
                ThrowHelper.ThrowArgumentException_Action();
            }
            else if (action != AcquireTimeoutAction.None && acquireTimeout < TimeSpan.Zero)
            {
                ThrowHelper.ThrowArgumentException_AcquireTimeoutMillis(acquireTimeout);
            }
            else
            {
                switch (action)
                {
                case AcquireTimeoutAction.Fail:
                    _timeoutTask = new TimeoutTask(this, OnTimeoutFail);
                    break;

                case AcquireTimeoutAction.New:
                    _timeoutTask = new TimeoutTask(this, OnTimeoutNew);
                    break;

                default:
                    ThrowHelper.ThrowArgumentException_Action(); break;
                }
            }

            _executor           = bootstrap.Group().GetNext();
            _maxConnections     = maxConnections;
            _maxPendingAcquires = maxPendingAcquires;

            _pendingAcquireQueue = PlatformDependent.NewMpscQueue <AcquireTask>();
        }
        public IChannelHandlerContext Read()
        {
            AbstractChannelHandlerContext next = this.FindContextOutbound();
            IEventExecutor nextExecutor        = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeRead();
            }
            else
            {
                // todo: consider caching task
                nextExecutor.Execute(InvokeReadAction, next);
            }
            return(this);
        }
        public Task BindAsync(EndPoint localAddress)
        {
            Contract.Requires(localAddress != null);
            // todo: check for cancellation
            //if (!validatePromise(ctx, promise, false)) {
            //    // promise cancelled
            //    return;
            //}

            AbstractChannelHandlerContext next = this.FindContextOutbound();
            IEventExecutor nextExecutor        = next.Executor;

            return(nextExecutor.InEventLoop
                ? next.InvokeBindAsync(localAddress)
                : SafeExecuteOutboundAsync(nextExecutor, () => next.InvokeBindAsync(localAddress)));
        }
        internal static void InvokeChannelRead(AbstractChannelHandlerContext next, object msg)
        {
            Contract.Requires(msg != null);

            object         m            = next.pipeline.Touch(msg, next);
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeChannelRead(m);
            }
            else
            {
                nextExecutor.Execute(InvokeChannelReadAction, next, msg);
            }
        }
예제 #20
0
        private void _NotifyListeners()
        {
            IEventExecutor executor = Executor;

            if (executor.InEventLoop())
            {
                // @TODO: 增加对调用堆栈深度的保护(避免出现堆栈溢出)
                try
                {
                    _NotifyListenersNow();
                }
                catch { }
                return;
            }
            _SafeExecute(executor, () => { _NotifyListenersNow(); });
        }
        /// <summary>
        /// Creates a new <see cref="FixedChannelPool"/> instance.
        /// </summary>
        /// <param name="bootstrap">The <see cref="Bootstrap"/> that is used for connections.</param>
        /// <param name="handler">
        /// The <see cref="IChannelPoolHandler"/> that will be notified for the different pool actions.
        /// </param>
        /// <param name="healthChecker">
        /// The <see cref="IChannelHealthChecker"/> that will be used to check if a <see cref="IChannel"/> is still
        /// healthy when obtained from the <see cref="IChannelPool"/>.
        /// </param>
        /// <param name="action">
        /// The <see cref="AcquireTimeoutAction"/> to use or <c>null</c> if none should be used. In this case,
        /// <paramref name="acquireTimeout"/> must also be <c>null</c>.
        /// </param>
        /// <param name="acquireTimeout">
        /// A <see cref="TimeSpan"/> after which an pending acquire must complete, or the
        /// <see cref="AcquireTimeoutAction"/> takes place.
        /// </param>
        /// <param name="maxConnections">
        /// The number of maximal active connections. Once this is reached, new attempts to acquire an
        /// <see cref="IChannel"/> will be delayed until a connection is returned to the pool again.
        /// </param>
        /// <param name="maxPendingAcquires">
        /// The maximum number of pending acquires. Once this is exceeded, acquire attempts will be failed.
        /// </param>
        /// <param name="releaseHealthCheck">If <c>true</c>, will check channel health before offering it back.</param>
        /// <param name="lastRecentUsed">
        /// If <c>true</c>, <see cref="IChannel"/> selection will be LIFO. If <c>false</c>, it will be FIFO.
        /// </param>
        public FixedChannelPool(Bootstrap bootstrap, IChannelPoolHandler handler, IChannelHealthChecker healthChecker, AcquireTimeoutAction action, TimeSpan acquireTimeout, int maxConnections, int maxPendingAcquires, bool releaseHealthCheck, bool lastRecentUsed)
            : base(bootstrap, handler, healthChecker, releaseHealthCheck, lastRecentUsed)
        {
            if (maxConnections < 1)
            {
                throw new ArgumentException($"maxConnections: {maxConnections} (expected: >= 1)");
            }

            if (maxPendingAcquires < 1)
            {
                throw new ArgumentException($"maxPendingAcquires: {maxPendingAcquires} (expected: >= 1)");
            }

            this.acquireTimeout = acquireTimeout;
            if (action == AcquireTimeoutAction.None && acquireTimeout == Timeout.InfiniteTimeSpan)
            {
                this.timeoutTask = null;
            }
            else if (action == AcquireTimeoutAction.None && acquireTimeout != Timeout.InfiniteTimeSpan)
            {
                throw new ArgumentException("action");
            }
            else if (action != AcquireTimeoutAction.None && acquireTimeout < TimeSpan.Zero)
            {
                throw new ArgumentException($"acquireTimeoutMillis: {acquireTimeout} (expected: >= 1)");
            }
            else
            {
                switch (action)
                {
                case AcquireTimeoutAction.Fail:
                    this.timeoutTask = new TimeoutTask(this, this.OnTimeoutFail);
                    break;

                case AcquireTimeoutAction.New:
                    this.timeoutTask = new TimeoutTask(this, this.OnTimeoutNew);
                    break;

                default:
                    throw new ArgumentException("action");
                }
            }

            this.executor           = bootstrap.Group().GetNext();
            this.maxConnections     = maxConnections;
            this.maxPendingAcquires = maxPendingAcquires;
        }
 static void SafeExecuteOutbound(IEventExecutor executor, IRunnable task, TaskCompletionSource promise, object msg)
 {
     try
     {
         executor.Execute(task);
     }
     catch (Exception cause)
     {
         try
         {
             promise.TrySetException(cause);
         }
         finally
         {
             ReferenceCountUtil.Release(msg);
         }
     }
 }
예제 #23
0
            internal override void Execute()
            {
                IEventExecutor executor = this.Ctx.Executor;

                if (executor.InEventLoop)
                {
                    this.Pipeline.CallHandlerAdded0(this.Ctx);
                }
                else
                {
                    try
                    {
                        executor.Execute(this);
                    }
                    catch
                    {
                        Remove0(this.Ctx);
                        this.Ctx.SetRemoved();
                    }
                }
            }
예제 #24
0
            internal override void Execute()
            {
                IEventExecutor executor = this.Ctx.Executor;

                if (executor.InEventLoop)
                {
                    this.Pipeline.CallHandlerRemoved0(this.Ctx);
                }
                else
                {
                    try
                    {
                        executor.Execute(this);
                    }
                    catch
                    {
                        // remove0(...) was call before so just call AbstractChannelHandlerContext.setRemoved().
                        this.Ctx.SetRemoved();
                    }
                }
            }
        Task WriteAsync(object msg, bool flush)
        {
            AbstractChannelHandlerContext next = this.FindContextOutbound();
            object         m            = this.pipeline.Touch(msg, next);
            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                return(flush
                    ? next.InvokeWriteAndFlushAsync(m)
                    : next.InvokeWriteAsync(m));
            }
            else
            {
                var promise            = new TaskCompletionSource();
                AbstractWriteTask task = flush
                    ? WriteAndFlushTask.NewInstance(next, m, promise)
                    : (AbstractWriteTask)WriteTask.NewInstance(next, m, promise);
                SafeExecuteOutbound(nextExecutor, task, promise, msg);
                return(promise.Task);
            }
        }
예제 #26
0
        internal static void InvokeExceptionCaught(FABHandlerContext next, Exception cause)
        {
            Contract.Requires(cause != null);

            IEventExecutor nextExecutor = next.Executor;

            if (nextExecutor.InEventLoop)
            {
                next.InvokeExceptionCaught(cause);
            }
            else
            {
                try
                {
                    nextExecutor.Execute((c, e) => ((FABHandlerContext)c).InvokeExceptionCaught((Exception)e), next, cause);
                }
                catch (Exception t)
                {
                    throw t;
                }
            }
        }
예제 #27
0
        void DestroyUp(AbstractChannelHandlerContext ctx)
        {
            Thread currentThread = Thread.CurrentThread;
            AbstractChannelHandlerContext tailContext = this.tail;

            while (true)
            {
                if (ctx == tailContext)
                {
                    this.DestroyDown(currentThread, tailContext.Prev);
                    break;
                }

                IEventExecutor executor = ctx.Executor;
                if (!executor.IsInEventLoop(currentThread))
                {
                    executor.Unwrap().Execute((self, c) => ((DefaultChannelPipeline)self).DestroyUp((AbstractChannelHandlerContext)c), this, ctx);
                    break;
                }

                ctx = ctx.Next;
            }
        }
예제 #28
0
        void DestroyUp(FABHandlerContext ctx, bool inEventLoop)
        {
            XThread           currentThread = XThread.CurrentThread;
            FABHandlerContext tailContext   = this.tail;

            while (true)
            {
                if (ctx == tailContext)
                {
                    this.DestroyDown(currentThread, tailContext.Prev, inEventLoop);
                    break;
                }

                IEventExecutor executor = ctx.Executor;
                if (!inEventLoop && !executor.IsInEventLoop(currentThread))
                {
                    executor.Execute((self, c) => ((FABChannelPipeline)self).DestroyUp((FABHandlerContext)c, true), this, ctx);
                    break;
                }

                ctx         = ctx.Next;
                inEventLoop = false;
            }
        }
예제 #29
0
 public static bool TryGetCurrentExecutor(out IEventExecutor executor)
 {
     executor = currentExecutor;
     return(executor != null);
 }
예제 #30
0
 public ExecutorTaskScheduler(IEventExecutor executor)
 {
     this.executor = executor;
     this.executorCallback = this.ExecutorCallback;
 }
        public DefaultChannelHandlerInvoker(IEventExecutor executor)
        {
            Contract.Requires(executor != null);

            this.executor = executor;
        }
예제 #32
0
        static async Task <Tuple <EmbeddedChannel, SslStream> > SetupStreamAndChannelAsync(bool isClient, IEventExecutor executor, IWriteStrategy writeStrategy, SslProtocols protocol, List <Task> writeTasks)
        {
            X509Certificate2 tlsCertificate = TestResourceHelper.GetTestCertificate();
            string           targetHost     = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
            TlsHandler       tlsHandler     = isClient ?
                                              new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost)) :
                                              TlsHandler.Server(tlsCertificate);
            //var ch = new EmbeddedChannel(new LoggingHandler("BEFORE"), tlsHandler, new LoggingHandler("AFTER"));
            var ch = new EmbeddedChannel(tlsHandler);

            IByteBuffer readResultBuffer = Unpooled.Buffer(4 * 1024);
            Func <ArraySegment <byte>, Task <int> > readDataFunc = async output =>
            {
                if (writeTasks.Count > 0)
                {
                    await Task.WhenAll(writeTasks).WithTimeout(TestTimeout);

                    writeTasks.Clear();
                }

                if (readResultBuffer.ReadableBytes < output.Count)
                {
                    await ReadOutboundAsync(async() => ch.ReadOutbound <IByteBuffer>(), output.Count - readResultBuffer.ReadableBytes, readResultBuffer, TestTimeout);
                }
                Assert.NotEqual(0, readResultBuffer.ReadableBytes);
                int read = Math.Min(output.Count, readResultBuffer.ReadableBytes);
                readResultBuffer.ReadBytes(output.Array, output.Offset, read);
                return(read);
            };
            var mediationStream = new MediationStream(readDataFunc, input =>
            {
                Task task = executor.SubmitAsync(() => writeStrategy.WriteToChannelAsync(ch, input)).Unwrap();
                writeTasks.Add(task);
                return(task);
            });

            var driverStream = new SslStream(mediationStream, true, (_1, _2, _3, _4) => true);

            if (isClient)
            {
                await Task.Run(() => driverStream.AuthenticateAsServerAsync(tlsCertificate)).WithTimeout(TimeSpan.FromSeconds(5));
            }
            else
            {
                await Task.Run(() => driverStream.AuthenticateAsClientAsync(targetHost, null, protocol, false)).WithTimeout(TimeSpan.FromSeconds(5));
            }
            writeTasks.Clear();

            return(Tuple.Create(ch, driverStream));
        }
예제 #33
0
 public void SetUp(BenchmarkContext context)
 {
     _executor = CreateExecutor();
     _executorThroughput = context.GetCounter(EventExecutorThroughputCounterName);
 }
예제 #34
0
 internal static void SetCurrentExecutor(IEventExecutor executor) => currentExecutor = executor;
예제 #35
0
 public EventExecutorTaskScheduler(IEventExecutor executor)
 {
     _executor = executor;
 }