Package com.linkedin.databus.container.request

Source Code of com.linkedin.databus.container.request.RegisterRequestProcessor

package com.linkedin.databus.container.request;
/*
*
* 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.IOException;
import java.io.StringWriter;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import com.linkedin.databus.container.netty.HttpRelay;
import com.linkedin.databus.core.data_model.LogicalSource;
import com.linkedin.databus2.core.DatabusException;
import com.linkedin.databus2.core.container.ChunkedWritableByteChannel;
import com.linkedin.databus2.core.container.DatabusHttpHeaders;
import com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector;
import com.linkedin.databus2.core.container.request.DatabusRequest;
import com.linkedin.databus2.core.container.request.InvalidRequestParamValueException;
import com.linkedin.databus2.core.container.request.RegisterResponseEntry;
import com.linkedin.databus2.core.container.request.RegisterResponseMetadataEntry;
import com.linkedin.databus2.core.container.request.RequestProcessingException;
import com.linkedin.databus2.core.container.request.RequestProcessor;
import com.linkedin.databus2.schemas.SchemaId;
import com.linkedin.databus2.schemas.SchemaRegistryService;
import com.linkedin.databus2.schemas.VersionedSchema;
import com.linkedin.databus2.schemas.VersionedSchemaSet;


public class RegisterRequestProcessor implements RequestProcessor
{
  public static final String MODULE = RegisterRequestProcessor.class.getName();
  public static final Logger LOG = Logger.getLogger(MODULE);
  public final static String COMMAND_NAME = "register";
  public final static String SOURCES_PARAM = "sources";

  private final ExecutorService _executorService;
  private final HttpRelay _relay;

  public RegisterRequestProcessor(ExecutorService executorService, HttpRelay relay)
  {
    super();
    _executorService = executorService;
    _relay = relay;
  }

  @Override
  public ExecutorService getExecutorService()
  {
    return _executorService;
  }

  @Override
  public DatabusRequest process(DatabusRequest request) throws IOException,
                                                               RequestProcessingException
  {
    try
    {
      // fail early if optional version param is included but isn't valid
      int registerRequestProtocolVersion = 3// 2 and 3 are same for us; 4 is a superset only newer clients understand
      String registerRequestProtocolVersionStr =
          request.getParams().getProperty(DatabusHttpHeaders.PROTOCOL_VERSION_PARAM);
      if (registerRequestProtocolVersionStr != null)
      {
        try
        {
          registerRequestProtocolVersion = Integer.parseInt(registerRequestProtocolVersionStr);
        }
        catch (NumberFormatException e)
        {
          LOG.error("Could not parse /register request protocol version: " + registerRequestProtocolVersionStr);
          throw new InvalidRequestParamValueException(COMMAND_NAME, DatabusHttpHeaders.PROTOCOL_VERSION_PARAM,
                                                      registerRequestProtocolVersionStr);
        }
        if (registerRequestProtocolVersion < 2 || registerRequestProtocolVersion > 4)
        {
          LOG.error("Out-of-range /register request protocol version: " + registerRequestProtocolVersionStr);
          throw new InvalidRequestParamValueException(COMMAND_NAME, DatabusHttpHeaders.PROTOCOL_VERSION_PARAM,
                                                      registerRequestProtocolVersionStr);
        }
      }

      Collection<LogicalSource> logicalSources = null;
      HttpStatisticsCollector relayStatsCollector = _relay.getHttpStatisticsCollector();

      String sources = request.getParams().getProperty(SOURCES_PARAM);
      if (null == sources)
      {
        // need to return all schemas, so first get all sources
        logicalSources = _relay.getSourcesIdNameRegistry().getAllSources();
      }
      else
      {
        String[] sourceIds = sources.split(",");
        logicalSources = new ArrayList<LogicalSource>(sourceIds.length);

        for (String sourceId: sourceIds)
        {
          int srcId;
          String trimmedSourceId = sourceId.trim();
          try
          {
            srcId = Integer.valueOf(trimmedSourceId);
            LogicalSource lsource = _relay.getSourcesIdNameRegistry().getSource(srcId);
            if (null != lsource) logicalSources.add(lsource);
            else
            {
              LOG.error("No source name for source id: " + srcId);
              throw new InvalidRequestParamValueException(COMMAND_NAME, SOURCES_PARAM, sourceId);
            }
          }
          catch (NumberFormatException nfe)
          {
            if (relayStatsCollector != null)
            {
              relayStatsCollector.registerInvalidRegisterCall();
            }
            throw new InvalidRequestParamValueException(COMMAND_NAME, SOURCES_PARAM, sourceId);
          }
        }
      }

      SchemaRegistryService schemaRegistry = _relay.getSchemaRegistryService();
      ArrayList<RegisterResponseEntry> registeredSources = new ArrayList<RegisterResponseEntry>(20);

      for (LogicalSource lsource: logicalSources)
      {
        getSchemas(schemaRegistry, lsource.getName(), lsource.getId(), sources, registeredSources);
      }

      // Note that, as of April 2013, the Espresso sandbox's schema registry
      // (in JSON format) is 4.5 MB and growing.  But 100 KB is probably OK
      // for regular production cases.
      StringWriter out = new StringWriter(102400);
      ObjectMapper mapper = new ObjectMapper();

      // any circumstances under which we might want to override this?
      int registerResponseProtocolVersion = registerRequestProtocolVersion;

      if (registerRequestProtocolVersion == 4// DDSDBUS-2009
      {
        LOG.debug("Got version 4 /register request; fetching metadata schema.");
        // Get (replication) metadata schema from registry; format it as list
        // of schemas (multiple only if more than one version exists).  Per
        // https://iwww.corp.linkedin.com/wiki/cf/display/ENGS/Espresso+Metadata+Schema,
        // name of replication metadata is simply "metadata".
        ArrayList<RegisterResponseMetadataEntry> registeredMetadata = new ArrayList<RegisterResponseMetadataEntry>(2);
        getMetadataSchemas(schemaRegistry, registeredMetadata);

        // Set up the v4 response as a map:  one entry is the existing list of source
        // schemas, and the others (if present) are the new lists of metadata schema(s)
        // and (TODO) key schemas.
        HashMap<String, List<Object>> responseMap = new HashMap<String, List<Object>>(4);
        responseMap.put(RegisterResponseEntry.SOURCE_SCHEMAS_KEY, (List<Object>)(List<?>)registeredSources);
        if (registeredMetadata.size() > 0)
        {
          LOG.debug("Sending v4 /register response with metadata schema.");
          responseMap.put(RegisterResponseMetadataEntry.METADATA_SCHEMAS_KEY,
                          (List<Object>)(List<?>)registeredMetadata);
        }
        else
        {
          LOG.debug("No metadata schema available; sending v4 /register response without.");
        }
        // TODO:  figure out how to retrieve key schemas and include via RegisterResponseEntry.KEY_SCHEMAS_KEY
        mapper.writeValue(out, responseMap);
      }
      else // fall back to old style (v2/v3 response)
      {
        mapper.writeValue(out, registeredSources);
      }

      ChunkedWritableByteChannel responseContent = request.getResponseContent();
      byte[] resultBytes = out.toString().getBytes(Charset.defaultCharset());
      responseContent.addMetadata(DatabusHttpHeaders.DBUS_CLIENT_RELAY_PROTOCOL_VERSION_HDR,
                                  registerResponseProtocolVersion);
      responseContent.write(ByteBuffer.wrap(resultBytes));

      if (null != relayStatsCollector)
      {
        HttpStatisticsCollector connStatsCollector = (HttpStatisticsCollector)
        request.getParams().get(relayStatsCollector.getName());
        if (null != connStatsCollector)
        {
          connStatsCollector.registerRegisterCall(registeredSources);
        }
        else
        {
          relayStatsCollector.registerRegisterCall(registeredSources);
        }
      }

      return request;
    }
    catch (InvalidRequestParamValueException e)
    {
      HttpStatisticsCollector relayStatsCollector = _relay.getHttpStatisticsCollector();
      if (null != relayStatsCollector)
        relayStatsCollector.registerInvalidRegisterCall();
      throw e;
    }
  }

  /**
   * Returns list of versioned source (or key?) schemas for the given source name and associates
   * them with the specified ID.
   * TODO:  either add support for key schemas or rename method to getSourceSchemas()
   */
  private void getSchemas(SchemaRegistryService schemaRegistry,                // IN
                          String name,                                         // IN:  source name
                          Integer sourceId,                                    // IN
                          String sources,                                      // IN (for error-logging only)
                          ArrayList<RegisterResponseEntry> registeredSources// OUT
  throws RequestProcessingException
  {
    Map<Short, String> versionedSchemas = null;
    try
    {
      versionedSchemas = schemaRegistry.fetchAllSchemaVersionsBySourceName(name);
    }
    catch (DatabusException ie)
    {
      HttpStatisticsCollector relayStatsCollector = _relay.getHttpStatisticsCollector();
      if (relayStatsCollector != null) relayStatsCollector.registerInvalidRegisterCall();
      throw new RequestProcessingException(ie);
    }

    if ((null == versionedSchemas) || (versionedSchemas.isEmpty()))
    {
      HttpStatisticsCollector relayStatsCollector = _relay.getHttpStatisticsCollector();
      if (relayStatsCollector != null) relayStatsCollector.registerInvalidRegisterCall();
      LOG.error("Problem fetching schema for sourceId " + sourceId + "; sources string = " + sources);
    }
    else
    {
      for (Entry<Short, String> e : versionedSchemas.entrySet())
      {
        registeredSources.add(new RegisterResponseEntry(sourceId.longValue(), e.getKey(), e.getValue()));
      }
    }
  }

  /**
   * Returns list of versioned metadata schemas.
   * TODO (DDSDBUS-2093):  implement this.
   */
  private void getMetadataSchemas(SchemaRegistryService schemaRegistry,                         // IN
                                  ArrayList<RegisterResponseMetadataEntry> registeredMetadata// OUT
  throws RequestProcessingException
  {
    Map<SchemaId, VersionedSchema> versionedSchemas = null;
    try
    {
      VersionedSchemaSet schemaSet = schemaRegistry.fetchAllMetadataSchemaVersions();
      if (schemaSet != null)
      {
        versionedSchemas = schemaSet.getAllVersionsWithSchemaId(SchemaRegistryService.DEFAULT_METADATA_SCHEMA_SOURCE);
      }
    }
    catch (DatabusException ie)
    {
      HttpStatisticsCollector relayStatsCollector = _relay.getHttpStatisticsCollector();
      if (relayStatsCollector != null) relayStatsCollector.registerInvalidRegisterCall();
      throw new RequestProcessingException(ie);
    }

    if (versionedSchemas != null && !versionedSchemas.isEmpty())
    {
      for (SchemaId id:  versionedSchemas.keySet())
      {
        VersionedSchema entry = versionedSchemas.get(id);
        if (entry.getOrigSchemaStr() == null)
        {
          throw new RequestProcessingException("Null schema string for metadata version " + entry.getVersion());
        }
        registeredMetadata.add(new RegisterResponseMetadataEntry((short)entry.getVersion(),
                                                                 entry.getOrigSchemaStr(),
                                                                 id.getByteArray()));
      }
    }
  }
}
TOP

Related Classes of com.linkedin.databus.container.request.RegisterRequestProcessor

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.