// AVRO-625 [Test]
        public void CancelPendingRequestsOnTransceiverClose()
        {
            // Start up a second server so that closing the server doesn't
            // interfere with the other unit tests:
            var blockingSimpleImpl = new BlockingSimpleImpl();

            var responder = new SpecificResponder <Simple>(blockingSimpleImpl);
            var server2   = new SocketServer("localhost", 0, responder);

            server2.Start();

            try
            {
                int serverPort = server2.Port;

                var transceiver2 = new SocketTransceiver("localhost", serverPort);

                var addFuture = new CallFuture <int>();
                try
                {
                    var simpleClient2 = SpecificRequestor.CreateClient <SimpleCallback>(transceiver2);

                    // The first call has to block for the handshake:
                    Assert.AreEqual(3, simpleClient2.add(1, 2));

                    // Now acquire the semaphore so that the server will block:
                    blockingSimpleImpl.acquireRunPermit();
                    simpleClient2.add(1, 2, addFuture);
                }
                finally
                {
                    // When the transceiver is closed, the CallFuture should get
                    // an IOException
                    transceiver2.Close();
                }
                bool ioeThrown = false;
                try
                {
                    addFuture.WaitForResult(2000);
                }
                catch (Exception)
                {
                }
                //catch (ExecutionException e) {
                //  ioeThrown = e.getCause() instanceof IOException;
                //  Assert.assertTrue(e.getCause() instanceof IOException);
                //} catch (Exception e) {
                //  e.printStackTrace();
                //  Assert.fail("Unexpected Exception: " + e.toString());
                //}
                Assert.IsTrue(ioeThrown, "Expected IOException to be thrown");
            }
            finally
            {
                blockingSimpleImpl.releaseRunPermit();
                server2.Stop();
            }
        }
        // AVRO-625 [Test]
        public void CancelPendingRequestsAfterChannelCloseByServerShutdown()
        {
            // The purpose of this test is to verify that a client doesn't stay
            // blocked when a server is unexpectedly killed (or when for some
            // other reason the channel is suddenly closed) while the server
            // was in the process of handling a request (thus after it received
            // the request, and before it returned the response).

            // Start up a second server so that closing the server doesn't
            // interfere with the other unit tests:
            var blockingSimpleImpl = new BlockingSimpleImpl();

            var responder = new SpecificResponder <Simple>(blockingSimpleImpl);
            var server2   = new SocketServer("localhost", 0, responder);

            server2.Start();
            SocketTransceiver transceiver2 = null;

            try
            {
                transceiver2 = new SocketTransceiver("localhost", server2.Port);

                var simpleClient2 = SpecificRequestor.CreateClient <SimpleCallback>(transceiver2);

                // Acquire the method-enter permit, which will be released by the
                // server method once we call it
                blockingSimpleImpl.acquireEnterPermit();

                // Acquire the run permit, to avoid that the server method returns immediately
                blockingSimpleImpl.acquireRunPermit();

                var t = new Thread(() =>
                {
                    try
                    {
                        simpleClient2.add(3, 4);
                        Assert.Fail("Expected an exception");
                    }
                    catch (Exception)
                    {
                        // expected
                    }
                });
                // Start client call
                t.Start();

                // Wait until method is entered on the server side
                blockingSimpleImpl.acquireEnterPermit();

                // The server side method is now blocked waiting on the run permit
                // (= is busy handling the request)

                // Stop the server
                server2.Stop();

                // With the server gone, we expect the client to get some exception and exit
                // Wait for client thread to exit
                t.Join(10000);

                Assert.IsFalse(t.IsAlive, "Client request should not be blocked on server shutdown");
            }
            finally
            {
                blockingSimpleImpl.releaseRunPermit();
                server2.Stop();
                if (transceiver2 != null)
                {
                    transceiver2.Close();
                }
            }
        }
Пример #3
0
        public void TestSocketTransceiverWhenServerStops()
        {
            Responder responder = new SpecificResponder <Mail>(new MailImpl());
            var       server    = new SocketServer("localhost", 0, responder);

            server.Start();

            var transceiver = new SocketTransceiver("localhost", server.Port);
            var mail        = SpecificRequestor.CreateClient <Mail>(transceiver);

            int[] successes = { 0 };
            int   failures  = 0;

            int[] quitOnFailure = { 0 };
            var   threads       = new List <Thread>();

            // Start a bunch of client threads that use the transceiver to send messages
            for (int i = 0; i < 100; i++)
            {
                var thread = new Thread(
                    () =>
                {
                    while (true)
                    {
                        try
                        {
                            mail.send(CreateMessage());
                            Interlocked.Increment(ref successes[0]);
                        }
                        catch (Exception)
                        {
                            Interlocked.Increment(ref failures);

                            if (Interlocked.Add(ref quitOnFailure[0], 0) == 1)
                            {
                                return;
                            }
                        }
                    }
                });

                thread.Name = "Thread" + i;
                threads.Add(thread);
                thread.Start();
            }

            // Be sure the threads are running: wait until we get a good deal of successes
            while (Interlocked.Add(ref successes[0], 0) < 10000)
            {
                Thread.Sleep(50);
            }

            // Now stop the server
            server.Stop();

            // Server is stopped: successes should not increase anymore: wait until we're in that situation
            while (true)
            {
                int previousSuccesses = Interlocked.Add(ref successes[0], 0);
                Thread.Sleep(500);
                if (previousSuccesses == Interlocked.Add(ref successes[0], 0))
                {
                    break;
                }
            }

            server.Start();

            long now = CurrentTimeMillis();

            int previousSuccesses2 = successes[0];

            while (true)
            {
                Thread.Sleep(500);
                if (successes[0] > previousSuccesses2)
                {
                    break;
                }
                if (CurrentTimeMillis() - now > 5000)
                {
                    Console.WriteLine("FYI: requests don't continue immediately...");
                    break;
                }
            }

            // Stop our client, we would expect this to go on immediately
            Console.WriteLine("Stopping transceiver");

            Interlocked.Add(ref quitOnFailure[0], 1);
            now = CurrentTimeMillis();
            transceiver.Close();

            // Wait for all threads to quit
            while (true)
            {
                threads.RemoveAll(x => !x.IsAlive);

                if (threads.Count > 0)
                {
                    Thread.Sleep(1000);
                }
                else
                {
                    break;
                }
            }

            if (CurrentTimeMillis() - now > 10000)
            {
                Assert.Fail("Stopping NettyTransceiver and waiting for client threads to quit took too long.");
            }
            else
            {
                Console.WriteLine("Stopping NettyTransceiver and waiting for client threads to quit took "
                                  + (CurrentTimeMillis() - now) + " ms");
            }
        }