Esempio n. 1
0
        public async Task TestReleaseAfterClosePool()
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);

            var pool = new FixedChannelPool(cb, new TestChannelPoolHandler(), 2);
            IChannel channel = await pool.AcquireAsync();
            pool.Close();

            await _group.GetNext().SubmitAsync(() => TaskUtil.Completed);
            var e = await Assert.ThrowsAsync<InvalidOperationException>(async () => await pool.ReleaseAsync(channel));
            Assert.Same(FixedChannelPool.PoolClosedOnReleaseException, e);

            // Since the pool is closed, the Channel should have been closed as well.
            await channel.CloseCompletion;
            Assert.False(channel.IsOpen, "Unexpected open channel");
            await sc.CloseAsync();
            pool.Close();
        }
Esempio n. 2
0
        private async Task TestAcquireTimeout0(long timeoutMillis)
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);
            var handler = new TestChannelPoolHandler();
            var pool = new FixedChannelPool(cb, handler, ChannelActiveHealthChecker.Instance, FixedChannelPool.AcquireTimeoutAction.Fail, TimeSpan.FromMilliseconds(timeoutMillis), 1, int.MaxValue);

            IChannel channel = await pool.AcquireAsync();
            try
            {
                await Assert.ThrowsAsync<TimeoutException>(async () => await pool.AcquireAsync());
            }
            finally
            {
                await sc.CloseAsync();
                await channel.CloseAsync();
                pool.Close();
            }
        }
Esempio n. 3
0
        public async Task TestReleaseDifferentPool()
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);
            var handler = new TestChannelPoolHandler();
            var pool = new FixedChannelPool(cb, handler, 1, 1);
            var pool2 = new FixedChannelPool(cb, handler, 1, 1);

            IChannel channel = await pool.AcquireAsync();

            try
            {
                await Assert.ThrowsAsync<ArgumentException>(async () => await pool2.ReleaseAsync(channel));
            }
            finally
            {
                await sc.CloseAsync();
                await channel.CloseAsync();
                pool.Close();
                pool2.Close();
            }
        }
Esempio n. 4
0
        public async Task TestAcquireBoundQueue()
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);
            var handler = new TestChannelPoolHandler();
            var pool = new FixedChannelPool(cb, handler, 1, 1);

            IChannel channel = await pool.AcquireAsync();
            var future = pool.AcquireAsync();
            Assert.False(future.IsCompleted);

            try
            {
                await Assert.ThrowsAsync<InvalidOperationException>(async () => await pool.AcquireAsync());
            }
            finally
            {
                await sc.CloseAsync();
                await channel.CloseAsync();
                pool.Close();
            }
        }
Esempio n. 5
0
        public async Task TestAcquireNewConnectionWhen()
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);
            var handler = new TestChannelPoolHandler();
            var pool = new FixedChannelPool(cb, handler, 1);
            IChannel channel1 = await pool.AcquireAsync();
            await channel1.CloseAsync();
#pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法
            pool.ReleaseAsync(channel1);
#pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法

            IChannel channel2 = await pool.AcquireAsync();

            Assert.NotSame(channel1, channel2);
            await sc.CloseAsync();
            await channel2.CloseAsync();
            pool.Close();
        }
Esempio n. 6
0
        public async Task TestAcquireNewConnection()
        {
            var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                .Group(_group)
                .Channel<LocalServerChannel>()
                .ChildHandler(
                    new ActionChannelInitializer<LocalChannel>(
                        ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);
            var handler = new TestChannelPoolHandler();
            var pool = new FixedChannelPool(
                cb,
                handler,
                ChannelActiveHealthChecker.Instance,
                FixedChannelPool.AcquireTimeoutAction.New,
                TimeSpan.FromMilliseconds(500),
                1,
                int.MaxValue);

            IChannel channel = await pool.AcquireAsync();
            IChannel channel2 = await pool.AcquireAsync();
            Assert.NotSame(channel, channel2);
            await sc.CloseAsync();
            await channel.CloseAsync();
            await channel2.CloseAsync();
            pool.Close();
        }
Esempio n. 7
0
        public async Task TestReleaseClosed()
        {
            var       addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb   = new Bootstrap().RemoteAddress(addr).Group(_group).Channel <LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                                 .Group(_group)
                                 .Channel <LocalServerChannel>()
                                 .ChildHandler(
                new ActionChannelInitializer <LocalChannel>(
                    ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);

            var      pool    = new FixedChannelPool(cb, new TestChannelPoolHandler(), 2);
            IChannel channel = await pool.AcquireAsync();

            await channel.CloseAsync();

            await pool.ReleaseAsync(channel);

            await sc.CloseAsync();

            pool.Close();
        }
Esempio n. 8
0
        public async Task TestAcquire()
        {
            var       addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId());
            Bootstrap cb   = new Bootstrap().RemoteAddress(addr).Group(_group).Channel <LocalChannel>();

            ServerBootstrap sb = new ServerBootstrap()
                                 .Group(_group)
                                 .Channel <LocalServerChannel>()
                                 .ChildHandler(
                new ActionChannelInitializer <LocalChannel>(
                    ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter()))
                );

            // Start server
            IChannel sc = await sb.BindAsync(addr);

            var handler = new CountingChannelPoolHandler();

            var pool = new FixedChannelPool(cb, handler, 1);

            IChannel channel = await pool.AcquireAsync();

            var future = pool.AcquireAsync();

            Assert.False(future.IsCompleted);

            await pool.ReleaseAsync(channel);

            await Task.Delay(TimeSpan.FromSeconds(1));

            Assert.True(future.IsCompleted);

            IChannel channel2 = future.Result;

            Assert.Same(channel, channel2);
            Assert.Equal(1, handler.ChannelCount);
            Assert.Equal(1, handler.AcquiredCount);
            Assert.Equal(1, handler.ReleasedCount);

            await sc.CloseAsync();

            await channel2.CloseAsync();

            pool.Close();
        }
Esempio n. 9
0
        public async Task TestDeadlockOnRemove()
        {
            IEventLoop thread1    = new SingleThreadEventLoop();
            Bootstrap  bootstrap1 = new Bootstrap()
                                    .Channel <LocalChannel>().Group(thread1).LocalAddress(new LocalAddress("#1"));
            IEventLoop thread2    = new SingleThreadEventLoop();
            Bootstrap  bootstrap2 = new Bootstrap()
                                    .Channel <LocalChannel>().Group(thread2).LocalAddress(new LocalAddress("#2"));

            // pool1 runs on thread2, pool2 runs on thread1
            FixedChannelPool pool1 = new FixedChannelPool(bootstrap2, NoopHandler.Instance, 1);
            FixedChannelPool pool2 = new FixedChannelPool(bootstrap1, NoopHandler.Instance, 1);
            var channelPoolMap     = new TestChannelPoolMap1(pool1, pool2);

            Assert.Same(pool1, channelPoolMap.Get("#1"));
            Assert.Same(pool2, channelPoolMap.Get("#2"));

            // thread1 tries to remove pool1 which is running on thread2
            // thread2 tries to remove pool2 which is running on thread1

            var barrier = new Barrier(2);

            var future1 = thread1.SubmitAsync(() =>
            {
                if (!barrier.SignalAndWait(TimeSpan.FromSeconds(1)))
                {
                    throw new TimeoutException();
                }
                channelPoolMap.Remove("#1");
                return(1);
            });

            var future2 = thread2.SubmitAsync(() =>
            {
                if (!barrier.SignalAndWait(TimeSpan.FromSeconds(1)))
                {
                    throw new TimeoutException();
                }
                channelPoolMap.Remove("#2");
                return(2);
            });

            // A blocking close on remove will cause a deadlock here and the test will time out
            try
            {
                var result = await TaskUtil.WaitAsync(future1, TimeSpan.FromSeconds(1));

                if (!result || !future1.IsSuccess())
                {
                    throw new TimeoutException();
                }
                result = await TaskUtil.WaitAsync(future2, TimeSpan.FromSeconds(1));

                if (!result || !future2.IsSuccess())
                {
                    throw new TimeoutException();
                }
            }
            catch (TimeoutException)
            {
                Assert.False(true); // Fail the test on timeout to distinguish from other errors
            }
            finally
            {
                pool1.Close();
                pool2.Close();
                channelPoolMap.Close();
                Shutdown(thread1, thread2);
            }
        }
Esempio n. 10
0
        public async Task TestDeadlockOnAcquire()
        {
            IEventLoop threadA1    = new SingleThreadEventLoop();
            Bootstrap  bootstrapA1 = new Bootstrap()
                                     .Channel <LocalChannel>().Group(threadA1).LocalAddress(new LocalAddress("A1"));
            IEventLoop threadA2    = new SingleThreadEventLoop();
            Bootstrap  bootstrapA2 = new Bootstrap()
                                     .Channel <LocalChannel>().Group(threadA2).LocalAddress(new LocalAddress("A2"));
            IEventLoop threadB1    = new SingleThreadEventLoop();
            Bootstrap  bootstrapB1 = new Bootstrap()
                                     .Channel <LocalChannel>().Group(threadB1).LocalAddress(new LocalAddress("B1"));
            IEventLoop threadB2    = new SingleThreadEventLoop();
            Bootstrap  bootstrapB2 = new Bootstrap()
                                     .Channel <LocalChannel>().Group(threadB2).LocalAddress(new LocalAddress("B2"));

            FixedChannelPool poolA1 = new FixedChannelPool(bootstrapA1, NoopHandler.Instance, 1);
            FixedChannelPool poolA2 = new FixedChannelPool(bootstrapB2, NoopHandler.Instance, 1);
            FixedChannelPool poolB1 = new FixedChannelPool(bootstrapB1, NoopHandler.Instance, 1);
            FixedChannelPool poolB2 = new FixedChannelPool(bootstrapA2, NoopHandler.Instance, 1);

            // Synchronize threads on these barriers to ensure order of execution, first wait until each thread is inside
            // the newPool callbak, then hold the two threads that should lose the match until the first two returns, then
            // release them to test if they deadlock when trying to release their pools on each other's threads.
            Barrier arrivalBarrier = new Barrier(4);
            Barrier releaseBarrier = new Barrier(3);

            var channelPoolMap = new TestChannelPoolMap0(
                threadA1, threadA2, threadB1, threadB2,
                poolA1, poolA2, poolB1, poolB2, arrivalBarrier, releaseBarrier);

            // Thread A1 calls ChannelPoolMap.get(A)
            // Thread A2 calls ChannelPoolMap.get(A)
            // Thread B1 calls ChannelPoolMap.get(B)
            // Thread B2 calls ChannelPoolMap.get(B)

            var futureA1 = threadA1.SubmitAsync(() =>
            {
                return(channelPoolMap.Get("A"));
            });

            var futureA2 = threadA2.SubmitAsync(() =>
            {
                return(channelPoolMap.Get("A"));
            });

            var futureB1 = threadB1.SubmitAsync(() =>
            {
                return(channelPoolMap.Get("B"));
            });

            var futureB2 = threadB2.SubmitAsync(() =>
            {
                return(channelPoolMap.Get("B"));
            });

            // Thread A1 succeeds on updating the map and moves on
            // Thread B1 succeeds on updating the map and moves on
            // These should always succeed and return with new pools
            try
            {
                var result = await TaskUtil.WaitAsync(futureA1, TimeSpan.FromSeconds(1));

                if (!result || !futureA1.IsSuccess())
                {
                    throw new TimeoutException();
                }
                Assert.Same(poolA1, futureA1.Result);

                result = await TaskUtil.WaitAsync(futureB1, TimeSpan.FromSeconds(1));

                if (!result || !futureB1.IsSuccess())
                {
                    throw new TimeoutException();
                }
                Assert.Same(poolB1, futureB1.Result);
            }
            catch (Exception e)
            {
                Shutdown(threadA1, threadA2, threadB1, threadB2);
                throw e;
            }

            // Now release the other two threads which at this point lost the race and will try to clean up the acquired
            // pools. The expected scenario is that both pools close, in case of a deadlock they will hang.
            if (!releaseBarrier.SignalAndWait(TimeSpan.FromSeconds(1)))
            {
                Assert.False(true);
            }

            // Thread A2 fails to update the map and submits close to thread B2
            // Thread B2 fails to update the map and submits close to thread A2
            // If the close is blocking, then these calls will time out as the threads are waiting for each other
            // If the close is not blocking, then the previously created pools will be returned
            try
            {
                var result = await TaskUtil.WaitAsync(futureA2, TimeSpan.FromSeconds(1));

                if (!result || !futureA2.IsSuccess())
                {
                    throw new TimeoutException();
                }
                Assert.Same(poolA1, futureA2.Result);

                result = await TaskUtil.WaitAsync(futureB2, TimeSpan.FromSeconds(1));

                if (!result || !futureB2.IsSuccess())
                {
                    throw new TimeoutException();
                }
                Assert.Same(poolB1, futureB2.Result);
            }
            catch (TimeoutException)
            {
                Assert.False(true); // Fail the test on timeout to distinguish from other errors
                throw;
            }
            finally
            {
                poolA1.Close();
                poolA2.Close();
                poolB1.Close();
                poolB2.Close();
                channelPoolMap.Close();
                Shutdown(threadA1, threadA2, threadB1, threadB2);
            }
        }