com.ery.hadoop.mrddx.hbase.HbaseOutputFormat.java Source code

Java tutorial

Introduction

Here is the source code for com.ery.hadoop.mrddx.hbase.HbaseOutputFormat.java

Source

/**
 * 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 com.ery.hadoop.mrddx.hbase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.io.compress.Compression.Algorithm;
import org.apache.hadoop.hbase.mapreduce.TableOutputCommitter;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.OutputCommitter;
import org.apache.hadoop.mapreduce.OutputFormat;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;

import com.ery.hadoop.mrddx.DBRecord;
import com.ery.hadoop.mrddx.DBReducer;
import com.ery.hadoop.mrddx.IHandleFormat;
import com.ery.hadoop.mrddx.log.MRLog;
import com.ery.hadoop.mrddx.util.StringUtil;

/**
 * A OutputFormat that sends the reduce output to a SQL table.
 * 
    
    
    
 * @createDate 2013-1-15
 * @version v1.0
 * @param <K>
 * @param <V>
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class HbaseOutputFormat<K extends HbaseWritable, V> extends OutputFormat<K, NullWritable>
        implements IHandleFormat {
    private static final Log LOG = LogFactory.getLog(HbaseOutputFormat.class);

    /**
     * ?
     * 
     * @param dbConf
     *            hbase?
     * @return true??
     * @throws Exception
     *             
     */
    public static boolean validateTable(HbaseConfiguration dbConf) throws Exception {
        Configuration conf = HBaseConfiguration.create();
        dbConf.setOutputHBaseConfParam(conf);
        HBaseAdmin admin = new HBaseAdmin(conf);

        // ?
        String tableName = dbConf.getOutputHBaseTableName();
        boolean isExistTable = admin.tableExists(tableName);
        if (!isExistTable) {
            // 
            return createTable(dbConf);
        }

        if (!dbConf.getOutputHBaseTableIsModify()) {
            return true;
        }

        // ??
        int blocksize = dbConf.getOutputHBaseColmunBlocksize();
        Algorithm compactionCompressionType = dbConf.getOutputHBaseColmunCompactionCompressionType();
        Algorithm compressionType = dbConf.getOutputHBaseColmunCompressionType();
        int maxversion = dbConf.getOutputHBaseColmunMaxversion();
        int minversion = dbConf.getOutputHBaseColmunMinversion();
        BloomType bloomType = dbConf.getOutputHBaseBloomFilterType();
        boolean inMemory = dbConf.getOutputHBaseSetInMemory();

        // ??
        HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(tableName));

        // ???
        List<HColumnDescriptor> lstModifyHColumnDesc = new ArrayList<HColumnDescriptor>();
        List<String> lstFamily = Arrays.asList(dbConf.getOutputHBaseFamilyNames());
        List<String> lstExistFamily = new ArrayList<String>();
        for (HColumnDescriptor hcd : tableDesc.getColumnFamilies()) {
            if (lstFamily.contains(hcd.getNameAsString())) {
                lstExistFamily.add(hcd.getNameAsString());
            }

            if (blocksize != hcd.getBlocksize()
                    || !compactionCompressionType.equals(hcd.getCompactionCompressionType())
                    || !compressionType.equals(hcd.getCompressionType()) || maxversion != (hcd.getMaxVersions())
                    || minversion != (hcd.getMinVersions()) || bloomType != hcd.getBloomFilterType()
                    || inMemory != hcd.isInMemory()) {
                lstModifyHColumnDesc.add(hcd);
            }
        }

        // ?
        if (admin.isTableEnabled(tableName)) {
            admin.disableTable(tableName);
        }

        // ?
        boolean isAddColumn = false;
        for (String familyName : lstFamily) {
            if (lstExistFamily.contains(familyName)) {
                continue;
            }
            isAddColumn = true;
            HColumnDescriptor hcolumn = new HColumnDescriptor(familyName);
            hcolumn.setBlocksize(blocksize);
            hcolumn.setCompactionCompressionType(compactionCompressionType);
            hcolumn.setCompressionType(compressionType);
            hcolumn.setMinVersions(maxversion);
            hcolumn.setMaxVersions(minversion);
            hcolumn.setBloomFilterType(bloomType);
            hcolumn.setInMemory(inMemory);
            admin.addColumn(tableName, hcolumn);
        }

        if (isAddColumn) {
            MRLog.info(LOG, "?!");
        }

        // 
        for (HColumnDescriptor hcolumn : lstModifyHColumnDesc) {
            hcolumn.setBlocksize(blocksize);
            hcolumn.setCompactionCompressionType(compactionCompressionType);
            hcolumn.setCompressionType(compressionType);
            hcolumn.setMinVersions(maxversion);
            hcolumn.setMaxVersions(minversion);
            hcolumn.setBloomFilterType(bloomType);
            hcolumn.setInMemory(inMemory);
            admin.modifyColumn(tableName, hcolumn);
        }

        if (lstModifyHColumnDesc.size() > 0) {
            MRLog.info(LOG, "?!");
        }

        // ?
        if (!admin.isTableEnabled(tableName)) {
            admin.enableTable(tableName);
        }

        return true;
    }

    /**
     * 
     * 
     * @param dbConf
     *            hbase config
     * @return true ??
     * @throws Exception
     *             
     */
    public static boolean createTable(HbaseConfiguration dbConf) throws Exception {
        // ??
        String tableName = dbConf.getOutputHBaseTableName();
        int blocksize = dbConf.getOutputHBaseColmunBlocksize();
        Algorithm compactionCompressionType = dbConf.getOutputHBaseColmunCompactionCompressionType();
        Algorithm compressionType = dbConf.getOutputHBaseColmunCompressionType();
        int maxversion = dbConf.getOutputHBaseColmunMaxversion();
        int minversion = dbConf.getOutputHBaseColmunMinversion();
        BloomType bloomType = dbConf.getOutputHBaseBloomFilterType();
        boolean inMemory = dbConf.getOutputHBaseSetInMemory();

        long hfileMaxfilesize = dbConf.getOutputHBaseHFileMaxfilesize();
        long memstoreFlushSize = dbConf.getOutputHBaseMemstoreFlushSize();
        boolean isDeferredLogFlush = dbConf.getOutputHBaseIsDeferredLogFlush();
        String familyNames[] = dbConf.getOutputHBaseFamilyNames();

        // 
        try {
            HBaseAdmin admin = new HBaseAdmin(dbConf.getConf());
            HTableDescriptor tableDesc = new HTableDescriptor(tableName);
            tableDesc.setMaxFileSize(hfileMaxfilesize);
            tableDesc.setMemStoreFlushSize(memstoreFlushSize);
            tableDesc.setDeferredLogFlush(isDeferredLogFlush);

            // ?
            for (int i = 0; i < familyNames.length; i++) {
                HColumnDescriptor hcolumn = new HColumnDescriptor(familyNames[i]);
                hcolumn.setBlocksize(blocksize);
                hcolumn.setCompactionCompressionType(compactionCompressionType);
                hcolumn.setCompressionType(compressionType);
                hcolumn.setMinVersions(minversion);
                hcolumn.setMaxVersions(maxversion);
                hcolumn.setBloomFilterType(bloomType);
                hcolumn.setInMemory(inMemory);
                tableDesc.addFamily(hcolumn);
            }
            admin.createTable(tableDesc);
            MRLog.info(LOG, "Create hbase table success!");
            return true;
        } catch (IOException e) {
            String errorInfo = "Create hbase table error!";
            MRLog.error(LOG, errorInfo);
            throw new Exception(errorInfo);
        }
    }

    @Override
    public RecordWriter<K, NullWritable> getRecordWriter(TaskAttemptContext context)
            throws IOException, InterruptedException {
        // public RecordWriter<K, NullWritable> getRecordWriter(FileSystem
        // ignored, JobConf job, String name,
        // Progressable progress) throws IOException {
        HbaseConfiguration dbConf = new HbaseConfiguration(context.getConfiguration(),
                HbaseConfiguration.FLAG_HBASE_OUTPUT);
        HTable table = new HTable(dbConf.getConf(), dbConf.getOutputHBaseTableName());
        table.setAutoFlush(false, true);
        table.setWriteBufferSize(dbConf.getOutputHBaseWriteBuffersize());
        return new HbaseRecordWriter<K, NullWritable>(dbConf, table);
    }

    /**
     * ?hbase?
     * 
     * @param job
     *            ?
     * @param tableName
     *            ??
     * @param rowKeyRule
     *            
     * @param memstoreFlushSize
     *            ?
     * @param isDeferredLogFlush
     *            
     * @param hfileMaxfilesize
     *            hfile
     * @param colmunCompressionType
     *            
     * @param colmunCompactionCompressionType
     *            ?
     * @param colmunBlocksize
     *            ??
     * @param colmunMaxversion
     *            
     * @param colmunMinversion
     *            ?
     * @param bloomType
     *            
     * @param inMemory
     *            ?
     * @param commitBufferLength
     *            ???
     * @param familyColumnName
     *            ???
     * @return HbaseConfiguration HBase?
     * @throws Exception
     *             
     */
    public static HbaseConfiguration setOutput(Job job, String tableName, String rowKeyRule, long memstoreFlushSize,
            boolean isDeferredLogFlush, int hfileMaxfilesize, int colmunCompressionType,
            int colmunCompactionCompressionType, int colmunBlocksize, int colmunMaxversion, int colmunMinversion,
            int bloomType, boolean inMemory, int commitBufferLength, String familyColumnName) throws Exception {
        HbaseConfiguration dbConf = setOutput(job, tableName);
        if (null != familyColumnName) {
            String familyColumnNames[] = familyColumnName.split(",");
            // ?family
            List<String> lstFamily = new ArrayList<String>();
            for (int i = 0; i < familyColumnNames.length; i++) {
                if (null == familyColumnNames[i]) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                String temp[] = familyColumnNames[i].split(HbaseConfiguration.sign_colon);
                if (temp.length != 2 || temp[0].trim().length() <= 0 || temp[1].trim().length() <= 0) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                if (!lstFamily.contains(temp[0])) {
                    lstFamily.add(temp[0]);
                }
            }

            dbConf.setOutputHBaseFamilyNames(lstFamily.toArray(new String[0]));
            dbConf.setOutputHBaseFieldNames(familyColumnName);
        }

        dbConf.setOutputHBaseRowKeyRule(rowKeyRule);

        dbConf.setOutputHBaseHFileMaxfilesize(hfileMaxfilesize);
        dbConf.setOutputHBaseMemstoreFlushSize(memstoreFlushSize);
        dbConf.setOutputHBaseIsDeferredLogFlush(isDeferredLogFlush);

        dbConf.setOutputHBaseColmunCompressionType(colmunCompressionType);
        dbConf.setOutputHBaseColmunCompactionCompressionType(colmunCompactionCompressionType);
        dbConf.setOutputHBaseColmunBlocksize(colmunBlocksize);
        dbConf.setOutputHBaseColmunMaxversion(colmunMaxversion);
        dbConf.setOutputHBaseColmunMinversion(colmunMinversion);
        dbConf.setOutputHBaseBloomFilterType(bloomType);
        dbConf.setOutputHBaseSetInMemory(inMemory);
        dbConf.setOutputHBaseBufferLength(commitBufferLength);

        // 
        if (!validateTable(dbConf)) {
            String errorInfo = "HBase output table, validate Execption!";
            MRLog.error(LOG, errorInfo);
            throw new Exception(errorInfo);
        }

        // ??
        printTableDesc(tableName, dbConf.getConf());
        return dbConf;
    }

    /**
     * ?hbase?
     * 
     * @param job
     *            ?
     * @param tableName
     *            ??
     * @param colmunCompressionType
     *            
     * @param colmunCompactionCompressionType
     *            ?
     * @param colmunBlocksize
     *            ??
     * @param colmunMaxversion
     *            
     * @param colmunMinversion
     *            ?
     * @param bloomType
     *            
     * @param inMemory
     *            ?
     * @param familyColumnName
     *            ???
     * @return HbaseConfiguration HBase?
     * @throws Exception
     *             
     */
    public static HbaseConfiguration setOutput(Job job, String tableName, int colmunCompressionType,
            int colmunCompactionCompressionType, int colmunBlocksize, int colmunMaxversion, int colmunMinversion,
            int bloomType, boolean inMemory, String familyColumnName) throws Exception {
        HbaseConfiguration dbConf = setOutput(job, tableName);
        if (null != familyColumnName) {
            String familyColumnNames[] = familyColumnName.split(",");
            // family
            List<String> lstFamily = new ArrayList<String>();
            for (int i = 0; i < familyColumnNames.length; i++) {
                if (null == familyColumnNames[i]) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                String temp[] = familyColumnNames[i].split(HbaseConfiguration.sign_colon);
                if (temp.length != 2 || temp[0].trim().length() <= 0 || temp[1].trim().length() <= 0) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                if (!lstFamily.contains(temp[0])) {
                    lstFamily.add(temp[0]);
                }
            }

            dbConf.setOutputHBaseFamilyNames(lstFamily.toArray(new String[0]));
            dbConf.setOutputHBaseFieldNames(familyColumnName);
        }

        dbConf.setOutputHBaseColmunCompressionType(colmunCompressionType);
        dbConf.setOutputHBaseColmunCompactionCompressionType(colmunCompactionCompressionType);
        dbConf.setOutputHBaseColmunBlocksize(colmunBlocksize);
        dbConf.setOutputHBaseColmunMaxversion(colmunMaxversion);
        dbConf.setOutputHBaseColmunMinversion(colmunMinversion);
        dbConf.setOutputHBaseBloomFilterType(bloomType);
        dbConf.setOutputHBaseSetInMemory(inMemory);

        // 
        if (validateTable(dbConf)) {
            String errorInfo = "validateTable Execption!";
            MRLog.error(LOG, errorInfo);
            throw new Exception(errorInfo);
        }

        return dbConf;
    }

    /**
     * format?
     * 
     * @param job
     *            ?
     * @param tableName
     *            ??
     * @return HbaseConfiguration HBase?
     * @throws IOException
     *             IO
     */
    public static HbaseConfiguration setOutput(Job job, String tableName) {
        job.setOutputFormatClass(HbaseOutputFormat.class);
        job.setReduceSpeculativeExecution(false);
        HbaseConfiguration dbConf = new HbaseConfiguration(job.getConfiguration(),
                HbaseConfiguration.FLAG_HBASE_OUTPUT);
        dbConf.setOutputHBaseTableName(tableName);
        return dbConf;
    }

    /**
     * ??
     * 
     * @param tableName
     *            ??
     * @param conf
     *            ?
     * @throws TableNotFoundException
     *             ?
     * @throws IOException
     *             IO
     */
    public static void printTableDesc(String tableName, Configuration conf)
            throws TableNotFoundException, IOException {
        HBaseAdmin admin = new HBaseAdmin(conf);
        HTableDescriptor tableDes = admin.getTableDescriptor(Bytes.toBytes(tableName));

        // table
        StringBuilder s = new StringBuilder();
        Map<ImmutableBytesWritable, ImmutableBytesWritable> values = tableDes.getValues();
        for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : values.entrySet()) {
            String key = Bytes.toString(e.getKey().get());
            String value = Bytes.toString(e.getValue().get());
            s.append(", ");
            s.append(key);
            s.append(" => '");
            s.append(value);
            s.append("'");
        }
        MRLog.info(LOG, "TableName:" + tableName + ",:" + s.toString());

        // ??
        HColumnDescriptor hColumnDescriptor[] = tableDes.getColumnFamilies();
        for (HColumnDescriptor hcd : hColumnDescriptor) {
            MRLog.info(LOG, "?:" + hcd.toString());
        }
    }

    @Override
    public void checkOutputSpecs(JobContext context) throws IOException, InterruptedException {
        // TODO Auto-generated method stub

    }

    @Override
    public void handle(Job conf) throws Exception {
        HbaseConfiguration hConf = new HbaseConfiguration(conf.getConfiguration(),
                HbaseConfiguration.FLAG_HBASE_OUTPUT);

        // ??
        String tableName = hConf.getOutputHBaseTableName();
        if (null == tableName || tableName.trim().length() <= 0) {
            String meg = "HBase??<" + HbaseConfiguration.OUTPUT_TABLE + ">?.";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ?
        String hbaseFieldNames = hConf.getOutputHBaseFieldNames();
        this.vParamTargetFamilyNames(hbaseFieldNames, hConf);
        hConf.setOutputHBaseFamilyNames(this.getHBaseFamilyNames(hbaseFieldNames));

        // 
        String rowKeyRule = hConf.getOutputHBaseRowKeyRule();
        if (null == rowKeyRule || rowKeyRule.trim().length() <= 0) {
            String meg = "<" + HbaseConfiguration.OUTPUT_ROWKEY_RULE + ">";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // HFile
        long hfileMaxfilesize = hConf.getOutputHBaseHFileMaxfilesize();
        if (hfileMaxfilesize <= 0) {
            String meg = "HFile<" + HbaseConfiguration.OUTPUT_HFILE_MAXFILESIZE + ">0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // memstore flushHDFS?
        long memstoreFlushSize = hConf.getOutputHBaseMemstoreFlushSize();
        if (memstoreFlushSize <= 0) {
            String meg = "memstore flushHDFS?<"
                    + HbaseConfiguration.OUTPUT_MEMSTORE_FLUSHSIZE + ">??0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ??
        int colmunBlocksize = hConf.getOutputHBaseColmunBlocksize();
        if (colmunBlocksize <= 0) {
            String meg = "??<" + HbaseConfiguration.OUTPUT_COLMUN_BLOCKSIZE + ">0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ?
        int colmunMaxversion = hConf.getOutputHBaseColmunMaxversion();
        if (colmunMaxversion <= 0) {
            String meg = "?<" + HbaseConfiguration.OUTPUT_COLMUN_MAXVERSION + ">0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ??
        int colmunMinversion = hConf.getOutputHBaseColmunMinversion();
        if (colmunMinversion <= 0) {
            String meg = "??<" + HbaseConfiguration.OUTPUT_COLMUN_MINVERSION + ">0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ????
        int commitBufferLength = hConf.getOutputHBaseBufferLength();
        if (commitBufferLength <= 0) {
            String meg = "????<" + HbaseConfiguration.OUTPUT_SET_COMMIT_BUFFERLENGTH
                    + ">0";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // ?hbaseWAL
        int walFlag = hConf.getOutputHBaseSetWalFlags();
        if (!(walFlag == -1 || walFlag >= 0 || walFlag <= 4)) {
            String meg = "WAL<" + HbaseConfiguration.OUTPUT_SET_WAL_FLAG
                    + ">?-1??:[0-4]";
            LOG.error(meg);
            throw new Exception(meg);
        }

        // 
        if (!validateTable(hConf)) {
            String errorInfo = "HBase output table, validate Execption!";
            MRLog.error(LOG, errorInfo);
            throw new Exception(errorInfo);
        }

        conf.setOutputFormatClass(HbaseOutputFormat.class);
        conf.setReduceSpeculativeExecution(false);
        conf.setOutputKeyClass(DBRecord.class);
        conf.setOutputValueClass(NullWritable.class);
        conf.setReducerClass(DBReducer.class);

        // ??
        printTableDesc(tableName, hConf.getConf());
    }

    public String[] getHBaseFamilyNames(String familyColumnName) throws Exception {
        Set<String> lstFamily = new HashSet<String>();
        if (null != familyColumnName) {
            String familyColumnNames[] = familyColumnName.split(",");
            // ?family
            for (int i = 0; i < familyColumnNames.length; i++) {
                if (null == familyColumnNames[i]) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                String temp[] = familyColumnNames[i].split(HbaseConfiguration.sign_colon);
                if (temp.length != 2 || temp[0].trim().length() <= 0 || temp[1].trim().length() <= 0) {
                    String errorInfo = "Parameter Execption:" + familyColumnNames;
                    MRLog.error(LOG, errorInfo);
                    throw new Exception(errorInfo);
                }

                if (!lstFamily.contains(temp[0])) {
                    lstFamily.add(temp[0]);
                }
            }
        }

        return lstFamily.toArray(new String[0]);
    }

    /**
     * ??
     * 
     * @param hConf
     *            ?
     * @param paraMap
     *            ?
     * @throws Exception
     *             
     */
    private void vParamTargetFamilyNames(String hbaseFieldNames, HbaseConfiguration hConf) throws Exception {
        // ?
        if (null == hbaseFieldNames || hbaseFieldNames.trim().length() <= 0) {
            String meg = "[MR ERROR]?<"
                    + HbaseConfiguration.OUTPUT_COLMUN_FAMILYS_REL + ">.";
            LOG.error(meg);
            throw new Exception(meg);
        }

        String famliyNames[] = hbaseFieldNames.split(",");
        Set<String> tempVar = new HashSet<String>();
        for (String fn : famliyNames) {
            String fc[] = fn.split(":");
            if (tempVar.contains(fn)) {
                String meg = "[MR ERROR]?<"
                        + HbaseConfiguration.OUTPUT_COLMUN_FAMILYS_REL + ">.???";
                LOG.error(meg);
                throw new Exception(meg);
            }

            tempVar.add(fn);
            if (fc.length != 2 || fc[0].trim().length() <= 0 || fc[1].trim().length() <= 0) {
                String meg = "[MR ERROR]?<"
                        + HbaseConfiguration.OUTPUT_COLMUN_FAMILYS_REL + ">.";
                LOG.error(meg);
                throw new Exception(meg);
            }
        }

        // ??
        String outColumnRelation = hConf.getOutputHBaseColumnRelation();
        if (null == outColumnRelation) {
            String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION
                    + ">?";
            MRLog.error(LOG, meg);
            throw new Exception(meg);
        }

        List<String[]> list = new ArrayList<String[]>();// ?
        List<String[]> rela = new ArrayList<String[]>();
        StringUtil.decodeOutColumnSplitRelation(outColumnRelation, list, rela);
        String[][] clusterFieldNames = list.toArray(new String[0][0]);
        String[][] outColumnSplitRelations = rela.toArray(new String[0][0]);
        if (clusterFieldNames.length <= 0 || outColumnSplitRelations.length <= 0) {
            String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION + ">?";
            MRLog.error(LOG, meg);
            throw new Exception(meg);
        }

        // ?
        for (int i = 0; i < clusterFieldNames.length; i++) {
            String tmp = clusterFieldNames[i][0] + ":" + clusterFieldNames[i][1];
            if (!tempVar.contains(tmp)) {
                String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION
                        + ">?<" + HbaseConfiguration.OUTPUT_COLMUN_FAMILYS_REL + ">";
                LOG.error(meg);
                throw new Exception(meg);
            }
        }

        // ?
        String splitSign = hConf.getOutputHBaseColumnSplitSign();
        Set<String> setTargetFiled = StringUtil.parseStringArrayToSet(hConf.getOutputFieldNames());
        for (int i = 0; i < outColumnSplitRelations.length; i++) {
            String temp[] = outColumnSplitRelations[i];
            for (int j = 0; j < temp.length; j++) {
                if (!setTargetFiled.contains(temp[j])) {
                    String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION
                            + ">?<"
                            + HbaseConfiguration.SYS_OUTPUT_FIELD_NAMES_PROPERTY + ">";
                    LOG.error(meg);
                    throw new Exception(meg);
                }
            }

            if (temp.length <= 0) {
                String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION
                        + ">??";
                LOG.error(meg);
                throw new Exception(meg);
            }

            if (temp.length > 1 && (null == splitSign || splitSign.trim().length() <= 0)) {
                String meg = "[MR ERROR]<" + HbaseConfiguration.OUTPUT_HBASE_COLUMN_RELATION
                        + ">?1, ?<"
                        + HbaseConfiguration.OUTPUT_HBASE_COLUMN_SPLIT_SIGN + ">";
                LOG.error(meg);
                throw new Exception(meg);
            }
        }
    }

    OutputCommitter committer = null;

    @Override
    public OutputCommitter getOutputCommitter(TaskAttemptContext context) throws IOException, InterruptedException {
        if (committer == null) {
            committer = new TableOutputCommitter();
        }
        return committer;
    }
}