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.tool; 019 020import java.io.IOException; 021import java.util.Collection; 022import java.util.List; 023import java.util.concurrent.ExecutorService; 024import java.util.concurrent.Executors; 025import java.util.concurrent.TimeUnit; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.fs.Path; 029import org.apache.hadoop.hbase.HBaseInterfaceAudience; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.util.AbstractHBaseTool; 032import org.apache.hadoop.hbase.util.CommonFSUtils; 033import org.apache.hadoop.hbase.util.FSUtils; 034import org.apache.hadoop.hbase.util.Threads; 035import org.apache.hadoop.hbase.util.hbck.HFileCorruptionChecker; 036import org.apache.yetus.audience.InterfaceAudience; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040import org.apache.hbase.thirdparty.com.google.common.util.concurrent.ThreadFactoryBuilder; 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 * @param conf used configuration 051 * @return number of HFiles corrupted HBase 052 * @throws IOException if a remote or network exception occurs 053 */ 054 private boolean validateHFileContent(Configuration conf) throws IOException { 055 FileSystem fileSystem = CommonFSUtils.getCurrentFileSystem(conf); 056 057 ExecutorService threadPool = createThreadPool(conf); 058 HFileCorruptionChecker checker; 059 060 try { 061 checker = new HFileCorruptionChecker(conf, threadPool, false); 062 063 Path rootDir = CommonFSUtils.getRootDir(conf); 064 LOG.info("Validating HFile contents under {}", rootDir); 065 066 Collection<Path> tableDirs = FSUtils.getTableDirs(fileSystem, rootDir); 067 checker.checkTables(tableDirs); 068 069 Path archiveRootDir = new Path(rootDir, HConstants.HFILE_ARCHIVE_DIRECTORY); 070 LOG.info("Validating HFile contents under {}", archiveRootDir); 071 072 List<Path> archiveTableDirs = FSUtils.getTableDirs(fileSystem, archiveRootDir); 073 checker.checkTables(archiveTableDirs); 074 } finally { 075 threadPool.shutdown(); 076 077 try { 078 threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); 079 } catch (InterruptedException e) { 080 Thread.currentThread().interrupt(); 081 } 082 } 083 084 int checkedFiles = checker.getHFilesChecked(); 085 Collection<Path> corrupted = checker.getCorrupted(); 086 087 if (corrupted.isEmpty()) { 088 LOG.info("Checked {} HFiles, none of them are corrupted.", checkedFiles); 089 LOG.info("There are no incompatible HFiles."); 090 091 return true; 092 } else { 093 LOG.info("Checked {} HFiles, {} are corrupted.", checkedFiles, corrupted.size()); 094 095 for (Path path : corrupted) { 096 LOG.info("Corrupted file: {}", path); 097 } 098 099 LOG.info("Change data block encodings before upgrading. " 100 + "Check https://s.apache.org/prefixtree for instructions."); 101 102 return false; 103 } 104 } 105 106 private ExecutorService createThreadPool(Configuration conf) { 107 int availableProcessors = Runtime.getRuntime().availableProcessors(); 108 int numThreads = conf.getInt("hfilevalidator.numthreads", availableProcessors); 109 return Executors.newFixedThreadPool(numThreads, 110 new ThreadFactoryBuilder().setNameFormat("hfile-validator-pool-%d").setDaemon(true) 111 .setUncaughtExceptionHandler(Threads.LOGGING_EXCEPTION_HANDLER).build()); 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}