Package com.linkedin.databus.client.netty

Source Code of com.linkedin.databus.client.netty.TestClientChannelClose$FakeRelay

package com.linkedin.databus.client.netty;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/


import java.io.StringWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.DefaultChannelPipeline;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.util.CharsetUtil;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.linkedin.databus.client.ChunkedBodyReadableByteChannel;
import com.linkedin.databus.client.DatabusHttpClientImpl;
import com.linkedin.databus.client.pub.ServerInfo;
import com.linkedin.databus.core.BufferInfoResponse;
import com.linkedin.databus.core.util.NamedThreadFactory;
import com.linkedin.databus.core.util.Utils;
import com.linkedin.databus2.core.container.ExtendedReadTimeoutHandler;
import com.linkedin.databus2.core.container.monitoring.mbean.ContainerStatisticsCollector;
import com.linkedin.databus2.test.TestUtil;

public class TestClientChannelClose
{
  static
  {
    TestUtil.setupLoggingWithTimestampedFile(true, "/tmp/TestClientChannelClose_", ".log", Level.ERROR);
  }

    public static enum MsgState
    {
      OPERATION_COMPLETE,
      CHANNEL_EXCEPTION_DECORATOR,
      CHANNEL_EXCEPTION_NO_DECORATOR,
      MSG_ENQUEUED,
          REQUEST_FAILURE,
      RESPONSE_FAILURE,
    }

    @Test
    public void testTimeoutCase() throws Exception
    {
      int port = Utils.getAvailablePort(27781);
      FakeRelay relay = new FakeRelay(port, 10, true , 100);
      TestClientConnectionFactory factory = null;
      try
      {
        relay.start();
        List<MsgState> msgList = new ArrayList<MsgState>();
        DatabusHttpClientImpl.Config conf = new DatabusHttpClientImpl.Config();
        conf.getContainer().setReadTimeoutMs(54);
        factory = new TestClientConnectionFactory(conf.build());
        ServerInfo relayInfo = new ServerInfo("dummy", "dummy", new InetSocketAddress(InetAddress.getLocalHost(), port), "dummy");
        for (int i = 0 ; i < 10 ; i++)
        {
            TestClientConnection conn = factory.createConnection(relayInfo, msgList);
          conn.requestCall();
          Thread.sleep(1000);
          System.out.println("MsgList is :" + msgList);
          //Assert.assertEquals(msgList.size(), 4, "Expected Size Check");
          int numMsgEnqueued = 0;
          for (MsgState s : msgList)
          {
            if (s == MsgState.MSG_ENQUEUED)
              numMsgEnqueued++;
          }
          Assert.assertEquals(numMsgEnqueued, 1, "Expected NumEnqueued Msgs");
          msgList.clear();
        }
      } finally {
        if ( null != relay )
          relay.shutdown();
        if (null != factory)
          factory.stop();
      }
    }


    public static class TestClientConnectionFactory
    {
      private final ExecutorService _bossThreadPool;
      private final ExecutorService _ioThreadPool;
      private final Timer _timeoutTimer;
      private final DatabusHttpClientImpl.StaticConfig _clientConfig;
      private final ChannelFactory _channelFactory;
      private final ChannelGroup _channelGroup; //provides automatic channel closure on shutdown

      public TestClientConnectionFactory(
          DatabusHttpClientImpl.StaticConfig clientConfig)
      {
        _bossThreadPool = Executors.newCachedThreadPool(new NamedThreadFactory("boss"));;
        _ioThreadPool = Executors.newCachedThreadPool(new NamedThreadFactory("io"));;
        _timeoutTimer = new HashedWheelTimer(5, TimeUnit.MILLISECONDS);
        _clientConfig = clientConfig;
        _channelFactory = new NioClientSocketChannelFactory(_bossThreadPool, _ioThreadPool);
        _channelGroup = new DefaultChannelGroup();;
      }

      public TestClientConnection createConnection(ServerInfo relay, List<MsgState> msgList)
      {
        return new TestClientConnection(relay, new ClientBootstrap(_channelFactory), null, _timeoutTimer,
                                        _clientConfig, _channelGroup, msgList,
                                        15000, Logger.getLogger(TestClientConnectionFactory.class));
      }

      public void stop()
        throws InterruptedException
      {
        _channelGroup.close().await();
        _timeoutTimer.stop();
      }
    }

    public static class TestHttpResponseProcessor
      extends AbstractHttpResponseProcessorDecorator <ChunkedBodyReadableByteChannel>
    {
    private List<MsgState> msgList;
    private final ExtendedReadTimeoutHandler _readTimeOutHandler;

    public TestHttpResponseProcessor(List<MsgState> msgList, ExtendedReadTimeoutHandler readTimeOutHandler)
    {
      super(new ChunkedBodyReadableByteChannel());
      this.msgList = msgList;
      this._readTimeOutHandler = readTimeOutHandler;
    }

      @Override
      public void finishResponse() throws Exception
      {
        super.finishResponse();
        System.out.println("finished response for /test");
        if (null != _readTimeOutHandler) _readTimeOutHandler.stop();
      }

      @Override
      public  void startResponse(HttpResponse response) throws Exception
      {
        LOG.info("Start Response !!");
        try
        {
          Thread.sleep(200);
        } catch (InterruptedException ie) {}
            super.startResponse(response);
            msgList.add(MsgState.MSG_ENQUEUED);
      }

    @Override
    public void handleChannelException(Throwable cause)
    {

      if ((_responseStatus != ResponseStatus.CHUNKS_SEEN) &&
          (_responseStatus != ResponseStatus.CHUNKS_FINISHED))
      {
        LOG.info("CHannel Exception : Message Enqueued !!");
        msgList.add(MsgState.MSG_ENQUEUED);
      }


      if (null != _decorated)
      {
        System.out.println("Response Status is :" + _responseStatus);
        msgList.add(MsgState.CHANNEL_EXCEPTION_DECORATOR);
        _decorated.channelException(cause);
      }
      else
      {
        msgList.add(MsgState.CHANNEL_EXCEPTION_NO_DECORATOR);
        LOG.error("channel exception but no decorated object:" + cause.getClass() + ":" +
            cause.getMessage());
        if (LOG.isDebugEnabled()) LOG.error(cause);
      }
    }
    }

    public static class TestClientConnection extends AbstractNettyHttpConnection
    {
      private ExtendedReadTimeoutHandler _readTimeOutHandler;
      private final List<MsgState> _msgList;

      public TestClientConnection(ServerInfo relay,
                  ClientBootstrap bootstrap,
                  ContainerStatisticsCollector containerStatsCollector,
                  Timer timeoutTimer,
                  DatabusHttpClientImpl.StaticConfig clientConfig,
                  ChannelGroup channelGroup,
                  List<MsgState> msgList,
                  long timeoutMs,
                  Logger log)
      {
        super(relay, bootstrap, null, timeoutTimer, timeoutMs, timeoutMs, channelGroup, 1, log);
        _msgList = msgList;
      }

      public void requestCall()
      {
        final TestClientConnection me = this;
        if (null == _channel || ! _channel.isConnected())
        {
          connectWithListener(new ConnectResultListener()
              {
                @Override
                public void onConnectSuccess(Channel channel)
                {
                  me.onConnected();
                }

                @Override
                public void onConnectFailure(Throwable cause)
                {
                  _msgList.add(MsgState.REQUEST_FAILURE);
                }
              });
        }
        else
        {
          onConnected();
        }
      }

      void onConnected()
      {
        ChannelPipeline channelPipeline = _channel.getPipeline();
        _readTimeOutHandler = (ExtendedReadTimeoutHandler)channelPipeline.get(GenericHttpClientPipelineFactory.READ_TIMEOUT_HANDLER_NAME);
        _readTimeOutHandler.start(channelPipeline.getContext(_readTimeOutHandler));

        TestHttpResponseProcessor testResponseProcessor =
            new TestHttpResponseProcessor(_msgList,_readTimeOutHandler);

            String uriString = "/test";
        HttpRequest request = createEmptyRequest(uriString);

        sendRequest(request, new AbstractNettyHttpConnection.SendRequestResultListener(){
            @Override
            public void onSendRequestSuccess(HttpRequest req)
            {
              _msgList.add(MsgState.REQUEST_FAILURE);
            }
            @Override
            public void onSendRequestFailure(HttpRequest req, Throwable cause)
            {
              onResponseFailure(cause);
            }
        }, testResponseProcessor);
      }

      private void onResponseFailure(Throwable cause)
      {
      }
    }

  public static class FakeRelay extends Thread
  {
    int _port;
    long _scn;
    boolean _returnSCN;
    ServerBootstrap _bootstrap;
    int _timeout;

    public FakeRelay(int port, long scn, boolean returnSCN, int timeout)
    {
      _port = port;
      _scn = scn;
      _returnSCN = returnSCN;
      _timeout = timeout;
    }

    @Override
    public void run()
    {
      _bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
          Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

      // Set up the event pipeline factory.
      _bootstrap.setPipelineFactory(new HttpServerPipelineFactory());

      // Bind and start to accept incoming connections.
      _bootstrap.bind(new InetSocketAddress(_port));
    }

    void shutdown()
    {
      if(_bootstrap != null)
      {
        _bootstrap.releaseExternalResources();
      }
    }

    class HttpServerPipelineFactory implements ChannelPipelineFactory
    {
      @Override
      public ChannelPipeline getPipeline() throws Exception
      {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = new DefaultChannelPipeline();
        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("deflater", new HttpContentCompressor());
        pipeline.addLast("handler", new HttpRequestHandler());
        return pipeline;
      }
    }
    class HttpRequestHandler extends SimpleChannelUpstreamHandler
    {
      @Override
      public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
      {
        System.out.println("Server : Request received");
        BufferInfoResponse bfResponse = new BufferInfoResponse();

        bfResponse.setMaxScn(_scn);
        bfResponse.setMinScn(_scn - 5000);
        bfResponse.setTimestampFirstEvent(System.currentTimeMillis() - 1000);
        bfResponse.setTimestampLatestEvent(System.currentTimeMillis());

        if(_timeout > 0)
        {
          //Thread.currentThread().sleep(_timeout);
        }
        if(_returnSCN)
        {
          ObjectMapper mapper = new ObjectMapper();
          StringWriter sw = new StringWriter();
          mapper.writeValue(sw, bfResponse);

          HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
          response.setContent(ChannelBuffers.copiedBuffer(sw.toString(), CharsetUtil.UTF_8));
          response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
          e.getChannel().write(response);
              try
              {
                Thread.sleep(_timeout);
              } catch (InterruptedException ie) {

              }
          e.getChannel().close();
        }

        else
        {
          HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
          response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
          e.getChannel().write(response);
          e.getChannel().close();
        }
      }
    }
  }

}
TOP

Related Classes of com.linkedin.databus.client.netty.TestClientChannelClose$FakeRelay

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.