diff --git a/client-adapter/kudu/pom.xml b/client-adapter/kudu/pom.xml
new file mode 100644
index 00000000..10c87858
--- /dev/null
+++ b/client-adapter/kudu/pom.xml
@@ -0,0 +1,87 @@
+
+
+
+ canal.client-adapter
+ com.alibaba.otter
+ 1.1.5-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+ com.alibaba.otter
+ client-adapter.kudu
+ jar
+ canal client adapter kudu module for otter ${project.version}
+
+
+ com.alibaba.otter
+ client-adapter.common
+ ${project.version}
+ provided
+
+
+ org.apache.kudu
+ kudu-client
+ 1.6.0
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ mysql
+ mysql-connector-java
+ 5.1.47
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.4
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ maven-antrun-plugin
+
+
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/KuduAdapter.java b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/KuduAdapter.java
new file mode 100644
index 00000000..95413683
--- /dev/null
+++ b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/KuduAdapter.java
@@ -0,0 +1,204 @@
+package com.alibaba.otter.canal.client.adapter.kudu;
+
+import com.alibaba.otter.canal.client.adapter.OuterAdapter;
+import com.alibaba.otter.canal.client.adapter.kudu.config.KuduMappingConfig;
+import com.alibaba.otter.canal.client.adapter.kudu.config.KuduMappingConfigLoader;
+import com.alibaba.otter.canal.client.adapter.kudu.monitor.KuduConfigMonitor;
+import com.alibaba.otter.canal.client.adapter.kudu.service.KuduEtlService;
+import com.alibaba.otter.canal.client.adapter.kudu.service.KuduSyncService;
+import com.alibaba.otter.canal.client.adapter.kudu.support.KuduTemplate;
+import com.alibaba.otter.canal.client.adapter.support.Dml;
+import com.alibaba.otter.canal.client.adapter.support.EtlResult;
+import com.alibaba.otter.canal.client.adapter.support.OuterAdapterConfig;
+import com.alibaba.otter.canal.client.adapter.support.SPI;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author liuyadong
+ * @description kudu适配器主类
+ */
+@SPI("kudu")
+public class KuduAdapter implements OuterAdapter {
+ private static Logger logger = LoggerFactory.getLogger(KuduAdapter.class);
+
+ private Map kuduMapping = new ConcurrentHashMap<>(); // 文件名对应配置
+ private Map> mappingConfigCache = new ConcurrentHashMap<>(); // 库名-表名对应配置
+
+ private String dataSourceKey;
+
+ private KuduTemplate kuduTemplate;
+
+ private KuduSyncService kuduSyncService;
+
+ private KuduConfigMonitor kuduConfigMonitor;
+
+ private Properties envProperties;
+
+ public Map getKuduMapping() {
+ return kuduMapping;
+ }
+
+ public Map> getMappingConfigCache() {
+ return mappingConfigCache;
+ }
+
+
+ @Override
+ public void init(OuterAdapterConfig configuration, Properties envProperties) {
+ this.envProperties = envProperties;
+ Map kuduMappingTmp = KuduMappingConfigLoader.load(envProperties);
+ // 过滤不匹配的key的配置,获取连接key,key为配置文件名称
+ kuduMappingTmp.forEach((key, mappingConfig) -> {
+ if ((mappingConfig.getOuterAdapterKey() == null && configuration.getKey() == null)
+ || (mappingConfig.getOuterAdapterKey() != null && mappingConfig.getOuterAdapterKey()
+ .equalsIgnoreCase(configuration.getKey()))) {
+ kuduMapping.put(key, mappingConfig);
+ dataSourceKey = mappingConfig.getDataSourceKey();
+ }
+ });
+ //判断目标字段是否为空
+ if (kuduMapping.isEmpty()) {
+ throw new RuntimeException("No kudu adapter found for config key: " + configuration.getKey());
+ }
+ for (Map.Entry entry : kuduMapping.entrySet()) {
+ String configName = entry.getKey();
+ KuduMappingConfig mappingConfig = entry.getValue();
+ String k;
+ if (envProperties != null && !"tcp".equalsIgnoreCase(envProperties.getProperty("canal.conf.mode"))) {
+ k = StringUtils.trimToEmpty(mappingConfig.getDestination()) + "-"
+ + StringUtils.trimToEmpty(mappingConfig.getGroupId()) + "_"
+ + mappingConfig.getKuduMapping().getDatabase() + "-"
+ + mappingConfig.getKuduMapping().getTable();
+ } else {
+ k = StringUtils.trimToEmpty(mappingConfig.getDestination()) + "_"
+ + mappingConfig.getKuduMapping().getDatabase() + "-"
+ + mappingConfig.getKuduMapping().getTable();
+ }
+ Map configMap = mappingConfigCache.computeIfAbsent(k,
+ k1 -> new ConcurrentHashMap<>());
+ configMap.put(configName, mappingConfig);
+ }
+ Map properties = configuration.getProperties();
+
+ String kudu_master = properties.get("kudu.master.address");
+ kuduTemplate = new KuduTemplate(kudu_master);
+ kuduSyncService = new KuduSyncService(kuduTemplate);
+
+ kuduConfigMonitor = new KuduConfigMonitor();
+ kuduConfigMonitor.init(this, envProperties);
+ }
+
+ @Override
+ public void sync(List dmls) {
+ if (dmls == null || dmls.isEmpty()) {
+ return;
+ }
+ for (Dml dml : dmls) {
+ if (dml == null) {
+ return;
+ }
+ String destination = StringUtils.trimToEmpty(dml.getDestination());
+ String groupId = StringUtils.trimToEmpty(dml.getGroupId());
+ String database = dml.getDatabase();
+ String table = dml.getTable();
+ Map configMap;
+ if (envProperties != null && !"tcp".equalsIgnoreCase(envProperties.getProperty("canal.conf.mode"))) {
+ configMap = mappingConfigCache.get(destination + "-"
+ + groupId + "_"
+ + database + "-" + table);
+ } else {
+ configMap = mappingConfigCache.get(destination + "_" + database + "-" + table);
+ }
+ if (configMap != null) {
+ List configs = new ArrayList<>();
+ configMap.values().forEach(config -> {
+ if (StringUtils.isNotEmpty(config.getGroupId())) {
+ if (config.getGroupId().equals(dml.getGroupId())) {
+ configs.add(config);
+ }
+ } else {
+ configs.add(config);
+ }
+ });
+ if (!configs.isEmpty()) {
+ configs.forEach(config -> kuduSyncService.sync(config, dml));
+ } else {
+ logger.error("groupID didn't mach,please check your gruopId ");
+ }
+ } else {
+ logger.error("{} config didn't get,please check your map key ", destination + "_" + database + "-" + table);
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if (kuduConfigMonitor != null) {
+ kuduConfigMonitor.destroy();
+ }
+ //加入kudu client 关闭钩子
+ kuduTemplate.closeKuduClient();
+ }
+
+ @Override
+ public EtlResult etl(String task, List params) {
+ EtlResult etlResult = new EtlResult();
+ KuduMappingConfig config = kuduMapping.get(task);
+ KuduEtlService hbaseEtlService = new KuduEtlService(kuduTemplate, config);
+ if (config != null) {
+ return hbaseEtlService.importData(params);
+ } else {
+ StringBuilder resultMsg = new StringBuilder();
+ boolean resSucc = true;
+ for (KuduMappingConfig configTmp : kuduMapping.values()) {
+ // 取所有的destination为task的配置
+ if (configTmp.getDestination().equals(task)) {
+ EtlResult etlRes = hbaseEtlService.importData(params);
+ if (!etlRes.getSucceeded()) {
+ resSucc = false;
+ resultMsg.append(etlRes.getErrorMessage()).append("\n");
+ } else {
+ resultMsg.append(etlRes.getResultMessage()).append("\n");
+ }
+ }
+ }
+ if (resultMsg.length() > 0) {
+ etlResult.setSucceeded(resSucc);
+ if (resSucc) {
+ etlResult.setResultMessage(resultMsg.toString());
+ } else {
+ etlResult.setErrorMessage(resultMsg.toString());
+ }
+ return etlResult;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Map count(String task) {
+ Map res = new LinkedHashMap<>();
+ KuduMappingConfig config = kuduMapping.get(task);
+ if (config != null && config.getKuduMapping() != null) {
+ String tableName = config.getKuduMapping().getTargetTable();
+ long rowCount = kuduTemplate.countRow(tableName);
+ res.put("kuduTable", tableName);
+ res.put("count", rowCount);
+ }
+ return res;
+ }
+
+ @Override
+ public String getDestination(String task) {
+ KuduMappingConfig config = kuduMapping.get(task);
+ if (config != null && config.getKuduMapping() != null) {
+ return config.getDestination();
+ }
+ return null;
+ }
+}
diff --git a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfig.java b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfig.java
new file mode 100644
index 00000000..bbfc0e6a
--- /dev/null
+++ b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfig.java
@@ -0,0 +1,199 @@
+package com.alibaba.otter.canal.client.adapter.kudu.config;
+
+import com.alibaba.otter.canal.client.adapter.support.AdapterConfig;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author liuyadong
+ * @description kudu配置文件映射
+ */
+public class KuduMappingConfig implements AdapterConfig {
+ private String dataSourceKey; // 数据源key
+
+ private String destination; // canal实例或MQ的topic
+
+ private String groupId; // groupId
+
+ private String outerAdapterKey; // 对应适配器的key
+
+ private boolean concurrent = false; // 是否并行同步
+
+ private KuduMapping kuduMapping; // db映射配置
+
+ @Override
+ public String getDataSourceKey() {
+ return dataSourceKey;
+ }
+
+ @Override
+ public AdapterMapping getMapping() {
+ return kuduMapping;
+ }
+
+ public void setDataSourceKey(String dataSourceKey) {
+ this.dataSourceKey = dataSourceKey;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getOuterAdapterKey() {
+ return outerAdapterKey;
+ }
+
+ public void setOuterAdapterKey(String outerAdapterKey) {
+ this.outerAdapterKey = outerAdapterKey;
+ }
+
+ public boolean getConcurrent() {
+ return concurrent;
+ }
+
+ public void setConcurrent(boolean concurrent) {
+ this.concurrent = concurrent;
+ }
+
+ public KuduMapping getKuduMapping() {
+ return kuduMapping;
+ }
+
+ public void setKuduMapping(KuduMapping kuduMapping) {
+ this.kuduMapping = kuduMapping;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public void setDestination(String destination) {
+ this.destination = destination;
+ }
+
+
+ public void validate() {
+ if (kuduMapping.database == null || kuduMapping.database.isEmpty()) {
+ throw new NullPointerException("KuduMapping.database");
+ }
+ }
+
+ public static class KuduMapping implements AdapterMapping {
+
+ private String database; // 数据库名或schema名
+ private String table; // 表名
+ private Map targetPk = new LinkedHashMap<>(); // 目标表主键字段
+ private boolean mapAll = false; // 映射所有字段
+ private String targetDb; // 目标库名
+ private String targetTable; // 目标表名
+ private Map targetColumns; // 目标表字段映射
+
+ private String etlCondition; // etl条件sql
+
+ private int readBatch = 5000;
+ private int commitBatch = 5000; // etl等批量提交大小
+
+ private Map allMapColumns;
+
+ public String getDatabase() {
+ return database;
+ }
+
+ public void setDatabase(String database) {
+ this.database = database;
+ }
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public Map getTargetPk() {
+ return targetPk;
+ }
+
+ public void setTargetPk(Map targetPk) {
+ this.targetPk = targetPk;
+ }
+
+ public Boolean getMapAll() {
+ return mapAll;
+ }
+
+ public void setMapAll(Boolean mapAll) {
+ this.mapAll = mapAll;
+ }
+
+ public String getTargetDb() {
+ return targetDb;
+ }
+
+ public void setTargetDb(String targetDb) {
+ this.targetDb = targetDb;
+ }
+
+ public String getTargetTable() {
+ return targetTable;
+ }
+
+ public void setTargetTable(String targetTable) {
+ this.targetTable = targetTable;
+ }
+
+ public Map getTargetColumns() {
+ if (targetColumns != null) {
+ targetColumns.forEach((key, value) -> {
+ if (StringUtils.isEmpty(value)) {
+ targetColumns.put(key, key);
+ }
+ });
+ }
+ return targetColumns;
+ }
+
+ public void setTargetColumns(Map targetColumns) {
+ this.targetColumns = targetColumns;
+ }
+
+ public String getEtlCondition() {
+ return etlCondition;
+ }
+
+ public void setEtlCondition(String etlCondition) {
+ this.etlCondition = etlCondition;
+ }
+
+ public int getReadBatch() {
+ return readBatch;
+ }
+
+ public void setReadBatch(int readBatch) {
+ this.readBatch = readBatch;
+ }
+
+ public int getCommitBatch() {
+ return commitBatch;
+ }
+
+ public void setCommitBatch(int commitBatch) {
+ this.commitBatch = commitBatch;
+ }
+
+ public Map getAllMapColumns() {
+ return allMapColumns;
+ }
+
+ public void setAllMapColumns(Map allMapColumns) {
+ this.allMapColumns = allMapColumns;
+ }
+ }
+}
diff --git a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfigLoader.java b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfigLoader.java
new file mode 100644
index 00000000..1edfa2c8
--- /dev/null
+++ b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/config/KuduMappingConfigLoader.java
@@ -0,0 +1,47 @@
+package com.alibaba.otter.canal.client.adapter.kudu.config;
+
+import com.alibaba.otter.canal.client.adapter.config.YmlConfigBinder;
+import com.alibaba.otter.canal.client.adapter.support.MappingConfigsLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author liuyadong
+ * @description kudu表信息加载
+ */
+public class KuduMappingConfigLoader {
+ private static Logger logger = LoggerFactory.getLogger(KuduMappingConfigLoader.class);
+
+ /**
+ * 加载HBase表映射配置
+ *
+ * @return 配置名/配置文件名--对象
+ */
+ public static Map load(Properties envProperties) {
+ logger.info("## Start loading kudu mapping config ... ");
+
+ Map result = new LinkedHashMap<>();
+
+ Map configContentMap = MappingConfigsLoader.loadConfigs("kudu");
+ configContentMap.forEach((fileName, content) -> {
+ KuduMappingConfig config = YmlConfigBinder
+ .bindYmlToObj(null, content, KuduMappingConfig.class, null, envProperties);
+ if (config == null) {
+ return;
+ }
+ try {
+ config.validate();
+ } catch (Exception e) {
+ throw new RuntimeException("ERROR load Config: " + fileName + " " + e.getMessage(), e);
+ }
+ result.put(fileName, config);
+ });
+
+ logger.info("## kudu mapping config loaded");
+ return result;
+ }
+}
diff --git a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/monitor/KuduConfigMonitor.java b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/monitor/KuduConfigMonitor.java
new file mode 100644
index 00000000..8288a44a
--- /dev/null
+++ b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/monitor/KuduConfigMonitor.java
@@ -0,0 +1,162 @@
+package com.alibaba.otter.canal.client.adapter.kudu.monitor;
+
+import com.alibaba.otter.canal.client.adapter.config.YmlConfigBinder;
+import com.alibaba.otter.canal.client.adapter.kudu.KuduAdapter;
+import com.alibaba.otter.canal.client.adapter.kudu.config.KuduMappingConfig;
+import com.alibaba.otter.canal.client.adapter.support.MappingConfigsLoader;
+import com.alibaba.otter.canal.client.adapter.support.Util;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
+import org.apache.commons.io.monitor.FileAlterationMonitor;
+import org.apache.commons.io.monitor.FileAlterationObserver;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author liuyadong
+ * @description 配置文件监听
+ */
+public class KuduConfigMonitor {
+ private static final Logger logger = LoggerFactory.getLogger(KuduConfigMonitor.class);
+
+ private static final String adapterName = "kudu";
+
+ private KuduAdapter kuduAdapter;
+
+ private Properties envProperties;
+
+ private FileAlterationMonitor fileMonitor;
+
+ public void init(KuduAdapter kuduAdapter, Properties envProperties) {
+ this.kuduAdapter = kuduAdapter;
+ this.envProperties = envProperties;
+ File confDir = Util.getConfDirPath(adapterName);
+ try {
+ FileAlterationObserver observer = new FileAlterationObserver(confDir,
+ FileFilterUtils.and(FileFilterUtils.fileFileFilter(), FileFilterUtils.suffixFileFilter("yml")));
+ FileListener listener = new FileListener();
+ observer.addListener(listener);
+ fileMonitor = new FileAlterationMonitor(3000, observer);
+ fileMonitor.start();
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 停止监听配置文件
+ */
+ public void destroy() {
+ try {
+ fileMonitor.stop();
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 配置文件监听
+ */
+ private class FileListener extends FileAlterationListenerAdaptor {
+ @Override
+ public void onFileCreate(File file) {
+ super.onFileCreate(file);
+
+ try {
+ // 加载新增的配置文件
+ String configContent = MappingConfigsLoader.loadConfig(adapterName + File.separator + file.getName());
+ KuduMappingConfig config = YmlConfigBinder
+ .bindYmlToObj(null, configContent, KuduMappingConfig.class, null, envProperties);
+ if (config == null) {
+ return;
+ }
+ config.validate();
+ addConfigToCache(file, config);
+
+ logger.info("Add a new kudu mapping config: {} to canal adapter", file.getName());
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void onFileChange(File file) {
+ super.onFileChange(file);
+
+ try {
+ if (kuduAdapter.getKuduMapping().containsKey(file.getName())) {
+ // 加载配置文件
+ String configContent = MappingConfigsLoader
+ .loadConfig(adapterName + File.separator + file.getName());
+ if (configContent == null) {
+ onFileDelete(file);
+ return;
+ }
+ KuduMappingConfig config = YmlConfigBinder
+ .bindYmlToObj(null, configContent, KuduMappingConfig.class, null, envProperties);
+ if (config == null) {
+ return;
+ }
+ config.validate();
+ if (kuduAdapter.getKuduMapping().containsKey(file.getName())) {
+ deleteConfigFromCache(file);
+ }
+ addConfigToCache(file, config);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+
+ @Override
+ public void onFileDelete(File file) {
+ super.onFileDelete(file);
+
+ try {
+ if (kuduAdapter.getKuduMapping().containsKey(file.getName())) {
+ deleteConfigFromCache(file);
+ logger.info("Delete a hbase mapping config: {} of canal adapter", file.getName());
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 添加配置文件信息到缓存
+ *
+ * @param file
+ * @param config
+ */
+ private void addConfigToCache(File file, KuduMappingConfig config) {
+ kuduAdapter.getKuduMapping().put(file.getName(), config);
+ Map configMap = kuduAdapter.getMappingConfigCache()
+ .computeIfAbsent(StringUtils.trimToEmpty(config.getDestination()) + "."
+ + config.getKuduMapping().getDatabase() + "." + config.getKuduMapping().getTable(),
+ k1 -> new HashMap<>());
+ configMap.put(file.getName(), config);
+ }
+
+ /**
+ * 从缓存中删除配置
+ *
+ * @param file 文件
+ */
+ private void deleteConfigFromCache(File file) {
+ kuduAdapter.getKuduMapping().remove(file.getName());
+ for (Map configMap : kuduAdapter.getMappingConfigCache().values()) {
+ if (configMap != null) {
+ configMap.remove(file.getName());
+ }
+ }
+ }
+
+ }
+}
diff --git a/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/service/KuduEtlService.java b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/service/KuduEtlService.java
new file mode 100644
index 00000000..8f0436cb
--- /dev/null
+++ b/client-adapter/kudu/src/main/java/com/alibaba/otter/canal/client/adapter/kudu/service/KuduEtlService.java
@@ -0,0 +1,131 @@
+package com.alibaba.otter.canal.client.adapter.kudu.service;
+
+import com.alibaba.otter.canal.client.adapter.kudu.config.KuduMappingConfig;
+import com.alibaba.otter.canal.client.adapter.kudu.support.KuduTemplate;
+import com.alibaba.otter.canal.client.adapter.kudu.support.SyncUtil;
+import com.alibaba.otter.canal.client.adapter.support.AbstractEtlService;
+import com.alibaba.otter.canal.client.adapter.support.AdapterConfig;
+import com.alibaba.otter.canal.client.adapter.support.EtlResult;
+import com.alibaba.otter.canal.client.adapter.support.Util;
+import com.google.common.base.Joiner;
+import org.apache.kudu.client.KuduException;
+
+import javax.sql.DataSource;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author liuyadong
+ * @description kudu 拉取历史数据
+ */
+public class KuduEtlService extends AbstractEtlService {
+
+ private KuduTemplate kuduTemplate;
+ private KuduMappingConfig config;
+
+ public KuduEtlService(KuduTemplate kuduTemplate, KuduMappingConfig config) {
+ super("kudu", config);
+ this.kuduTemplate = kuduTemplate;
+ this.config = config;
+ }
+
+ public EtlResult importData(List params) {
+ EtlResult etlResult = new EtlResult();
+ List errMsg = new ArrayList<>();
+
+ KuduMappingConfig.KuduMapping kuduMapping = config.getKuduMapping();
+ boolean flag = kuduTemplate.tableExists(kuduMapping.getTargetTable());
+ //表不存在,停止导入
+ if (!flag) {
+ logger.info("{} is don't hava,please check your kudu table !", kuduMapping.getTargetTable());
+ errMsg.add(kuduMapping.getTargetTable() + " is don't hava,please check your kudu table !");
+ etlResult.setErrorMessage(Joiner.on("\n").join(errMsg));
+ return etlResult;
+ }
+ logger.info("{} etl is starting!", kuduMapping.getTargetTable());
+ String sql = "SELECT * FROM " + kuduMapping.getDatabase() + "." + kuduMapping.getTable();
+ return importData(sql, params);
+ }
+
+
+ @Override
+ protected boolean executeSqlImport(DataSource ds, String sql, List