Package com.linkedin.databus.bootstrap.utils

Source Code of com.linkedin.databus.bootstrap.utils.BootstrapSeederMain$Config

package com.linkedin.databus.bootstrap.utils;
/*
*
* 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.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.PropertyConfigurator;
import org.codehaus.jackson.map.ObjectMapper;

import com.linkedin.databus.bootstrap.common.BootstrapConfig;
import com.linkedin.databus.bootstrap.common.BootstrapReadOnlyConfig;
import com.linkedin.databus.core.util.ConfigBuilder;
import com.linkedin.databus.core.util.ConfigLoader;
import com.linkedin.databus.core.util.InvalidConfigException;
import com.linkedin.databus2.producers.db.OracleTriggerMonitoredSourceInfo;
import com.linkedin.databus2.relay.OracleEventProducerFactory;
import com.linkedin.databus2.relay.OracleJarUtils;
import com.linkedin.databus2.relay.config.LogicalSourceConfig;
import com.linkedin.databus2.relay.config.PhysicalSourceConfig;
import com.linkedin.databus2.relay.config.ReplicationBitSetterStaticConfig.SourceType;
import com.linkedin.databus2.schemas.FileSystemSchemaRegistryService;
import com.linkedin.databus2.schemas.SchemaRegistryConfigBuilder;
import com.linkedin.databus2.schemas.SchemaRegistryStaticConfig;


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

    public static final String HELP_OPT_LONG_NAME = "help";
  public static final String BOOTSTRAP_DB_PROPS_OPT_LONG_NAME = "bootstrap_db_props";
  public static final String PHYSICAL_CONFIG_OPT_LONG_NAME = "physical_config";
    public static final String LOG4J_PROPS_OPT_LONG_NAME = "log_props";
    public static final String VALIDATION_TYPE_OPT_LONG_NAME="validation-type";
    public static final String VALIDATION_SAMPLE_PCT_LONG_NAME="validation-sample-pct";
    public static final char   HELP_OPT_CHAR = 'h';
  public static final char   BOOTSTRAP_DB_PROP_OPT_CHAR = 'p';
  public static final char   PHYSICAL_CONFIG_OPT_CHAR = 'c';
  public static final char LOG4J_PROPS_OPT_CHAR = 'l';
  public static final char VALIDATION_TYPE_OPT_CHAR='v';
public static final char VALIDATION_SAMPLE_PCT_CHAR='s';


  private static Properties  _sBootstrapConfigProps = null;
  private static String      _sSourcesConfigFile    = null;
  private static DataSource  _sDataStore      = null;
  private static StaticConfig _sStaticConfig        = null;
  private static List<OracleTriggerMonitoredSourceInfo> _sources = null;
  private static BootstrapDBSeeder _sSeeder         = null;
  private static BootstrapSrcDBEventReader _sReader = null;
  private static BootstrapSeederWriterThread _sWriterThread = null;
  private static BootstrapEventBuffer  _sBootstrapBuffer = null;

  private static String _validationType = "normal";
  private static double _validationSamplePct = 100.0;

    public static BootstrapDBSeeder getSeeder()
    {
      return _sSeeder;
    }

    public static String getValidationType ()
    {
      return _validationType;
    }

    public static double getValidationSamplePct ()
    {
      return _validationSamplePct;
    }

    public static BootstrapSrcDBEventReader getReader()
    {
      return _sReader;
    }

    public static Properties getBootstrapConfigProps()
    {
      return _sBootstrapConfigProps;
    }

    public static String getSourcesConfigFile()
    {
      return _sSourcesConfigFile;
    }

    public static DataSource getDataStore()
    {
      return _sDataStore;
    }

    public static StaticConfig getStaticConfig()
    {
      return _sStaticConfig;
    }

    public static List<OracleTriggerMonitoredSourceInfo> getSources()
    {
      return _sources;
    }

  /**
   * @param args
   */
  public static void main(String[] args)
    throws Exception
  {
      init(args);
      _sSeeder.startSeeding();
      //_sReader.readEventsFromAllSources(0);
      _sReader.start();
      _sWriterThread.start();
  }

  public static void init(String[] args)
    throws Exception
  {
    parseArgs(args);

      // Load the source configuration JSON file
      //File sourcesJson = new File("integration-test/config/sources-member2.json");
      File sourcesJson = new File(_sSourcesConfigFile);

      ObjectMapper mapper = new ObjectMapper();
      PhysicalSourceConfig physicalSourceConfig = mapper.readValue(sourcesJson, PhysicalSourceConfig.class);
      physicalSourceConfig.checkForNulls();

      Config config = new Config();

      ConfigLoader<StaticConfig> configLoader =
                new ConfigLoader<StaticConfig>("databus.seed.", config);
      _sStaticConfig = configLoader.loadConfig(_sBootstrapConfigProps);

      // Make sure the URI from the configuration file identifies an Oracle JDBC source.
      String uri = physicalSourceConfig.getUri();
      if(!uri.startsWith("jdbc:oracle"))
      {
        throw new InvalidConfigException("Invalid source URI (" +
            physicalSourceConfig.getUri() + "). Only jdbc:oracle: URIs are supported.");
      }

      String sourceTypeStr = physicalSourceConfig.getReplBitSetter().getSourceType();
        if (SourceType.TOKEN.toString().equalsIgnoreCase(sourceTypeStr))
          throw new InvalidConfigException("Token Source-type for Replication bit setter config cannot be set for trigger-based Databus relay !!");

      // Create the OracleDataSource used to get DB connection(s)
      try
      {
        Class oracleDataSourceClass = OracleJarUtils.loadClass("oracle.jdbc.pool.OracleDataSource");
        Object ods = oracleDataSourceClass.newInstance();
        Method setURLMethod = oracleDataSourceClass.getMethod("setURL", String.class);
        setURLMethod.invoke(ods, uri);
        _sDataStore = (DataSource) ods;
      } catch (Exception e)
      {
        String errMsg = "Error creating a data source object ";
        LOG.error(errMsg, e);
        throw e;
      }

      //TODO: Need a better way than relaying on RelayFactory for generating MonitoredSourceInfo
      OracleEventProducerFactory factory = new BootstrapSeederOracleEventProducerFactory(_sStaticConfig.getController().getPKeyNameMap());

      // Parse each one of the logical sources
      _sources = new ArrayList<OracleTriggerMonitoredSourceInfo>();
      FileSystemSchemaRegistryService schemaRegistryService =
            FileSystemSchemaRegistryService.build(_sStaticConfig.getSchemaRegistry().getFileSystem());

      Set<String> seenUris = new HashSet<String>();
      for(LogicalSourceConfig sourceConfig : physicalSourceConfig.getSources())
      {
        String srcUri  = sourceConfig.getUri();
        if ( seenUris.contains(srcUri))
        {
          String msg = "Uri (" + srcUri + ") is used for more than one sources. Currently Bootstrap Seeder cannot support seeding sources with the same URI together. Please have them run seperately !!";
          LOG.fatal(msg);
          throw new InvalidConfigException(msg);
        }
        seenUris.add(srcUri);
        OracleTriggerMonitoredSourceInfo source =
            factory.buildOracleMonitoredSourceInfo(sourceConfig.build(), physicalSourceConfig.build(), schemaRegistryService);
        _sources.add(source);
      }
      _sSeeder = new BootstrapDBSeeder(_sStaticConfig.getBootstrap(),_sources);

      _sBootstrapBuffer = new BootstrapEventBuffer(_sStaticConfig.getController().getCommitInterval() * 2);

      _sWriterThread = new BootstrapSeederWriterThread(_sBootstrapBuffer, _sSeeder);

      _sReader = new BootstrapSrcDBEventReader(_sDataStore,_sBootstrapBuffer,
                                               _sStaticConfig.getController(),
                                               _sources,
                                               _sSeeder.getLastRows(),
                                               _sSeeder.getLastKeys(),
                                               0);
  }

  @SuppressWarnings("static-access")
  public static void parseArgs(String[] args) throws IOException
  {
    CommandLineParser cliParser = new GnuParser();


        Option helpOption = OptionBuilder.withLongOpt(HELP_OPT_LONG_NAME)
                                       .withDescription("Help screen")
                                       .create(HELP_OPT_CHAR);

      Option sourcesOption = OptionBuilder.withLongOpt(PHYSICAL_CONFIG_OPT_LONG_NAME)
                                     .withDescription("Bootstrap producer properties to use")
                                     .hasArg()
                                     .withArgName("property_file")
                                     .create(PHYSICAL_CONFIG_OPT_CHAR);

      Option dbOption = OptionBuilder.withLongOpt(BOOTSTRAP_DB_PROPS_OPT_LONG_NAME)
                      .withDescription("Bootstrap producer properties to use")
                      .hasArg()
                      .withArgName("property_file")
                      .create(BOOTSTRAP_DB_PROP_OPT_CHAR);

      Option log4jPropsOption = OptionBuilder.withLongOpt(LOG4J_PROPS_OPT_LONG_NAME)
                        .withDescription("Log4j properties to use")
                        .hasArg()
                        .withArgName("property_file")
                        .create(LOG4J_PROPS_OPT_CHAR);

      Option validationType = OptionBuilder.withLongOpt(VALIDATION_TYPE_OPT_LONG_NAME)
                  .withDescription("Type of validation algorithm , normal[cmp two sorted streams of oracle and bootstrap db]  or point[entry in bootstrap checked in oracle]")
                  .hasArg()
                  .withArgName("validation_type")
                  .create(VALIDATION_TYPE_OPT_CHAR);

      Option validationSamplePct = OptionBuilder.withLongOpt(VALIDATION_SAMPLE_PCT_LONG_NAME)
          .withDescription("Validation sample pct ,0.0 to 100.00 [100.0]")
          .hasArg()
          .withArgName("validation_sample_pct")
          .create(VALIDATION_SAMPLE_PCT_CHAR);

      Options options = new Options();
      options.addOption(helpOption);
      options.addOption(sourcesOption);
      options.addOption(dbOption);
      options.addOption(log4jPropsOption);
      options.addOption(validationType);
      options.addOption(validationSamplePct);


      CommandLine cmd = null;
      try
      {
        cmd = cliParser.parse(options, args);
      }
      catch (ParseException pe)
      {
        LOG.fatal("Bootstrap Physical Config: failed to parse command-line options.", pe);
        throw new RuntimeException("Bootstrap Physical Config: failed to parse command-line options.", pe);
      }

      if (cmd.hasOption(LOG4J_PROPS_OPT_CHAR))
      {
        String log4jPropFile = cmd.getOptionValue(LOG4J_PROPS_OPT_CHAR);
        PropertyConfigurator.configure(log4jPropFile);
        LOG.info("Using custom logging settings from file " + log4jPropFile);
      }
      else
      {
        PatternLayout defaultLayout = new PatternLayout("%d{ISO8601} +%r [%t] (%p) {%c} %m%n");
        ConsoleAppender defaultAppender = new ConsoleAppender(defaultLayout);

        Logger.getRootLogger().removeAllAppenders();
        Logger.getRootLogger().addAppender(defaultAppender);
        Logger.getRootLogger().setLevel(Level.INFO)//using info as the default log level
        LOG.info("Using default logging settings. Log Level is :" + Logger.getRootLogger().getLevel());
      }

      if (cmd.hasOption(HELP_OPT_CHAR))
      {
        printCliHelp(options);
        System.exit(0);
      }

      if (! cmd.hasOption(PHYSICAL_CONFIG_OPT_CHAR))
        throw new RuntimeException("Sources Config is not provided; use --help for usage");

      if (!cmd.hasOption(BOOTSTRAP_DB_PROP_OPT_CHAR) )
        throw new RuntimeException("Bootstrap config is not provided; use --help for usage");

      _sSourcesConfigFile = cmd.getOptionValue(PHYSICAL_CONFIG_OPT_CHAR);

      String propFile = cmd.getOptionValue(BOOTSTRAP_DB_PROP_OPT_CHAR);
      LOG.info("Loading bootstrap DB config from properties file " + propFile);

      _sBootstrapConfigProps = new Properties();
      _sBootstrapConfigProps.load(new FileInputStream(propFile));
      if (!cmd.hasOption(VALIDATION_TYPE_OPT_CHAR))
      {
        _validationType = "normal";
      }
      else
      {
        String vtype = cmd.getOptionValue(VALIDATION_TYPE_OPT_CHAR);
        if (vtype.equals("point") || vtype.equals("normal") || vtype.equals("pointBs"))
        {
          _validationType = vtype;
        }
        else
        {
          throw new RuntimeException("Validation type has to be one of 'normal' or 'point' or 'pointBs'");
        }
      }
      if (cmd.hasOption(VALIDATION_SAMPLE_PCT_CHAR))
      {
         try
         {
           _validationSamplePct = Double.parseDouble(cmd.getOptionValue(VALIDATION_SAMPLE_PCT_CHAR));
           if (_validationSamplePct < 0.0 || _validationSamplePct > 100.0)
           {
             throw new RuntimeException("Error in specifying: " + VALIDATION_SAMPLE_PCT_LONG_NAME +
                 "Should be between 0.0 and 100.0. It was " + _validationSamplePct);
           }
         }
         catch (NumberFormatException e)
         {
           throw new RuntimeException("Error in specifying: " + VALIDATION_SAMPLE_PCT_LONG_NAME +  " Exception:" + e);
         }
      }
      else
      {
        _validationSamplePct = 100.0;
      }

  }

    private static void printCliHelp(Options cliOptions)
    {
      HelpFormatter helpFormatter = new HelpFormatter();
      helpFormatter.printHelp("java " + BootstrapSeederMain.class.getName(), cliOptions);
    }

  public static class StaticConfig
  {
    public SchemaRegistryStaticConfig getSchemaRegistry()
    {
      return _schemaRegistry;
    }

    public BootstrapReadOnlyConfig getBootstrap()
    {
      return _bootstrap;
    }

    public BootstrapSrcDBEventReader.StaticConfig getController()
    {
      return _controller;
    }

    public StaticConfig(BootstrapSrcDBEventReader.StaticConfig controller,
        SchemaRegistryStaticConfig schemaRegistry,
        BootstrapReadOnlyConfig bootstrap,
        Map<String,String> checkpointPersistanceScript)
    {
      super();
      _controller = controller;
      _schemaRegistry = schemaRegistry;
      _bootstrap = bootstrap;
    }

    private final BootstrapSrcDBEventReader.StaticConfig _controller;
    private final SchemaRegistryStaticConfig _schemaRegistry;
    private final BootstrapReadOnlyConfig   _bootstrap;
   }

  public static class Config implements ConfigBuilder<StaticConfig>
  {
    public Config()
    {
      _controller = new BootstrapSrcDBEventReader.Config();
      _checkpointPersistanceScript = new HashMap<String, String>();

      try
      {
        _bootstrap = new BootstrapConfig();
      } catch (IOException io) {
        LOG.error("Got exception while instantiating BootstrapConfig !!",io);
        throw new RuntimeException("Got exception while instantiating BootstrapConfig !!",io);
      }

      _schemaRegistry = new SchemaRegistryConfigBuilder();
    }

    @Override
        public StaticConfig build() throws InvalidConfigException
    {
      return new StaticConfig(_controller.build(),
                          _schemaRegistry.build(), _bootstrap.build(), _checkpointPersistanceScript);
    }


    public SchemaRegistryConfigBuilder getSchemaRegistry()
    {
      return _schemaRegistry;
    }

    public BootstrapConfig getBootstrap()
    {
      return _bootstrap;
    }

    public BootstrapSrcDBEventReader.Config getController()
    {
      return _controller;
    }


    public void setSchemaRegistry(SchemaRegistryConfigBuilder schemaRegistry)
    {
      this._schemaRegistry = schemaRegistry;
    }

    public void setBootstrap(BootstrapConfig bootstrap)
    {
      this._bootstrap = bootstrap;
    }

    public void setController(BootstrapSrcDBEventReader.Config controller)
    {
      this._controller = controller;
    }

    public void setCheckpointPersistanceScript(String source, String script)
    {
      _checkpointPersistanceScript.put(source,script);
    }

    public String getCheckpointPersistanceScript(String source)
    {
      String script = _checkpointPersistanceScript.get(source);

      if ( null == script )
      {
        _checkpointPersistanceScript.put(source,DEFAULT_SCRIPT);
        return DEFAULT_SCRIPT;
      }
      return script;
    }

    private  BootstrapSrcDBEventReader.Config _controller;
    private  SchemaRegistryConfigBuilder _schemaRegistry;
    private  BootstrapConfig   _bootstrap;
    private final  Map<String,String>  _checkpointPersistanceScript;

    private static final String DEFAULT_SCRIPT = "";
  }
}
TOP

Related Classes of com.linkedin.databus.bootstrap.utils.BootstrapSeederMain$Config

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.