org.opencb.opencga.storage.hadoop.variant.HadoopVariantStorageTest.java Source code

Java tutorial

Introduction

Here is the source code for org.opencb.opencga.storage.hadoop.variant.HadoopVariantStorageTest.java

Source

/*
 * Copyright 2015-2016 OpenCB
 *
 * 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.
 */

package org.opencb.opencga.storage.hadoop.variant;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.backup.regionserver.LogRollRegionServerProcedureManager;
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.Put;
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
import org.apache.hadoop.hbase.fs.HFileSystem;
import org.apache.hadoop.hbase.io.compress.Compression;
import org.apache.hadoop.hbase.io.hfile.CacheConfig;
import org.apache.hadoop.hbase.mapreduce.TableInputFormatBase;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.master.*;
import org.apache.hadoop.hbase.master.procedure.MasterDDLOperationHelper;
import org.apache.hadoop.hbase.master.procedure.ModifyTableProcedure;
import org.apache.hadoop.hbase.procedure.ProcedureManagerHost;
import org.apache.hadoop.hbase.procedure.ZKProcedureUtil;
import org.apache.hadoop.hbase.procedure.flush.RegionServerFlushTableProcedureManager;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore;
import org.apache.hadoop.hbase.quotas.RegionServerQuotaManager;
import org.apache.hadoop.hbase.regionserver.*;
import org.apache.hadoop.hbase.regionserver.compactions.CompactionConfiguration;
import org.apache.hadoop.hbase.regionserver.snapshot.RegionServerSnapshotManager;
import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.FSTableDescriptors;
import org.apache.hadoop.hbase.zookeeper.ZKTableStateManager;
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
import org.apache.hadoop.hdfs.server.common.Storage;
import org.apache.hadoop.hdfs.server.datanode.DataNode;
import org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream;
import org.apache.hadoop.hdfs.server.namenode.FSEditLog;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.http.HttpServer2;
import org.apache.hadoop.io.compress.CodecPool;
import org.apache.hadoop.mapred.MapTask;
import org.apache.hadoop.mapred.Task;
import org.apache.log4j.Level;
import org.apache.phoenix.coprocessor.MetaDataEndpointImpl;
import org.apache.phoenix.hbase.index.Indexer;
import org.apache.phoenix.hbase.index.covered.data.IndexMemStore;
import org.apache.phoenix.hbase.index.parallel.BaseTaskRunner;
import org.apache.phoenix.hbase.index.write.ParallelWriterIndexCommitter;
import org.apache.phoenix.hbase.index.write.recovery.TrackingParallelWriterIndexCommitter;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.schema.MetaDataClient;
import org.apache.tools.ant.types.Commandline;
import org.apache.zookeeper.ClientCnxn;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.server.NIOServerCnxn;
import org.apache.zookeeper.server.NIOServerCnxnFactory;
import org.apache.zookeeper.server.PrepRequestProcessor;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.junit.Assert;
import org.junit.rules.ExternalResource;
import org.opencb.commons.datastore.core.ObjectMap;
import org.opencb.opencga.storage.core.config.StorageConfiguration;
import org.opencb.opencga.storage.core.config.StorageEtlConfiguration;
import org.opencb.opencga.storage.core.variant.VariantStorageTest;
import org.opencb.opencga.storage.hadoop.utils.HBaseManager;
import org.opencb.opencga.storage.hadoop.variant.archive.ArchiveDriver;
import org.opencb.opencga.storage.hadoop.variant.executors.MRExecutor;
import org.opencb.opencga.storage.hadoop.variant.index.AbstractVariantTableDriver;
import org.opencb.opencga.storage.hadoop.variant.index.VariantTableDeletionDriver;
import org.opencb.opencga.storage.hadoop.variant.index.VariantTableDriver;
import org.opencb.opencga.storage.hadoop.variant.index.VariantTableMapper;
import org.opencb.opencga.storage.hadoop.variant.index.phoenix.PhoenixHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Created on 15/10/15
 *
 * @author Jacobo Coll <jacobo167@gmail.com>
 */
public interface HadoopVariantStorageTest /*extends VariantStorageManagerTestUtils */ extends VariantStorageTest {

    AtomicReference<HBaseTestingUtility> utility = new AtomicReference<>(null);
    AtomicReference<Configuration> configuration = new AtomicReference<>(null);
    //    Set<HadoopVariantStorageEngine> managers = new ConcurrentHashSet<>();
    AtomicReference<HadoopVariantStorageEngine> manager = new AtomicReference<>();

    class HadoopExternalResource extends ExternalResource implements HadoopVariantStorageTest {

        Logger logger = LoggerFactory.getLogger(this.getClass());

        @Override
        public void before() throws Throwable {
            if (utility.get() == null) {

                // Disable most of the useless loggers

                // HBase loggers
                org.apache.log4j.Logger.getLogger(HStore.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HRegion.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HMaster.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HRegionServer.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HFileSystem.class).setLevel(Level.WARN);
                //                org.apache.log4j.Logger.getLogger(HBaseAdmin.class).setLevel(Level.WARN); // This logger is interesting!
                org.apache.log4j.Logger.getLogger(ServerManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RegionServerSnapshotManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(SplitLogWorker.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(LogRollRegionServerProcedureManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HeapMemoryManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MasterMobCompactionThread.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RegionServerFlushTableProcedureManager.class)
                        .setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ChoreService.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RegionServerQuotaManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MetaMigrationConvertingToPB.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(TableNamespaceManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ProcedureManagerHost.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ZKProcedureUtil.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(WALProcedureStore.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ProcedureExecutor.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ModifyTableProcedure.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(DefaultStoreFlusher.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(StoreFile.Reader.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RegionCoprocessorHost.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(CoprocessorHost.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RegionStates.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(AssignmentManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MasterDDLOperationHelper.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(FSTableDescriptors.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ZKTableStateManager.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MetaTableAccessor.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(RSRpcServices.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(CacheConfig.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(CompactionConfiguration.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(CompactSplitThread.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger("org.apache.hadoop.metrics2.impl.MetricsConfig")
                        .setLevel(Level.ERROR);
                org.apache.log4j.Logger
                        .getLogger("org.apache.hadoop.hbase.client.ConnectionManager$HConnectionImplementation")
                        .setLevel(Level.WARN);

                // Phoenix loggers
                org.apache.log4j.Logger.getLogger(ParallelWriterIndexCommitter.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(BaseTaskRunner.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(Indexer.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(IndexMemStore.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(TrackingParallelWriterIndexCommitter.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MetaDataEndpointImpl.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MetaDataClient.class).setLevel(Level.WARN);
                //                org.apache.log4j.Logger.getLogger(QueryUtil.class).setLevel(Level.WARN); // Interesting. Only logs the new connections

                // Hadoop loggers
                org.apache.log4j.Logger.getLogger(CodecPool.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(HttpServer2.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(org.apache.hadoop.ipc.Server.class).setLevel(Level.WARN);

                // Zookeeper loggers
                org.apache.log4j.Logger.getLogger(ZooKeeper.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ZooKeeperServer.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(ClientCnxn.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(NIOServerCnxn.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(NIOServerCnxnFactory.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(PrepRequestProcessor.class).setLevel(Level.WARN);
                // Interesting class for logging new Zookeeper connections
                //                org.apache.log4j.Logger.getLogger(RecoverableZooKeeper.class).setLevel(Level.WARN);

                // HDFS loggers
                org.apache.log4j.Logger.getLogger(FSNamesystem.class.getName() + ".audit").setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(Storage.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(FSNamesystem.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(NameNode.stateChangeLog.getName()).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(NameNode.blockStateChangeLog.getName()).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(DataNode.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(DatanodeDescriptor.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(FSEditLog.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(FSHLog.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(EditLogFileOutputStream.class).setLevel(Level.WARN);
                org.apache.log4j.Logger
                        .getLogger(
                                "org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetAsyncDiskService")
                        .setLevel(Level.WARN);

                // MR loggers
                //                org.apache.log4j.Logger.getLogger(LocalJobRunner.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(Task.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(MapTask.class).setLevel(Level.WARN);
                org.apache.log4j.Logger.getLogger(TableInputFormatBase.class).setLevel(Level.WARN);

                utility.set(new HBaseTestingUtility());
                Configuration conf = utility.get().getConfiguration();
                HadoopVariantStorageTest.configuration.set(conf);

                //                // Change port to avoid port collisions
                //                utility.get().getStorageConfiguration().setInt(HConstants.MASTER_INFO_PORT, HConstants.DEFAULT_MASTER_INFOPORT + 1);

                // Enable phoenix secundary indexes
                conf.set("hbase.regionserver.wal.codec",
                        org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec.class.getName());
                conf.set("hbase.region.server.rpc.scheduler.factory.class",
                        org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory.class.getName());
                conf.set("hbase.rpc.controllerfactory.class",
                        org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory.class.getName());

                // Not required in Phoenix 4.8
                //                conf.set("hbase.master.loadbalancer.class",
                //                        org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer.class.getName());
                //                conf.set("hbase.coprocessor.master.classes",
                //                        org.apache.phoenix.hbase.index.master.IndexMasterObserver.class.getName());
                //                conf.set("hbase.coprocessor.regionserver.classes",
                //                        org.apache.hadoop.hbase.regionserver.LocalIndexMerger.class.getName());

                conf.setBoolean(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, true);

                // Zookeeper always with the same clientPort.
                //                conf.setInt("test.hbase.zookeeper.property.clientPort", 55419);

                utility.get().startMiniCluster(1);

                //            MiniMRCluster miniMRCluster = utility.startMiniMapReduceCluster();
                //            MiniMRClientCluster miniMRClientCluster = MiniMRClientClusterFactory.create(HadoopVariantStorageManagerTestUtils.class, 1, configuration);
                //            miniMRClientCluster.start();

                //                checkHBaseMiniCluster();
            }
        }

        @Override
        public void after() {
            try {
                logger.info("Closing HBaseTestingUtility");
                //                for (HadoopVariantStorageEngine manager : managers) {
                //                    manager.close();
                //                }
                if (manager.get() != null) {
                    manager.get().close();
                    manager.set(null);
                }
                //                for (Connection connection : HBaseManager.CONNECTIONS) {
                //                    connection.close();
                //                }
                System.out.println("HBaseManager.getOpenConnections() = " + HBaseManager.getOpenConnections());

                configuration.set(null);
                try {
                    if (utility.get() != null) {
                        utility.get().shutdownMiniCluster();
                    }
                } finally {
                    utility.set(null);
                }
            } catch (Exception e) {
                Assert.fail(e.getMessage());
            }
            System.out.println("##### HBaseMiniCluster down ###################");
        }

        public Configuration getConf() {
            return configuration.get();
        }

        private void checkHBaseMiniCluster() throws IOException {
            Connection con = ConnectionFactory.createConnection(configuration.get());
            HBaseManager hBaseManager = new HBaseManager(configuration.get(), con);

            String tableName = "table";
            byte[] columnFamily = Bytes.toBytes("0");
            hBaseManager.createTableIfNeeded(hBaseManager.getConnection(), tableName, columnFamily,
                    Collections.emptyList(), Compression.Algorithm.NONE);
            hBaseManager.act(tableName, table -> {
                table.put(Arrays.asList(
                        new Put(Bytes.toBytes("r1")).addColumn(columnFamily, Bytes.toBytes("c"),
                                Bytes.toBytes("value 1")),
                        new Put(Bytes.toBytes("r2")).addColumn(columnFamily, Bytes.toBytes("c"),
                                Bytes.toBytes("value 2")),
                        new Put(Bytes.toBytes("r2")).addColumn(columnFamily, Bytes.toBytes("c2"),
                                Bytes.toBytes("value 3"))));
            });

            hBaseManager.act(tableName, table -> {
                table.getScanner(columnFamily).forEach(result -> {
                    System.out.println("Row: " + Bytes.toString(result.getRow()));
                    for (Map.Entry<byte[], byte[]> entry : result.getFamilyMap(columnFamily).entrySet()) {
                        System.out
                                .println(Bytes.toString(entry.getKey()) + " = " + Bytes.toString(entry.getValue()));
                    }
                });
            });

            TableName tname = TableName.valueOf(tableName);
            try (Admin admin = con.getAdmin()) {
                if (admin.tableExists(tname)) {
                    utility.get().deleteTable(tableName);
                }
            }

            con.close();
        }
    }

    @Override
    default HadoopVariantStorageEngine getVariantStorageEngine() throws Exception {
        synchronized (manager) {
            if (manager.get() == null) {
                manager.set(new HadoopVariantStorageEngine());
            }
        }
        HadoopVariantStorageEngine manager = HadoopVariantStorageTest.manager.get();

        //Make a copy of the configuration
        Configuration conf = new Configuration(false);
        HBaseConfiguration.merge(conf, HadoopVariantStorageTest.configuration.get());
        StorageConfiguration storageConfiguration = getStorageConfiguration(conf);
        storageConfiguration.getStorageEngine(HadoopVariantStorageEngine.STORAGE_ENGINE_ID).getVariant()
                .getOptions().putAll(getOtherStorageConfigurationOptions());

        manager.setConfiguration(storageConfiguration, HadoopVariantStorageEngine.STORAGE_ENGINE_ID);
        manager.mrExecutor = new TestMRExecutor(conf);
        manager.conf = conf;
        return manager;
    }

    static StorageConfiguration getStorageConfiguration(Configuration conf) throws IOException {
        StorageConfiguration storageConfiguration;
        try (InputStream is = HadoopVariantStorageTest.class.getClassLoader()
                .getResourceAsStream("storage-configuration.yml")) {
            storageConfiguration = StorageConfiguration.load(is);
        }
        return updateStorageConfiguration(storageConfiguration, conf);
    }

    static StorageConfiguration updateStorageConfiguration(StorageConfiguration storageConfiguration,
            Configuration conf) throws IOException {
        storageConfiguration.setDefaultStorageEngineId(HadoopVariantStorageEngine.STORAGE_ENGINE_ID);
        StorageEtlConfiguration variantConfiguration = storageConfiguration
                .getStorageEngine(HadoopVariantStorageEngine.STORAGE_ENGINE_ID).getVariant();
        ObjectMap options = variantConfiguration.getOptions();

        options.put(HadoopVariantStorageEngine.EXTERNAL_MR_EXECUTOR, TestMRExecutor.class);
        TestMRExecutor.setStaticConfiguration(conf);

        options.put(GenomeHelper.CONFIG_HBASE_ADD_DEPENDENCY_JARS, false);
        EnumSet<Compression.Algorithm> supportedAlgorithms = EnumSet.of(Compression.Algorithm.NONE,
                HBaseTestingUtility.getSupportedCompressionAlgorithms());

        options.put(ArchiveDriver.CONFIG_ARCHIVE_TABLE_COMPRESSION,
                supportedAlgorithms.contains(Compression.Algorithm.GZ) ? Compression.Algorithm.GZ.getName()
                        : Compression.Algorithm.NONE.getName());
        options.put(VariantTableDriver.CONFIG_VARIANT_TABLE_COMPRESSION,
                supportedAlgorithms.contains(Compression.Algorithm.SNAPPY) ? Compression.Algorithm.SNAPPY.getName()
                        : Compression.Algorithm.NONE.getName());

        FileSystem fs = FileSystem.get(HadoopVariantStorageTest.configuration.get());
        String intermediateDirectory = fs.getHomeDirectory().toUri().resolve("opencga_test/").toString();
        System.out.println(HadoopVariantStorageEngine.OPENCGA_STORAGE_HADOOP_INTERMEDIATE_HDFS_DIRECTORY + " = "
                + intermediateDirectory);
        options.put(CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY,
                conf.get(CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY));
        options.put(HadoopVariantStorageEngine.OPENCGA_STORAGE_HADOOP_INTERMEDIATE_HDFS_DIRECTORY,
                intermediateDirectory);

        options.put(ArchiveDriver.CONFIG_ARCHIVE_TABLE_PRESPLIT_SIZE, 5);
        options.put(AbstractVariantTableDriver.CONFIG_VARIANT_TABLE_PRESPLIT_SIZE, 5);

        variantConfiguration.getDatabase().setHosts(Collections.singletonList(
                "hbase://" + HadoopVariantStorageTest.configuration.get().get(HConstants.ZOOKEEPER_QUORUM)));
        return storageConfiguration;
    }

    default Map<String, ?> getOtherStorageConfigurationOptions() {
        return new ObjectMap();
    }

    default void clearHBase() throws Exception {
        try (Connection con = ConnectionFactory.createConnection(configuration.get());
                Admin admin = con.getAdmin()) {
            for (TableName tableName : admin.listTableNames()) {
                utility.get().deleteTableIfAny(tableName);
            }
        }
    }

    @Override
    default void clearDB(String tableName) throws Exception {
        LoggerFactory.getLogger(HadoopVariantStorageTest.class).info("Drop table " + tableName);
        PhoenixHelper phoenixHelper = new PhoenixHelper(configuration.get());
        try (java.sql.Connection con = phoenixHelper.newJdbcConnection()) {
            if (phoenixHelper.tableExists(con, tableName)) {
                phoenixHelper.dropTable(con, tableName, true, true);
            }
        }
        utility.get().deleteTableIfAny(TableName.valueOf(tableName));
    }

    class TestMRExecutor implements MRExecutor {

        private static Configuration staticConfiguration;
        private final Configuration configuration;

        public TestMRExecutor() {
            this.configuration = new Configuration(staticConfiguration);
        }

        public TestMRExecutor(Configuration configuration) {
            this.configuration = configuration;
        }

        public static void setStaticConfiguration(Configuration staticConfiguration) {
            TestMRExecutor.staticConfiguration = staticConfiguration;
        }

        @Override
        public int run(String executable, String args) {
            try {
                // Copy configuration
                Configuration conf = new Configuration(false);
                HBaseConfiguration.merge(conf, configuration);
                if (executable.endsWith(ArchiveDriver.class.getName())) {
                    System.out.println("Executing ArchiveDriver : " + executable + " " + args);
                    int r = ArchiveDriver.privateMain(Commandline.translateCommandline(args), conf);
                    System.out.println("Finish execution ArchiveDriver");

                    return r;
                } else if (executable.endsWith(VariantTableDriver.class.getName())) {
                    System.out.println("Executing VariantTableDriver : " + executable + " " + args);
                    int r = VariantTableDriver.privateMain(Commandline.translateCommandline(args), conf,
                            new VariantTableDriver() {
                                @Override
                                protected Class<? extends TableMapper> getMapperClass() {
                                    return VariantTableMapperFail.class;
                                }
                            });
                    System.out.println("Finish execution VariantTableDriver");
                    return r;
                } else if (executable.endsWith(VariantTableDeletionDriver.class.getName())) {
                    System.out.println("Executing VariantTableDeletionDriver : " + executable + " " + args);
                    int r = VariantTableDeletionDriver.privateMain(Commandline.translateCommandline(args), conf);
                    System.out.println("Finish execution VariantTableDeletionDriver");
                    return r;
                }
            } catch (Exception e) {
                e.printStackTrace();
                return -1;
            }
            return 0;
        }
    }

    class VariantTableMapperFail extends VariantTableMapper {

        public static final String SLICE_TO_FAIL = "slice.to.fail";
        private String sliceToFail = "";
        private AtomicBoolean hadFail = new AtomicBoolean();

        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            super.setup(context);

            hadFail.set(false);
            sliceToFail = context.getConfiguration().get(SLICE_TO_FAIL, sliceToFail);

        }

        @Override
        protected void doMap(VariantMapReduceContext ctx) throws IOException, InterruptedException {
            if (Bytes.toString(ctx.getCurrRowKey()).equals(sliceToFail)) {
                if (!hadFail.getAndSet(true)) {
                    System.out.println("DO FAIL!!");
                    ctx.getContext().getCounter(COUNTER_GROUP_NAME, "TEST.FAIL").increment(1);
                    throw new RuntimeException();
                }
            }
            super.doMap(ctx);
        }
    }

}