Package com.linkedin.databus.client.netty

Source Code of com.linkedin.databus.client.netty.RemoteExceptionHandler

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.ByteArrayInputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.sql.SQLException;

import org.apache.log4j.Logger;

import com.linkedin.databus.client.ChunkedBodyReadableByteChannel;
import com.linkedin.databus.client.DatabusSourcesConnection;
import com.linkedin.databus.core.DbusErrorEvent;
import com.linkedin.databus.core.DbusEventBuffer;
import com.linkedin.databus.core.DbusEventFactory;
import com.linkedin.databus.core.DbusEventInternalReadable;
import com.linkedin.databus.core.DbusEventInternalWritable;
import com.linkedin.databus.core.DbusPrettyLogUtils;
import com.linkedin.databus.core.InvalidEventException;
import com.linkedin.databus.core.PullerRetriesExhaustedException;
import com.linkedin.databus.core.ScnNotFoundException;
import com.linkedin.databus2.core.container.DatabusHttpHeaders;
import com.linkedin.databus2.core.container.request.BootstrapDBException;
import com.linkedin.databus2.core.container.request.BootstrapDatabaseTooOldException;
import com.linkedin.databus2.core.container.request.BootstrapDatabaseTooYoungException;


public class RemoteExceptionHandler
{
  public static final String MODULE = RemoteExceptionHandler.class.getName();
  public static final Logger LOG = Logger.getLogger(MODULE);

  private final DatabusSourcesConnection _sourcesConn;
  private final DbusEventBuffer _dbusEventBuffer;
  private final DbusEventFactory _eventFactory;

  public RemoteExceptionHandler(DatabusSourcesConnection sourcesConn,
                                DbusEventBuffer dataEventsBuffer,
                                DbusEventFactory eventFactory)
  {
    _sourcesConn = sourcesConn;
    _dbusEventBuffer = dataEventsBuffer;
    _eventFactory = eventFactory;
  }

  public int getPendingEventSize(ChunkedBodyReadableByteChannel readChannel)
  {
    String result = readChannel.getMetadata(DatabusHttpHeaders.DATABUS_PENDING_EVENT_SIZE);
    if (result == null)
    {
      // There was no such header.
      return 0;
    }
    try
    {
      return Integer.parseInt(result);
    }
    catch(NumberFormatException e)
    {
      LOG.error("Could not parse pending event size:" + result);
      return 0;
    }
  }

  public static String getExceptionName(ChunkedBodyReadableByteChannel readChannel)
  {
    String result = readChannel.getMetadata(DatabusHttpHeaders.DATABUS_ERROR_CAUSE_CLASS_HEADER);
    if (result==null)
    {
      result = readChannel.getMetadata(DatabusHttpHeaders.DATABUS_ERROR_CLASS_HEADER);
    }
    return result;
  }

  public static String getExceptionMessage(ChunkedBodyReadableByteChannel readChannel)
  {
    String exceptionName = getExceptionName(readChannel);
    if (null == exceptionName) return null;

    StringBuilder result = new StringBuilder(exceptionName.length() + 100);
    result.append("Remote exception");
    String reqId = readChannel.getMetadata(DatabusHttpHeaders.DATABUS_REQUEST_ID_HEADER);
    if (null != reqId) result.append(" for request id");
    result.append(":");
    result.append(exceptionName);

    return result.toString();
  }

  public Throwable getException(ChunkedBodyReadableByteChannel readChannel)
  {
    Throwable remoteException = null;
    String err = getExceptionName(readChannel);
    if (null != err)
    { // in theory, we shall be reading the actual exception from the read channel.
      if (err.equalsIgnoreCase(ScnNotFoundException.class.getName()))
      {
        remoteException = new ScnNotFoundException();
      }
      else if (err.equalsIgnoreCase(BootstrapDatabaseTooOldException.class.getName()))
      {
        remoteException = new BootstrapDatabaseTooOldException();
      }
      else if (err.equalsIgnoreCase( PullerRetriesExhaustedException.class.getName()))
      {
        remoteException = new PullerRetriesExhaustedException();
      }
      else if (err.equalsIgnoreCase(BootstrapDatabaseTooYoungException.class.getName()))
      {
        remoteException = new BootstrapDatabaseTooYoungException();
      }
      else if (err.equalsIgnoreCase(BootstrapDBException.class.getName()))
      {
        remoteException = new BootstrapDBException();
      }
      else if (err.equalsIgnoreCase(SQLException.class.getName()))
      {
        remoteException = new SQLException();
      }
      else
      {
        LOG.error("Unexpected remote error received: " + err);
      }
      LOG.info("Remote exception received: " + remoteException);
    }

    return remoteException;
  }

  public void handleException(Throwable remoteException)
    throws InvalidEventException, InterruptedException
  {
    if ((remoteException instanceof BootstrapDatabaseTooOldException) || (remoteException instanceof PullerRetriesExhaustedException))
    {
      suspendConnectionOnError(remoteException);
    }
    else
    {
      LOG.error("Unexpected exception received: " + remoteException);
    }
  }

  private void suspendConnectionOnError(Throwable exception)
    throws InvalidEventException, InterruptedException
  {
    // suspend pull threads
    _sourcesConn.getConnectionStatus().suspendOnError(exception);

    // send an error event to dispatcher through dbusEventBuffer

    DbusEventInternalReadable errorEvent = null;
    if (exception instanceof BootstrapDatabaseTooOldException)
    {
      errorEvent = _eventFactory.createErrorEvent(
          new DbusErrorEvent(exception, DbusEventInternalWritable.BOOTSTRAPTOOOLD_ERROR_SRCID));
    }
    else if (exception instanceof PullerRetriesExhaustedException)
    {
      errorEvent = _eventFactory.createErrorEvent(
          new DbusErrorEvent(exception, DbusEventInternalWritable.PULLER_RETRIES_EXPIRED));
    }
    else
    {
      throw new InvalidEventException("Got an unrecognizable exception ");
    }
    byte[] errorEventBytes = new byte[errorEvent.getRawBytes().limit()];

    if (LOG.isDebugEnabled())
    {
      LOG.debug("error event size: " + errorEventBytes.length);
      LOG.debug("error event:" + errorEvent.toString());
    }

    errorEvent.getRawBytes().get(errorEventBytes);
    ByteArrayInputStream errIs = new ByteArrayInputStream(errorEventBytes);
    ReadableByteChannel errRbc = Channels.newChannel(errIs);

    boolean success = false;
    int retryCounter = 0;
    while (!success && retryCounter < 10)
    {
      String errMsg = "Sending an internal system event to dispatcher. Retry count = " + retryCounter;
      DbusPrettyLogUtils.logExceptionAtInfo(errMsg, exception, LOG);
      success = _dbusEventBuffer.readEvents(errRbc) > 0 ? true : false;
      if (!success)
      {
        LOG.warn("Unable to send an internal system event to dispatcher. Will retry later " + retryCounter);
        retryCounter ++;
        Thread.sleep(1000);
      }
    }
  }
}
TOP

Related Classes of com.linkedin.databus.client.netty.RemoteExceptionHandler

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.