/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.hadoop.hbase.spark;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.IntegrationTestBase;
import org.apache.hadoop.hbase.IntegrationTestingUtility;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Consistency;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.IntegrationTestBulkLoad;
import org.apache.hadoop.hbase.tool.LoadIncrementalHFiles;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.util.RegionSplitter;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.util.ToolRunner;
import org.apache.spark.Partitioner;
import org.apache.spark.SerializableWritable;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFlatMapFunction;
import org.apache.spark.api.java.function.VoidFunction;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Tuple2;

import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;

/**
 * Test Bulk Load and Spark on a distributed cluster.
 * It starts an Spark job that creates linked chains.
 * This test mimic {@link IntegrationTestBulkLoad} in mapreduce.
 *
 * Usage on cluster:
 *   First add hbase related jars and hbase-spark.jar into spark classpath.
 *
 *   spark-submit --class org.apache.hadoop.hbase.spark.IntegrationTestSparkBulkLoad
 *                HBASE_HOME/lib/hbase-spark-it-XXX-tests.jar -m slowDeterministic
 *                -Dhbase.spark.bulkload.chainlength=300
 */
public class IntegrationTestSparkBulkLoad extends IntegrationTestBase {

  private static final Logger LOG = LoggerFactory.getLogger(IntegrationTestSparkBulkLoad.class);

  // The number of partitions for random generated data
  private static String BULKLOAD_PARTITIONS_NUM = "hbase.spark.bulkload.partitionsnum";
  private static int DEFAULT_BULKLOAD_PARTITIONS_NUM = 3;

  private static String BULKLOAD_CHAIN_LENGTH = "hbase.spark.bulkload.chainlength";
  private static int DEFAULT_BULKLOAD_CHAIN_LENGTH = 200000;

  private static String BULKLOAD_IMPORT_ROUNDS = "hbase.spark.bulkload.importround";
  private static int DEFAULT_BULKLOAD_IMPORT_ROUNDS  = 1;

  private static String CURRENT_ROUND_NUM = "hbase.spark.bulkload.current.roundnum";

  private static String NUM_REPLICA_COUNT_KEY = "hbase.spark.bulkload.replica.countkey";
  private static int DEFAULT_NUM_REPLICA_COUNT = 1;

  private static String BULKLOAD_TABLE_NAME = "hbase.spark.bulkload.tableName";
  private static String DEFAULT_BULKLOAD_TABLE_NAME = "IntegrationTestSparkBulkLoad";

  private static String BULKLOAD_OUTPUT_PATH = "hbase.spark.bulkload.output.path";

  private static final String OPT_LOAD = "load";
  private static final String OPT_CHECK = "check";

  private boolean load = false;
  private boolean check = false;

  private static final byte[] CHAIN_FAM  = Bytes.toBytes("L");
  private static final byte[] SORT_FAM = Bytes.toBytes("S");
  private static final byte[] DATA_FAM = Bytes.toBytes("D");

  /**
   * Running spark job to load data into hbase table
   */
  public void runLoad() throws Exception {
    setupTable();
    int numImportRounds = getConf().getInt(BULKLOAD_IMPORT_ROUNDS, DEFAULT_BULKLOAD_IMPORT_ROUNDS);
    LOG.info("Running load with numIterations:" + numImportRounds);
    for (int i = 0; i < numImportRounds; i++) {
      runLinkedListSparkJob(i);
    }
  }

  /**
   * Running spark job to create LinkedList for testing
   * @param iteration iteration th of this job
   * @throws Exception if an HBase operation or getting the test directory fails
   */
  public void runLinkedListSparkJob(int iteration) throws Exception {
    String jobName =  IntegrationTestSparkBulkLoad.class.getSimpleName() + " _load " +
        EnvironmentEdgeManager.currentTime();

    LOG.info("Running iteration " + iteration + "in Spark Job");

    Path output = null;
    if (conf.get(BULKLOAD_OUTPUT_PATH) == null) {
      output = util.getDataTestDirOnTestFS(getTablename() + "-" + iteration);
    } else {
      output = new Path(conf.get(BULKLOAD_OUTPUT_PATH));
    }

    SparkConf sparkConf = new SparkConf().setAppName(jobName).setMaster("local");
    Configuration hbaseConf = new Configuration(getConf());
    hbaseConf.setInt(CURRENT_ROUND_NUM, iteration);
    int partitionNum = hbaseConf.getInt(BULKLOAD_PARTITIONS_NUM, DEFAULT_BULKLOAD_PARTITIONS_NUM);


    JavaSparkContext jsc = new JavaSparkContext(sparkConf);
    JavaHBaseContext hbaseContext = new JavaHBaseContext(jsc, hbaseConf);


    LOG.info("Partition RDD into " + partitionNum + " parts");
    List<String> temp = new ArrayList<>();
    JavaRDD<List<byte[]>> rdd = jsc.parallelize(temp, partitionNum).
        mapPartitionsWithIndex(new LinkedListCreationMapper(new SerializableWritable<>(hbaseConf)),
                false);

    hbaseContext.bulkLoad(rdd, getTablename(), new ListToKeyValueFunc(), output.toUri().getPath(),
        new HashMap<>(), false, HConstants.DEFAULT_MAX_FILE_SIZE);

    try (Connection conn = ConnectionFactory.createConnection(conf);
        Admin admin = conn.getAdmin();
        Table table = conn.getTable(getTablename());
        RegionLocator regionLocator = conn.getRegionLocator(getTablename())) {
      // Create a new loader.
      LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);

      // Load the HFiles into table.
      loader.doBulkLoad(output, admin, table, regionLocator);
    }


    // Delete the files.
    util.getTestFileSystem().delete(output, true);
    jsc.close();
  }

  // See mapreduce.IntegrationTestBulkLoad#LinkedListCreationMapper
  // Used to generate test data
  public static class LinkedListCreationMapper implements
      Function2<Integer, Iterator<String>, Iterator<List<byte[]>>> {

    SerializableWritable swConfig = null;
    private Random rand = new Random();

    public LinkedListCreationMapper(SerializableWritable conf) {
      this.swConfig = conf;
    }

    @Override
    public Iterator<List<byte[]>> call(Integer v1, Iterator v2) throws Exception {
      Configuration config = (Configuration) swConfig.value();
      int partitionId = v1.intValue();
      LOG.info("Starting create List in Partition " + partitionId);

      int partitionNum = config.getInt(BULKLOAD_PARTITIONS_NUM, DEFAULT_BULKLOAD_PARTITIONS_NUM);
      int chainLength = config.getInt(BULKLOAD_CHAIN_LENGTH, DEFAULT_BULKLOAD_CHAIN_LENGTH);
      int iterationsNum = config.getInt(BULKLOAD_IMPORT_ROUNDS, DEFAULT_BULKLOAD_IMPORT_ROUNDS);
      int iterationsCur = config.getInt(CURRENT_ROUND_NUM, 0);
      List<List<byte[]>> res = new LinkedList<>();


      long tempId = partitionId + iterationsCur * partitionNum;
      long totalPartitionNum = partitionNum * iterationsNum;
      long chainId = Math.abs(rand.nextLong());
      chainId = chainId - (chainId % totalPartitionNum) + tempId;

      byte[] chainIdArray = Bytes.toBytes(chainId);
      long currentRow = 0;
      long nextRow = getNextRow(0, chainLength);
      for(long i = 0; i < chainLength; i++) {
        byte[] rk = Bytes.toBytes(currentRow);
        // Insert record into a list
        List<byte[]> tmp1 = Arrays.asList(rk, CHAIN_FAM, chainIdArray, Bytes.toBytes(nextRow));
        List<byte[]> tmp2 = Arrays.asList(rk, SORT_FAM, chainIdArray, Bytes.toBytes(i));
        List<byte[]> tmp3 = Arrays.asList(rk, DATA_FAM, chainIdArray, Bytes.toBytes("random" + i));
        res.add(tmp1);
        res.add(tmp2);
        res.add(tmp3);

        currentRow = nextRow;
        nextRow = getNextRow(i+1, chainLength);
      }
      return res.iterator();
    }

    /** Returns a unique row id within this chain for this index */
    private long getNextRow(long index, long chainLength) {
      long nextRow = Math.abs(new Random().nextLong());
      // use significant bits from the random number, but pad with index to ensure it is unique
      // this also ensures that we do not reuse row = 0
      // row collisions from multiple mappers are fine, since we guarantee unique chainIds
      nextRow = nextRow - (nextRow % chainLength) + index;
      return nextRow;
    }
  }



  public static class ListToKeyValueFunc implements
      Function<List<byte[]>, Pair<KeyFamilyQualifier, byte[]>> {
    @Override
    public Pair<KeyFamilyQualifier, byte[]> call(List<byte[]> v1) throws Exception {
      if (v1 == null || v1.size() != 4) {
        return null;
      }
      KeyFamilyQualifier kfq = new KeyFamilyQualifier(v1.get(0), v1.get(1), v1.get(2));

      return new Pair<>(kfq, v1.get(3));
    }
  }

  /**
   * After adding data to the table start a mr job to check the bulk load.
   */
  public void runCheck() throws Exception {
    LOG.info("Running check");
    String jobName = IntegrationTestSparkBulkLoad.class.getSimpleName() + "_check" +
            EnvironmentEdgeManager.currentTime();

    SparkConf sparkConf = new SparkConf().setAppName(jobName).setMaster("local");
    Configuration hbaseConf = new Configuration(getConf());
    JavaSparkContext jsc = new JavaSparkContext(sparkConf);
    JavaHBaseContext hbaseContext = new JavaHBaseContext(jsc, hbaseConf);

    Scan scan = new Scan();
    scan.addFamily(CHAIN_FAM);
    scan.addFamily(SORT_FAM);
    scan.setMaxVersions(1);
    scan.setCacheBlocks(false);
    scan.setBatch(1000);
    int replicaCount = conf.getInt(NUM_REPLICA_COUNT_KEY, DEFAULT_NUM_REPLICA_COUNT);
    if (replicaCount != DEFAULT_NUM_REPLICA_COUNT) {
      scan.setConsistency(Consistency.TIMELINE);
    }

    // 1. Using TableInputFormat to get data from HBase table
    // 2. Mimic LinkedListCheckingMapper in mapreduce.IntegrationTestBulkLoad
    // 3. Sort LinkKey by its order ID
    // 4. Group LinkKey if they have same chainId, and repartition RDD by NaturalKeyPartitioner
    // 5. Check LinkList in each Partition using LinkedListCheckingFlatMapFunc
    hbaseContext.hbaseRDD(getTablename(), scan).flatMapToPair(new LinkedListCheckingFlatMapFunc())
        .sortByKey()
        .combineByKey(new createCombinerFunc(), new mergeValueFunc(), new mergeCombinersFunc(),
            new NaturalKeyPartitioner(new SerializableWritable<>(hbaseConf)))
        .foreach(new LinkedListCheckingForeachFunc(new SerializableWritable<>(hbaseConf)));
    jsc.close();
  }

  private void runCheckWithRetry() throws Exception {
    try {
      runCheck();
    } catch (Throwable t) {
      LOG.warn("Received " + StringUtils.stringifyException(t));
      LOG.warn("Running the check MR Job again to see whether an ephemeral problem or not");
      runCheck();
      throw t; // we should still fail the test even if second retry succeeds
    }
    // everything green
  }

  /**
   * PairFlatMapFunction used to transfer {@code <Row, Result>} to
   * {@code Tuple<SparkLinkKey, SparkLinkChain>}.
   */
  public static class LinkedListCheckingFlatMapFunc implements
      PairFlatMapFunction<Tuple2<ImmutableBytesWritable, Result>, SparkLinkKey, SparkLinkChain> {

    @Override
    public Iterator<Tuple2<SparkLinkKey, SparkLinkChain>> call(Tuple2<ImmutableBytesWritable,
            Result> v) throws Exception {
      Result value = v._2();
      long longRk = Bytes.toLong(value.getRow());
      List<Tuple2<SparkLinkKey, SparkLinkChain>> list = new LinkedList<>();

      for (Map.Entry<byte[], byte[]> entry : value.getFamilyMap(CHAIN_FAM).entrySet()) {
        long chainId = Bytes.toLong(entry.getKey());
        long next = Bytes.toLong(entry.getValue());
        Cell c = value.getColumnCells(SORT_FAM, entry.getKey()).get(0);
        long order = Bytes.toLong(CellUtil.cloneValue(c));
        Tuple2<SparkLinkKey, SparkLinkChain> tuple2 =
            new Tuple2<>(new SparkLinkKey(chainId, order), new SparkLinkChain(longRk, next));
        list.add(tuple2);
      }
      return list.iterator();
    }
  }

  public static class createCombinerFunc implements
      Function<SparkLinkChain, List<SparkLinkChain>> {
    @Override
    public List<SparkLinkChain> call(SparkLinkChain v1) throws Exception {
      List<SparkLinkChain> list = new LinkedList<>();
      list.add(v1);
      return list;
    }
  }

  public static class mergeValueFunc implements
      Function2<List<SparkLinkChain>, SparkLinkChain, List<SparkLinkChain>> {
    @Override
    public List<SparkLinkChain> call(List<SparkLinkChain> v1, SparkLinkChain v2) throws Exception {
      if (v1 == null) {
        v1 = new LinkedList<>();
      }

      v1.add(v2);
      return v1;
    }
  }

  public static class mergeCombinersFunc implements
      Function2<List<SparkLinkChain>, List<SparkLinkChain>, List<SparkLinkChain>> {
    @Override
    public List<SparkLinkChain> call(List<SparkLinkChain> v1, List<SparkLinkChain> v2)
            throws Exception {
      v1.addAll(v2);
      return v1;
    }
  }

  /**
   * Class to figure out what partition to send a link in the chain to.  This is based upon
   * the linkKey's ChainId.
   */
  public static class NaturalKeyPartitioner extends Partitioner {

    private int numPartions = 0;
    public NaturalKeyPartitioner(SerializableWritable swConf) {
      Configuration hbaseConf = (Configuration) swConf.value();
      numPartions = hbaseConf.getInt(BULKLOAD_PARTITIONS_NUM, DEFAULT_BULKLOAD_PARTITIONS_NUM);

    }

    @Override
    public int numPartitions() {
      return numPartions;
    }

    @Override
    public int getPartition(Object key) {
      if (!(key instanceof SparkLinkKey)) {
        return -1;
      }

      int hash = ((SparkLinkKey) key).getChainId().hashCode();
      return Math.abs(hash % numPartions);

    }
  }

  /**
   * Sort all LinkChain for one LinkKey, and test {@code List<LinkChain>}.
   */
  public static class LinkedListCheckingForeachFunc
      implements VoidFunction<Tuple2<SparkLinkKey, List<SparkLinkChain>>> {

    private  SerializableWritable swConf = null;

    public LinkedListCheckingForeachFunc(SerializableWritable conf) {
      swConf = conf;
    }

    @Override
    public void call(Tuple2<SparkLinkKey, List<SparkLinkChain>> v1) throws Exception {
      long next = -1L;
      long prev = -1L;
      long count = 0L;

      SparkLinkKey key = v1._1();
      List<SparkLinkChain> values = v1._2();

      for (SparkLinkChain lc : values) {

        if (next == -1) {
          if (lc.getRk() != 0L) {
            String msg = "Chains should all start at rk 0, but read rk " + lc.getRk()
                + ". Chain:" + key.getChainId() + ", order:" + key.getOrder();
            throw new RuntimeException(msg);
          }
          next = lc.getNext();
        } else {
          if (next != lc.getRk()) {
            String msg = "Missing a link in the chain. Prev rk " + prev + " was, expecting "
                + next + " but got " + lc.getRk() + ". Chain:" + key.getChainId()
                + ", order:" + key.getOrder();
            throw new RuntimeException(msg);
          }
          prev = lc.getRk();
          next = lc.getNext();
        }
        count++;
      }
      Configuration hbaseConf = (Configuration) swConf.value();
      int expectedChainLen = hbaseConf.getInt(BULKLOAD_CHAIN_LENGTH, DEFAULT_BULKLOAD_CHAIN_LENGTH);
      if (count != expectedChainLen) {
        String msg = "Chain wasn't the correct length.  Expected " + expectedChainLen + " got "
            + count + ". Chain:" + key.getChainId() + ", order:" + key.getOrder();
        throw new RuntimeException(msg);
      }
    }
  }

  /**
   * Writable class used as the key to group links in the linked list.
   *
   * Used as the key emited from a pass over the table.
   */
  public static class SparkLinkKey implements java.io.Serializable, Comparable<SparkLinkKey> {

    private Long chainId;
    private Long order;

    public Long getOrder() {
      return order;
    }

    public Long getChainId() {
      return chainId;
    }

    public SparkLinkKey(long chainId, long order) {
      this.chainId = chainId;
      this.order = order;
    }

    @Override
    public int hashCode() {
      return this.getChainId().hashCode();
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof SparkLinkKey)) {
        return false;
      }

      SparkLinkKey otherKey = (SparkLinkKey) other;
      return this.getChainId().equals(otherKey.getChainId());
    }

    @Override
    public int compareTo(SparkLinkKey other) {
      int res = getChainId().compareTo(other.getChainId());

      if (res == 0) {
        res = getOrder().compareTo(other.getOrder());
      }

      return res;
    }
  }

  /**
   * Writable used as the value emitted from a pass over the hbase table.
   */
  public static class SparkLinkChain implements java.io.Serializable, Comparable<SparkLinkChain>{

    public Long getNext() {
      return next;
    }

    public Long getRk() {
      return rk;
    }


    public SparkLinkChain(Long rk, Long next) {
      this.rk = rk;
      this.next = next;
    }

    private Long rk;
    private Long next;

    @Override
    public int compareTo(SparkLinkChain linkChain) {
      int res = getRk().compareTo(linkChain.getRk());
      if (res == 0) {
        res = getNext().compareTo(linkChain.getNext());
      }
      return res;
    }

    @Override
    public int hashCode() {
      return getRk().hashCode() ^ getNext().hashCode();
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof SparkLinkChain)) {
        return false;
      }

      SparkLinkChain otherKey = (SparkLinkChain) other;
      return this.getRk().equals(otherKey.getRk()) && this.getNext().equals(otherKey.getNext());
    }
  }


  /**
   * Allow the scan to go to replica, this would not affect the runCheck()
   * Since data are BulkLoaded from HFile into table
   * @throws IOException if an HBase operation fails
   * @throws InterruptedException if modifying the table fails
   */
  private void installSlowingCoproc() throws IOException, InterruptedException {
    int replicaCount = conf.getInt(NUM_REPLICA_COUNT_KEY, DEFAULT_NUM_REPLICA_COUNT);

    if (replicaCount == DEFAULT_NUM_REPLICA_COUNT) {
      return;
    }

    TableName t = getTablename();
    Admin admin = util.getAdmin();
    HTableDescriptor desc = admin.getTableDescriptor(t);
    desc.addCoprocessor(IntegrationTestBulkLoad.SlowMeCoproScanOperations.class.getName());
    HBaseTestingUtility.modifyTableSync(admin, desc);
  }

  @Test
  public void testBulkLoad() throws Exception {
    runLoad();
    installSlowingCoproc();
    runCheckWithRetry();
  }


  private byte[][] getSplits(int numRegions) {
    RegionSplitter.UniformSplit split = new RegionSplitter.UniformSplit();
    split.setFirstRow(Bytes.toBytes(0L));
    split.setLastRow(Bytes.toBytes(Long.MAX_VALUE));
    return split.split(numRegions);
  }

  private void setupTable() throws IOException, InterruptedException {
    if (util.getAdmin().tableExists(getTablename())) {
      util.deleteTable(getTablename());
    }

    util.createTable(
        getTablename(),
        new byte[][]{CHAIN_FAM, SORT_FAM, DATA_FAM},
        getSplits(16)
    );

    int replicaCount = conf.getInt(NUM_REPLICA_COUNT_KEY, DEFAULT_NUM_REPLICA_COUNT);

    if (replicaCount == DEFAULT_NUM_REPLICA_COUNT) {
      return;
    }

    TableName t = getTablename();
    HBaseTestingUtility.setReplicas(util.getAdmin(), t, replicaCount);
  }

  @Override
  public void setUpCluster() throws Exception {
    util = getTestingUtil(getConf());
    util.initializeCluster(1);
    int replicaCount = getConf().getInt(NUM_REPLICA_COUNT_KEY, DEFAULT_NUM_REPLICA_COUNT);
    if (LOG.isDebugEnabled() && replicaCount != DEFAULT_NUM_REPLICA_COUNT) {
      LOG.debug("Region Replicas enabled: " + replicaCount);
    }

    // Scale this up on a real cluster
    if (util.isDistributedCluster()) {
      util.getConfiguration().setIfUnset(BULKLOAD_PARTITIONS_NUM,
              String.valueOf(DEFAULT_BULKLOAD_PARTITIONS_NUM));
      util.getConfiguration().setIfUnset(BULKLOAD_IMPORT_ROUNDS, "1");
    } else {
      util.startMiniMapReduceCluster();
    }
  }

  @Override
  protected void addOptions() {
    super.addOptions();
    super.addOptNoArg(OPT_CHECK, "Run check only");
    super.addOptNoArg(OPT_LOAD, "Run load only");
  }

  @Override
  protected void processOptions(CommandLine cmd) {
    super.processOptions(cmd);
    check = cmd.hasOption(OPT_CHECK);
    load = cmd.hasOption(OPT_LOAD);
  }

  @Override
  public int runTestFromCommandLine() throws Exception {
    if (load) {
      runLoad();
    } else if (check) {
      installSlowingCoproc();
      runCheckWithRetry();
    } else {
      testBulkLoad();
    }
    return 0;
  }

  @Override
  public TableName getTablename() {
    return getTableName(getConf());
  }

  public static TableName getTableName(Configuration conf) {
    return TableName.valueOf(conf.get(BULKLOAD_TABLE_NAME, DEFAULT_BULKLOAD_TABLE_NAME));
  }

  @Override
  protected Set<String> getColumnFamilies() {
    return Sets.newHashSet(Bytes.toString(CHAIN_FAM) , Bytes.toString(DATA_FAM),
        Bytes.toString(SORT_FAM));
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = HBaseConfiguration.create();
    IntegrationTestingUtility.setUseDistributedCluster(conf);
    int status =  ToolRunner.run(conf, new IntegrationTestSparkBulkLoad(), args);
    System.exit(status);
  }
}
