org.apache.hadoop.mapred.SkipBadRecords.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.mapred.SkipBadRecords.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 org.apache.hadoop.mapred;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;

/**
 * Utility class for skip bad records functionality. It contains various 
 * settings related to skipping of bad records.
 * 
 * <p>Hadoop provides an optional mode of execution in which the bad records
 * are detected and skipped in further attempts.
 * 
 * <p>This feature can be used when map/reduce tasks crashes deterministically on 
 * certain input. This happens due to bugs in the map/reduce function. The usual
 * course would be to fix these bugs. But sometimes this is not possible; 
 * perhaps the bug is in third party libraries for which the source code is 
 * not available. Due to this, the task never reaches to completion even with 
 * multiple attempts and complete data for that task is lost.</p>
 *  
 * <p>With this feature, only a small portion of data is lost surrounding 
 * the bad record, which may be acceptable for some user applications.
 * see {@link SkipBadRecords#setMapperMaxSkipRecords(Configuration, long)}</p>
 * 
 * <p>The skipping mode gets kicked off after certain no of failures 
 * see {@link SkipBadRecords#setAttemptsToStartSkipping(Configuration, int)}</p>
 *  
 * <p>In the skipping mode, the map/reduce task maintains the record range which 
 * is getting processed at all times. Before giving the input to the
 * map/reduce function, it sends this record range to the Task tracker.
 * If task crashes, the Task tracker knows which one was the last reported
 * range. On further attempts that range get skipped.</p>
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class SkipBadRecords {

    /**
     * Special counters which are written by the application and are 
     * used by the framework for detecting bad records. For detecting bad records 
     * these counters must be incremented by the application.
     */
    public static final String COUNTER_GROUP = "SkippingTaskCounters";

    /**
     * Number of processed map records.
     * @see SkipBadRecords#getAutoIncrMapperProcCount(Configuration)
     */
    public static final String COUNTER_MAP_PROCESSED_RECORDS = "MapProcessedRecords";

    /**
     * Number of processed reduce groups.
     * @see SkipBadRecords#getAutoIncrReducerProcCount(Configuration)
     */
    public static final String COUNTER_REDUCE_PROCESSED_GROUPS = "ReduceProcessedGroups";

    private static final String ATTEMPTS_TO_START_SKIPPING = JobContext.SKIP_START_ATTEMPTS;
    private static final String AUTO_INCR_MAP_PROC_COUNT = JobContext.MAP_SKIP_INCR_PROC_COUNT;
    private static final String AUTO_INCR_REDUCE_PROC_COUNT = JobContext.REDUCE_SKIP_INCR_PROC_COUNT;
    private static final String OUT_PATH = JobContext.SKIP_OUTDIR;
    private static final String MAPPER_MAX_SKIP_RECORDS = JobContext.MAP_SKIP_MAX_RECORDS;
    private static final String REDUCER_MAX_SKIP_GROUPS = JobContext.REDUCE_SKIP_MAXGROUPS;

    /**
     * Get the number of Task attempts AFTER which skip mode 
     * will be kicked off. When skip mode is kicked off, the 
     * tasks reports the range of records which it will process 
     * next to the TaskTracker. So that on failures, TT knows which 
     * ones are possibly the bad records. On further executions, 
     * those are skipped.
     * Default value is 2.
     * 
     * @param conf the configuration
     * @return attemptsToStartSkipping no of task attempts
     */
    public static int getAttemptsToStartSkipping(Configuration conf) {
        return conf.getInt(ATTEMPTS_TO_START_SKIPPING, 2);
    }

    /**
     * Set the number of Task attempts AFTER which skip mode 
     * will be kicked off. When skip mode is kicked off, the 
     * tasks reports the range of records which it will process 
     * next to the TaskTracker. So that on failures, TT knows which 
     * ones are possibly the bad records. On further executions, 
     * those are skipped.
     * Default value is 2.
     * 
     * @param conf the configuration
     * @param attemptsToStartSkipping no of task attempts
     */
    public static void setAttemptsToStartSkipping(Configuration conf, int attemptsToStartSkipping) {
        conf.setInt(ATTEMPTS_TO_START_SKIPPING, attemptsToStartSkipping);
    }

    /**
     * Get the flag which if set to true, 
     * {@link SkipBadRecords#COUNTER_MAP_PROCESSED_RECORDS} is incremented 
     * by MapRunner after invoking the map function. This value must be set to 
     * false for applications which process the records asynchronously 
     * or buffer the input records. For example streaming. 
     * In such cases applications should increment this counter on their own.
     * Default value is true.
     * 
     * @param conf the configuration
     * @return <code>true</code> if auto increment 
     *                       {@link SkipBadRecords#COUNTER_MAP_PROCESSED_RECORDS}.
     *         <code>false</code> otherwise.
     */
    public static boolean getAutoIncrMapperProcCount(Configuration conf) {
        return conf.getBoolean(AUTO_INCR_MAP_PROC_COUNT, true);
    }

    /**
     * Set the flag which if set to true, 
     * {@link SkipBadRecords#COUNTER_MAP_PROCESSED_RECORDS} is incremented 
     * by MapRunner after invoking the map function. This value must be set to 
     * false for applications which process the records asynchronously 
     * or buffer the input records. For example streaming. 
     * In such cases applications should increment this counter on their own.
     * Default value is true.
     * 
     * @param conf the configuration
     * @param autoIncr whether to auto increment 
     *        {@link SkipBadRecords#COUNTER_MAP_PROCESSED_RECORDS}.
     */
    public static void setAutoIncrMapperProcCount(Configuration conf, boolean autoIncr) {
        conf.setBoolean(AUTO_INCR_MAP_PROC_COUNT, autoIncr);
    }

    /**
     * Get the flag which if set to true, 
     * {@link SkipBadRecords#COUNTER_REDUCE_PROCESSED_GROUPS} is incremented 
     * by framework after invoking the reduce function. This value must be set to 
     * false for applications which process the records asynchronously 
     * or buffer the input records. For example streaming. 
     * In such cases applications should increment this counter on their own.
     * Default value is true.
     * 
     * @param conf the configuration
     * @return <code>true</code> if auto increment 
     *                    {@link SkipBadRecords#COUNTER_REDUCE_PROCESSED_GROUPS}.
     *         <code>false</code> otherwise.
     */
    public static boolean getAutoIncrReducerProcCount(Configuration conf) {
        return conf.getBoolean(AUTO_INCR_REDUCE_PROC_COUNT, true);
    }

    /**
     * Set the flag which if set to true, 
     * {@link SkipBadRecords#COUNTER_REDUCE_PROCESSED_GROUPS} is incremented 
     * by framework after invoking the reduce function. This value must be set to 
     * false for applications which process the records asynchronously 
     * or buffer the input records. For example streaming. 
     * In such cases applications should increment this counter on their own.
     * Default value is true.
     * 
     * @param conf the configuration
     * @param autoIncr whether to auto increment 
     *        {@link SkipBadRecords#COUNTER_REDUCE_PROCESSED_GROUPS}.
     */
    public static void setAutoIncrReducerProcCount(Configuration conf, boolean autoIncr) {
        conf.setBoolean(AUTO_INCR_REDUCE_PROC_COUNT, autoIncr);
    }

    /**
     * Get the directory to which skipped records are written. By default it is 
     * the sub directory of the output _logs directory.
     * User can stop writing skipped records by setting the value null.
     * 
     * @param conf the configuration.
     * @return path skip output directory. Null is returned if this is not set 
     * and output directory is also not set.
     */
    public static Path getSkipOutputPath(Configuration conf) {
        String name = conf.get(OUT_PATH);
        if (name != null) {
            if ("none".equals(name)) {
                return null;
            }
            return new Path(name);
        }
        Path outPath = FileOutputFormat.getOutputPath(new JobConf(conf));
        return outPath == null ? null : new Path(outPath, "_logs" + Path.SEPARATOR + "skip");
    }

    /**
     * Set the directory to which skipped records are written. By default it is 
     * the sub directory of the output _logs directory.
     * User can stop writing skipped records by setting the value null.
     * 
     * @param conf the configuration.
     * @param path skip output directory path
     */
    public static void setSkipOutputPath(JobConf conf, Path path) {
        String pathStr = null;
        if (path == null) {
            pathStr = "none";
        } else {
            pathStr = path.toString();
        }
        conf.set(OUT_PATH, pathStr);
    }

    /**
     * Get the number of acceptable skip records surrounding the bad record PER 
     * bad record in mapper. The number includes the bad record as well.
     * To turn the feature of detection/skipping of bad records off, set the 
     * value to 0.
     * The framework tries to narrow down the skipped range by retrying  
     * until this threshold is met OR all attempts get exhausted for this task. 
     * Set the value to Long.MAX_VALUE to indicate that framework need not try to 
     * narrow down. Whatever records(depends on application) get skipped are 
     * acceptable.
     * Default value is 0.
     * 
     * @param conf the configuration
     * @return maxSkipRecs acceptable skip records.
     */
    public static long getMapperMaxSkipRecords(Configuration conf) {
        return conf.getLong(MAPPER_MAX_SKIP_RECORDS, 0);
    }

    /**
     * Set the number of acceptable skip records surrounding the bad record PER 
     * bad record in mapper. The number includes the bad record as well.
     * To turn the feature of detection/skipping of bad records off, set the 
     * value to 0.
     * The framework tries to narrow down the skipped range by retrying  
     * until this threshold is met OR all attempts get exhausted for this task. 
     * Set the value to Long.MAX_VALUE to indicate that framework need not try to 
     * narrow down. Whatever records(depends on application) get skipped are 
     * acceptable.
     * Default value is 0.
     * 
     * @param conf the configuration
     * @param maxSkipRecs acceptable skip records.
     */
    public static void setMapperMaxSkipRecords(Configuration conf, long maxSkipRecs) {
        conf.setLong(MAPPER_MAX_SKIP_RECORDS, maxSkipRecs);
    }

    /**
     * Get the number of acceptable skip groups surrounding the bad group PER 
     * bad group in reducer. The number includes the bad group as well.
     * To turn the feature of detection/skipping of bad groups off, set the 
     * value to 0.
     * The framework tries to narrow down the skipped range by retrying  
     * until this threshold is met OR all attempts get exhausted for this task. 
     * Set the value to Long.MAX_VALUE to indicate that framework need not try to 
     * narrow down. Whatever groups(depends on application) get skipped are 
     * acceptable.
     * Default value is 0.
     * 
     * @param conf the configuration
     * @return maxSkipGrps acceptable skip groups.
     */
    public static long getReducerMaxSkipGroups(Configuration conf) {
        return conf.getLong(REDUCER_MAX_SKIP_GROUPS, 0);
    }

    /**
     * Set the number of acceptable skip groups surrounding the bad group PER 
     * bad group in reducer. The number includes the bad group as well.
     * To turn the feature of detection/skipping of bad groups off, set the 
     * value to 0.
     * The framework tries to narrow down the skipped range by retrying  
     * until this threshold is met OR all attempts get exhausted for this task. 
     * Set the value to Long.MAX_VALUE to indicate that framework need not try to 
     * narrow down. Whatever groups(depends on application) get skipped are 
     * acceptable.
     * Default value is 0.
     * 
     * @param conf the configuration
     * @param maxSkipGrps acceptable skip groups.
     */
    public static void setReducerMaxSkipGroups(Configuration conf, long maxSkipGrps) {
        conf.setLong(REDUCER_MAX_SKIP_GROUPS, maxSkipGrps);
    }
}