001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.tool; 020 021import java.io.IOException; 022import java.util.Collection; 023import java.util.List; 024import java.util.concurrent.ExecutorService; 025import java.util.concurrent.Executors; 026import java.util.concurrent.TimeUnit; 027 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.fs.FileSystem; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.HBaseInterfaceAudience; 032import org.apache.hadoop.hbase.HConstants; 033import org.apache.hadoop.hbase.util.AbstractHBaseTool; 034import org.apache.hadoop.hbase.util.FSUtils; 035import org.apache.hadoop.hbase.util.Threads; 036import org.apache.hadoop.hbase.util.hbck.HFileCorruptionChecker; 037import org.apache.yetus.audience.InterfaceAudience; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine; 042 043@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 044public class HFileContentValidator extends AbstractHBaseTool { 045 046 private static final Logger LOG = LoggerFactory.getLogger(HFileContentValidator.class); 047 048 /** 049 * Check HFile contents are readable by HBase 2. 050 * 051 * @param conf used configuration 052 * @return number of HFiles corrupted HBase 053 * @throws IOException if a remote or network exception occurs 054 */ 055 private boolean validateHFileContent(Configuration conf) throws IOException { 056 FileSystem fileSystem = FSUtils.getCurrentFileSystem(conf); 057 058 ExecutorService threadPool = createThreadPool(conf); 059 HFileCorruptionChecker checker; 060 061 try { 062 checker = new HFileCorruptionChecker(conf, threadPool, false); 063 064 Path rootDir = FSUtils.getRootDir(conf); 065 LOG.info("Validating HFile contents under {}", rootDir); 066 067 Collection<Path> tableDirs = FSUtils.getTableDirs(fileSystem, rootDir); 068 checker.checkTables(tableDirs); 069 070 Path archiveRootDir = new Path(rootDir, HConstants.HFILE_ARCHIVE_DIRECTORY); 071 LOG.info("Validating HFile contents under {}", archiveRootDir); 072 073 List<Path> archiveTableDirs = FSUtils.getTableDirs(fileSystem, archiveRootDir); 074 checker.checkTables(archiveTableDirs); 075 } finally { 076 threadPool.shutdown(); 077 078 try { 079 threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); 080 } catch (InterruptedException e) { 081 Thread.currentThread().interrupt(); 082 } 083 } 084 085 int checkedFiles = checker.getHFilesChecked(); 086 Collection<Path> corrupted = checker.getCorrupted(); 087 088 if (corrupted.isEmpty()) { 089 LOG.info("Checked {} HFiles, none of them are corrupted.", checkedFiles); 090 LOG.info("There are no incompatible HFiles."); 091 092 return true; 093 } else { 094 LOG.info("Checked {} HFiles, {} are corrupted.", checkedFiles, corrupted.size()); 095 096 for (Path path : corrupted) { 097 LOG.info("Corrupted file: {}", path); 098 } 099 100 LOG.info("Change data block encodings before upgrading. " 101 + "Check https://s.apache.org/prefixtree for instructions."); 102 103 return false; 104 } 105 } 106 107 private ExecutorService createThreadPool(Configuration conf) { 108 int availableProcessors = Runtime.getRuntime().availableProcessors(); 109 int numThreads = conf.getInt("hfilevalidator.numthreads", availableProcessors); 110 return Executors.newFixedThreadPool(numThreads, 111 Threads.newDaemonThreadFactory("hfile-validator")); 112 } 113 114 @Override 115 protected void addOptions() { 116 } 117 118 @Override 119 protected void processOptions(CommandLine cmd) { 120 } 121 122 @Override 123 protected int doWork() throws Exception { 124 return (validateHFileContent(getConf())) ? EXIT_SUCCESS : EXIT_FAILURE; 125 } 126}