Package com.linkedin.databus2.core.container.netty

Source Code of com.linkedin.databus2.core.container.netty.DatabusRequestExecutionHandler

package com.linkedin.databus2.core.container.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 static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.SET_COOKIE;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;

import com.linkedin.databus.core.DbusConstants;
import com.linkedin.databus.core.data_model.PhysicalPartition;
import com.linkedin.databus.core.util.DbusHttpUtils;
import com.linkedin.databus2.core.container.DatabusHttpHeaders;
import com.linkedin.databus2.core.container.monitoring.mbean.ContainerStatisticsCollector;
import com.linkedin.databus2.core.container.request.DatabusRequest;
import com.linkedin.databus2.core.container.request.RequestProcessorRegistry;

/**
* Expects DatabusRequest objects and runs them
* @author cbotev
*
*/
public class DatabusRequestExecutionHandler extends SimpleChannelUpstreamHandler
{
  public static final String MODULE = DatabusRequestExecutionHandler.class.getName();
  public static final Logger LOG = Logger.getLogger(MODULE);

  private final RequestProcessorRegistry _processorRegistry;
  private final ServerContainer _serverContainer;

  private DatabusRequest _dbusRequest;
  private HttpRequest _httpRequest;

  public DatabusRequestExecutionHandler(ServerContainer serverContainer)
  {
    _serverContainer = serverContainer;
    _processorRegistry = _serverContainer.getProcessorRegistry();
  }

  @Override
  public void channelClosed(
      ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    super.channelClosed(ctx, e);
    ctx.setAttachment(null);
  }

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
  {
    if (e.getMessage() instanceof HttpRequest)
    {
      _httpRequest = (HttpRequest)e.getMessage();
      ctx.sendUpstream(e);
    }
    if (e.getMessage() instanceof DatabusRequest)
    {
      _dbusRequest = (DatabusRequest)e.getMessage();
      // If there is a physical partition stashed away, then restore it into the request now.
      if (ctx.getAttachment() != null &&  ctx.getAttachment() instanceof PhysicalPartition)
      {
        _dbusRequest.setCursorPartition((PhysicalPartition)(ctx.getAttachment()));
      }

      //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
      /*NettyStats nettyStats = _configManager.getNettyStats();
      boolean nettyStatsEnabled = nettyStats.isEnabled();
      CallCompletion callCompletion = nettyStatsEnabled ?
          nettyStats.getRequestHandler_writeResponse().startCall() :
          null;
      CallCompletion processRequestCompletion = null;*/
      try
      {
        if (LOG.isDebugEnabled())
        {
          LOG.debug("Creating response for command [" + _dbusRequest.getId() + "] " +
                    _dbusRequest.getName());
        }

        // Decide whether to close the connection or not.
        boolean keepAlive = isKeepAlive(_httpRequest);

        HttpResponse response = generateEmptyResponse();
        if (LOG.isDebugEnabled())
        {
          //We are debugging -- let's add some more info to the response
          response.addHeader(DatabusHttpHeaders.DATABUS_REQUEST_ID_HEADER,
                             Long.toString(_dbusRequest.getId()));
        }

        // Write the response.
        ChunkedBodyWritableByteChannel responseChannel = null;
        try
        {
          responseChannel = new ChunkedBodyWritableByteChannel(e.getChannel(), response);
          _dbusRequest.setResponseContent(responseChannel);

          if (LOG.isDebugEnabled())
          {
            LOG.debug("About to run command [" + _dbusRequest.getId() + "] " + _dbusRequest.getName());
          }

          //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
          /*if (nettyStatsEnabled)
          {
            processRequestCompletion = nettyStats.getRequestHandler_processRequest().startCall();
          }*/
          Future<DatabusRequest> responseFuture = _processorRegistry.run(_dbusRequest);

          ServerContainer.RuntimeConfig config = _dbusRequest.getConfig();
          int timeoutMs = config.getRequestProcessingBudgetMs();

          boolean done = responseFuture.isDone();
          while (!done)
          {
            try
            {
              responseFuture.get(timeoutMs, TimeUnit.MILLISECONDS);
              done = true;
              ctx.setAttachment(_dbusRequest.getCursorPartition());
            }
            catch (InterruptedException ie)
            {
              done = responseFuture.isDone();
            }
            catch (Exception ex)
            {
              done = true;
              _dbusRequest.setError(ex);
              // On any error, clear any context saved. We will start afresh in a new request.
              ctx.setAttachment(null);
              //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
              /*if (null != processRequestCompletion)
              {
                processRequestCompletion.endCallWithError(ex);
                processRequestCompletion = null;
              }*/
            }
          }
        }
        finally
        {
          if (null != responseChannel)
          {
            if (LOG.isDebugEnabled())
            {
              //Add some more debugging info
              long curTimeMs = System.currentTimeMillis();
              responseChannel.addMetadata(DatabusHttpHeaders.DATABUS_REQUEST_LATENCY_HEADER,
                                          Long.toString(curTimeMs - _dbusRequest.getCreateTimestampMs()));
            }
            responseChannel.close();
          }
          if (null != _dbusRequest.getResponseThrowable())
          {
            ContainerStatisticsCollector statsCollector = _serverContainer.getContainerStatsCollector();
            if (null != statsCollector)
            {
              statsCollector.registerContainerError(_dbusRequest.getResponseThrowable());
            }
          }
       }

        //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
        /*if (null != processRequestCompletion)
        {
          processRequestCompletion.endCall();
        }*/

        if (LOG.isDebugEnabled())
        {
          LOG.debug("Done runing command [" + _dbusRequest.getId() + "] " + _dbusRequest.getName());
        }

        // Close the non-keep-alive or hard-failed connection after the write operation is done.
        if (!keepAlive || null == responseChannel)
        {
          e.getChannel().close();
        }

        //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
        /*if (null != callCompletion)
        {
          callCompletion.endCall();
        }*/
      }
      catch (RuntimeException ex)
      {
        LOG.error("HttpRequestHandler.writeResponse error", ex);
        //FIXME   DDS-305: Rework the netty stats collector to use event-based stats aggregation
        /*if (null != callCompletion)
        {
          callCompletion.endCallWithError(ex);
        }*/
        ContainerStatisticsCollector statsCollector = _serverContainer.getContainerStatsCollector();
        if (null != statsCollector) statsCollector.registerContainerError(ex);
      }

    }
    else
    {
      //Pass on everything else
      ctx.sendUpstream(e);
    }
  }

  private HttpResponse generateEmptyResponse()
  {
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);

    //response.setContent(ChannelBuffers.wrappedBuffer(responseBody));
    response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
    response.setHeader("Access-Control-Allow-Origin", "*");

    setTrackingInfo(response);

    // Encode the cookie.
    String cookieString = _httpRequest.getHeader(COOKIE);
    if (cookieString != null)
    {
        CookieDecoder cookieDecoder = new CookieDecoder();
        Set<Cookie> cookies = cookieDecoder.decode(cookieString);
        if(!cookies.isEmpty()) {
            // Reset the cookies if necessary.
            CookieEncoder cookieEncoder = new CookieEncoder(true);
            for (Cookie cookie : cookies) {
                cookieEncoder.addCookie(cookie);
            }
            response.addHeader(SET_COOKIE, cookieEncoder.encode());
        }
    }

    return response;
  }

  /**
   * Set headers to allow clients to trace information of relays across VIPs
   * @param response
   */
  private void setTrackingInfo(HttpResponse response)
  {
    String hostname = DbusConstants.getMachineName();
    if (null == hostname || DbusConstants.UNKNOWN_HOST.equals(hostname))
    {
      hostname = DbusHttpUtils.getLocalHostName();
    }
    response.setHeader(DatabusHttpHeaders.DBUS_SERVER_HOST_HDR, hostname);

    String serviceId = DbusConstants.getServiceIdentifier();
    if (! DbusConstants.UNKNOWN_SERVICE_ID.equals(serviceId))
    {
      response.setHeader(DatabusHttpHeaders.DBUS_SERVER_SERVICE_HDR,
                         DbusConstants.getServiceIdentifier());
    }
  }
}
TOP

Related Classes of com.linkedin.databus2.core.container.netty.DatabusRequestExecutionHandler

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.