commit 6d82a2d4ce92b036e1693e96bdc1dde798145f20 Author: Todd Lipcon Date: Thu Dec 30 18:14:25 2010 -0800 hbck to fix case where region is on fs but not in META TODO: should double-check that there is in fact a hole in META at this range! diff --git src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java index bf5c663..b8fdab3 100644 --- src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java +++ src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java @@ -419,6 +419,11 @@ public class HBaseFsck { } else if (!inMeta && inHdfs && !isDeployed) { errors.reportError("Region " + descriptiveName + " on HDFS, but not listed in META " + "or deployed on any region server."); + if (shouldFix()) { + errors.print("Trying to fix region missing from META..."); + setShouldRerun(); + HBaseFsckRepair.fixMissingFromMeta(this.conf, hbi.foundRegionDir.getPath()); + } } else if (!inMeta && inHdfs && isDeployed) { errors.reportError("Region " + descriptiveName + " not in META, but deployed on " + Joiner.on(", ").join(hbi.deployedOn)); diff --git src/main/java/org/apache/hadoop/hbase/util/HBaseFsckRepair.java src/main/java/org/apache/hadoop/hbase/util/HBaseFsckRepair.java index b624d28..fc434e6 100644 --- src/main/java/org/apache/hadoop/hbase/util/HBaseFsckRepair.java +++ src/main/java/org/apache/hadoop/hbase/util/HBaseFsckRepair.java @@ -23,13 +23,20 @@ import java.io.IOException; import java.util.List; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.FSDataInputStream; +import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HServerAddress; import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.ZooKeeperConnectionException; +import org.apache.hadoop.hbase.catalog.CatalogTracker; +import org.apache.hadoop.hbase.catalog.MetaEditor; +import org.apache.hadoop.hbase.client.HConnection; import org.apache.hadoop.hbase.client.HConnectionManager; import org.apache.hadoop.hbase.ipc.HRegionInterface; +import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.zookeeper.ZKAssign; import org.apache.zookeeper.KeeperException; @@ -78,6 +85,47 @@ public class HBaseFsckRepair { forceOfflineInZK(conf, actualRegion); } + /** + * Fix the case where a region is on the filesystem but not in META. + * This is done by reading the regioninfo off the filesystem and inserting + * into META, then creating an offline node in ZK. + */ + public static void fixMissingFromMeta(Configuration conf, Path regionDir) + throws IOException, KeeperException { + HRegionInfo hri = readRegionInfo(conf, regionDir); + + HConnection conn = HConnectionManager.getConnection(conf); + CatalogTracker tracker = new CatalogTracker(conn); + try { + tracker.start(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new IOException(ie); + } + try { + MetaEditor.updateRegionInfo(tracker, hri); + } finally { + tracker.stop(); + } + } + + private static HRegionInfo readRegionInfo(Configuration conf, Path regionDir) + throws IOException { + FileSystem fs = regionDir.getFileSystem(conf); + Path hriFile = new Path(regionDir, HRegion.REGIONINFO_FILE); + if (!fs.exists(hriFile)) { + throw new IOException("Unable to repair, no regioninfo file at " + hriFile); + } + FSDataInputStream fsi = fs.open(hriFile); + try { + HRegionInfo hri = new HRegionInfo(); + hri.readFields(fsi); + return hri; + } finally { + fsi.close(); + } + } + private static void forceOfflineInZK(Configuration conf, HRegionInfo region) throws ZooKeeperConnectionException, KeeperException, IOException { ZKAssign.createOrForceNodeOffline( @@ -105,4 +153,4 @@ public class HBaseFsckRepair { throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout); } -} \ No newline at end of file +}