001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.util.hbck;
019
020import java.io.IOException;
021
022import org.apache.commons.lang3.StringUtils;
023import org.apache.yetus.audience.InterfaceAudience;
024import org.apache.yetus.audience.InterfaceStability;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027import org.apache.hadoop.conf.Configuration;
028import org.apache.hadoop.fs.Path;
029import org.apache.hadoop.hbase.HBaseConfiguration;
030import org.apache.hadoop.hbase.HBaseInterfaceAudience;
031import org.apache.hadoop.hbase.util.FSUtils;
032import org.apache.hadoop.hbase.util.HBaseFsck;
033import org.apache.hadoop.io.MultipleIOException;
034
035/**
036 * This code is used to rebuild meta off line from file system data. If there
037 * are any problem detected, it will fail suggesting actions for the user to do
038 * to "fix" problems. If it succeeds, it will backup the previous hbase:meta and
039 * -ROOT- dirs and write new tables in place.
040 *
041 * This is an advanced feature, so is only exposed for use if explicitly
042 * mentioned.
043 *
044 * hbase org.apache.hadoop.hbase.util.hbck.OfflineMetaRepair ...
045 */
046@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
047@InterfaceStability.Evolving
048public class OfflineMetaRepair {
049  private static final Logger LOG = LoggerFactory.getLogger(OfflineMetaRepair.class.getName());
050
051  protected static void printUsageAndExit() {
052    StringBuilder sb = new StringBuilder();
053    sb.append("Usage: OfflineMetaRepair [opts]\n").
054       append(" where [opts] are:\n").
055       append("   -details               Display full report of all regions.\n").
056       append("   -base <hdfs://>        Base Hbase Data directory.\n").
057       append("   -sidelineDir <hdfs://> HDFS path to backup existing meta and root.\n").
058       append("   -fix                   Auto fix as many problems as possible.\n").
059       append("   -fixHoles              Auto fix as region holes.");
060    System.err.println(sb.toString());
061    Runtime.getRuntime().exit(-2);
062  }
063
064  /**
065   * Main program
066   *
067   * @param args
068   * @throws Exception
069   */
070  public static void main(String[] args) throws Exception {
071
072    // create a fsck object
073    Configuration conf = HBaseConfiguration.create();
074    // Cover both bases, the old way of setting default fs and the new.
075    // We're supposed to run on 0.20 and 0.21 anyways.
076    FSUtils.setFsDefault(conf, FSUtils.getRootDir(conf));
077    HBaseFsck fsck = new HBaseFsck(conf);
078    boolean fixHoles = false;
079
080    // Process command-line args.
081    for (int i = 0; i < args.length; i++) {
082      String cmd = args[i];
083      if (cmd.equals("-details")) {
084        HBaseFsck.setDisplayFullReport();
085      } else if (cmd.equals("-base")) {
086        if (i == args.length - 1) {
087          System.err.println("OfflineMetaRepair: -base needs an HDFS path.");
088          printUsageAndExit();
089        }
090        // update hbase root dir to user-specified base
091        i++;
092        FSUtils.setRootDir(conf, new Path(args[i]));
093        FSUtils.setFsDefault(conf, FSUtils.getRootDir(conf));
094      } else if (cmd.equals("-sidelineDir")) {
095        if (i == args.length - 1) {
096          System.err.println("OfflineMetaRepair: -sidelineDir needs an HDFS path.");
097          printUsageAndExit();
098        }
099        // set the hbck sideline dir to user-specified one
100        i++;
101        fsck.setSidelineDir(args[i]);
102      } else if (cmd.equals("-fixHoles")) {
103        fixHoles = true;
104      } else if (cmd.equals("-fix")) {
105        // make all fix options true
106        fixHoles = true;
107      } else {
108        String str = "Unknown command line option : " + cmd;
109        LOG.info(str);
110        System.out.println(str);
111        printUsageAndExit();
112      }
113    }
114
115    System.out.println("OfflineMetaRepair command line options: " + StringUtils.join(args, " "));
116
117    // Fsck doesn't shutdown and and doesn't provide a way to shutdown its
118    // threads cleanly, so we do a System.exit.
119    boolean success = false;
120    try {
121      success = fsck.rebuildMeta(fixHoles);
122    } catch (MultipleIOException mioes) {
123      for (IOException ioe : mioes.getExceptions()) {
124        LOG.error("Bailed out due to:", ioe);
125      }
126    } catch (Exception e) {
127      LOG.error("Bailed out due to: ", e);
128    } finally {
129      System.exit(success ? 0 : 1);
130    }
131  }
132}