sqoop 抽取源码流程分析( 二 ) 导入工具代码结构分析

1.导入工具的起点importTool.java

抽取就是从这个地方开始的,重点是其中的run() 方法

 @Override

  /** {@inheritDoc} */

  public int run(SqoopOptions options) {

 .........

    codeGenerator.setManager(manager);



    try {

      if (options.doHiveImport()) {

        hiveImport = new HiveImport(options, manager, options.getConf(), false);

      }



      // Import a single table (or query) the user specified.

      importTable(options, options.getTableName(), hiveImport);

这个manager 的作用就是管理下面各种数据库的访问,比如你是要访问mysql 呢,还是oracle 呢。
这个代码重点是在manager 这个地方,这个是什么时候初始化的呢

protected ConnManager manager;

1.1 诞生之地

这个就是链接管理,那么这个东东的初始化在哪里呢?通过尾随其回家的路,终于嘿嘿。。。
public abstract class BaseSqoopTool extends com.cloudera.sqoop.tool.SqoopTool {
这就是manager 的老巢了。

进去看看

  */

  protected boolean init(SqoopOptions sqoopOpts) {

    // Get the connection to the database.

    try {

      JobData data = new JobData(sqoopOpts, this);

      this.manager = new ConnFactory(sqoopOpts.getConf()).getManager(data);

      return true;

    } catch (Exception e) {

      LOG.error("Got error creating database manager: "

          + StringUtils.stringifyException(e));

      if (System.getProperty(Sqoop.SQOOP_RETHROW_PROPERTY) != null) {

        throw new RuntimeException(e);

      }

    }



    return false;

  }

这就是他的出生之地了

  this.manager = new ConnFactory(sqoopOpts.getConf()).getManager(data);

1.2 工厂

public class ConnFactory {

在这个类里面,可以看到默认有两个工厂实现类
当然,也可以通过配置文件指定自定义的工厂实现类,相关代码也在这个类中可以找到

 public static final String[] DEFAULT_FACTORY_CLASS_NAMES_ARR =

      {OraOopManagerFactory.class.getName(),

      DefaultManagerFactory.class.getName(), };


    ......

    private List<ManagerFactory> factories; // 存储实例化的工厂对象

除了这两个默认的工厂,还可以利用配置文件来进行扩展,一般是在conf 目录下,利用manager.d 目录提供的配置文件来
控制你要提供的工厂,具体的请结合ConnFactory的代码来看

ConnFactory 的对外接口

 public ConnManager getManager(JobData data) throws IOException {

根据配置信息来构造出一个连接器供抽取使用。

下面分别对这两个默认工厂的实现进行介绍

1.2.1 缺省工厂DefaultManagerFactory

public class DefaultManagerFactory

    extends com.cloudera.sqoop.manager.ManagerFactory {
 .........

  public ConnManager accept(JobData data) {

    SqoopOptions options = data.getSqoopOptions();



    String scheme = extractScheme(options);

    if (null == scheme) {

      // We don't know if this is a mysql://, hsql://, etc.

      // Can't do anything with this.

      LOG.warn("Null scheme associated with connect string.");

      return null;

    }



    LOG.debug("Trying with scheme: " + scheme);



    if (scheme.equals("jdbc:mysql:")) {

      if (options.isDirect()) {

        return new DirectMySQLManager(options);

      } else {

        return new MySQLManager(options);

      }

    } else if (scheme.equals("jdbc:postgresql:")) {

      if (options.isDirect()) {

        return new DirectPostgresqlManager(options);

      } else {

        return new PostgresqlManager(options);

      }

    } else if (scheme.startsWith("jdbc:hsqldb:")) {

      return new HsqldbManager(options);

    } else if (scheme.startsWith("jdbc:oracle:")) {

      return new OracleManager(options);

    } else if (scheme.startsWith("jdbc:sqlserver:")) {

      return new SQLServerManager(options);

    } else if (scheme.startsWith("jdbc:jtds:sqlserver:")) {

      return new SQLServerManager(

        "net.sourceforge.jtds.jdbc.Driver",

        options);

    } else if (scheme.startsWith("jdbc:db2:")) {

      return new Db2Manager(options);

    } else if (scheme.startsWith("jdbc:netezza:")) {

      if (options.isDirect()) {

        return new DirectNetezzaManager(options);

      } else {

        return new NetezzaManager(options);

      }

    } else if (scheme.startsWith("jdbc:cubrid:")) {

      return new CubridManager(options);

    } else {

      return null;

    }

  }



protected String extractScheme(SqoopOptions options) {

.............. 
      }



    return connectStr.substring(0, schemeStopIdx);

  }

}

String scheme = extractScheme(options);
取得连接的参数,然后判断是属于那种类型的数据库链接,是mysql 还是oracle.
OracleManager.java 或 MySQLManager.java 等
然后制造出不同数据库的manager. 到这里,工厂的使命就完成了

1.2.2 ORA 工厂 OraOopManagerFactory

TBD

2. 再回 importTool

还是在run 方法里面


      importTable(options, options.getTableName(), hiveImport);

再看其实现里面有这么一段


  if (null != tableName) {

      manager.importTable(context);

    } else {

      manager.importQuery(context);

    }

这里的importTable 或者 importQuery 就是由工厂制造出来具体的类来实现了,比如OracleManager.java 或 MySQLManager.java

3. 进入抽取阶段

3.1 具体实现的继承关系


public abstract class SqlManager

    extends com.cloudera.sqoop.manager.ConnManager {


public abstract class SqlManager

    extends org.apache.sqoop.manager.SqlManager {



public class GenericJdbcManager

    extends com.cloudera.sqoop.manager.SqlManager {



public class GenericJdbcManager

    extends org.apache.sqoop.manager.GenericJdbcManager {

GenericJdbcManager下面有多种数据库进行的子类化


public abstract class CatalogQueryManager

    extends com.cloudera.sqoop.manager.GenericJdbcManager {

其他的如OracleManager , MySqlManager 应该去代码里面实现。

这是多少层继承关系啊
好了,那么importQuery() 的实现是在SqlManager 这个类里面

3.2 importQuery的实现

public void importQuery(com.cloudera.sqoop.manager.ImportJobContext context)

      throws IOException, ImportException {



 ImportJobBase importer;

......
      if (!opts.isBulkLoadEnabled()){

        importer = new HBaseImportJob(opts, context);

      } else {

        importer = new HBaseBulkImportJob(opts, context);

      }

    } else if (opts.getAccumuloTable() != null) {

      // Import to Accumulo.

    ......      

    importer = new AccumuloImportJob(opts, context);

    } else {

      // Import to HDFS.

      importer = new DataDrivenImportJob(opts, context.getInputFormat(),context);

    }


 importer.runImport(null, jarFile, splitCol, opts.getConf());

这里可以看出,导出主要是有三种存储类型,HBASE 、Accumulo 和 HDFS

那么hive 当然是算导入到hdfs 了,所以重点还是在 DataDrivenImportJob上面

4. 抽取到hdfs

4.1 继承关系


public class DataDrivenImportJob

    extends org.apache.sqoop.mapreduce.DataDrivenImportJob {

public class DataDrivenImportJob extends ImportJobBase {

public class ImportJobBase

    extends org.apache.sqoop.mapreduce.ImportJobBase {

public class ImportJobBase extends JobBase {

ImportJobBase 提供了 runImport 方法的实现

 public void runImport(String tableName, String ormJarFile, String splitByCol,

      Configuration conf) throws IOException, ImportException {

    ...................

    if (null != tableName) {

      LOG.info("Beginning import of " + tableName);

    } else {

      LOG.info("Beginning query import.");

    }

    ....................

 上传mapred 包
    loadJars(conf, ormJarFile, tableClassName);


创建mapred  job

    Job job = createJob(conf);

    try {

      // Set the external jar to use for the job.

      job.getConfiguration().set("mapred.jar", ormJarFile);

      if (options.getMapreduceJobName() != null) {

        job.setJobName(options.getMapreduceJobName());

      }



      propagateOptionsToJob(job);

    // 设置输入格式

      configureInputFormat(job, tableName, tableClassName, splitByCol);

    // 设置输出格式

      configureOutputFormat(job, tableName, tableClassName);

      configureMapper(job, tableName, tableClassName);

      configureNumTasks(job);

      cacheJars(job, getContext().getConnManager());



      jobSetup(job);

      setJob(job);

//    运行mapreduce job.
      boolean success = runJob(job);

      if (!success) {

        throw new ImportException("Import job failed!");

      }



      completeImport(job);

................
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值