diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateClientSideReader.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateClientSideReader.java index 03579ff..943b79d 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateClientSideReader.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateClientSideReader.java @@ -139,6 +139,19 @@ public class ZKTableStateClientSideReader { } /** + * Gets a list of all the tables set as enabling or enabled in zookeeper. + * @param zkw ZooKeeperWatcher instance to use + * @return Set of enabling / enabled tables, empty Set if none + * @throws KeeperException + * @throws InterruptedException + */ + public static Set getEnablingAndEnabledTables(ZooKeeperWatcher zkw) + throws KeeperException, InterruptedException { + return getTablesInStates(zkw, ZooKeeperProtos.Table.State.ENABLING, + ZooKeeperProtos.Table.State.ENABLED); + } + + /** * Gets a list of tables that are set as one of the passing in states in zookeeper. * @param zkw ZooKeeperWatcher instance to use * @param states the list of states that a table could be in diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java index e5e4b5a..03be69a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java @@ -3542,11 +3542,12 @@ public class HBaseFsck extends Configured implements Closeable { */ private void checkAndFixOrphanedTableZNodes() throws IOException, KeeperException, InterruptedException { - Set enablingTables = ZKTableStateClientSideReader.getEnablingTables(zkw); + Set enablingAndEnabledTables = + ZKTableStateClientSideReader.getEnablingAndEnabledTables(zkw); String msg; TableInfo tableInfo; - for (TableName tableName : enablingTables) { + for (TableName tableName : enablingAndEnabledTables) { // Check whether the table exists in hbase tableInfo = tablesInfo.get(tableName); if (tableInfo != null) { @@ -3573,8 +3574,8 @@ public class HBaseFsck extends Configured implements Closeable { } catch (CoordinatedStateException e) { // This exception should not happen here LOG.error( - "Got a CoordinatedStateException while fixing the ENABLING table znode " + tableName, - e); + "Got a CoordinatedStateException while fixing the ENABLING/ ENABLED table znode " + + tableName, e); } } } @@ -3703,7 +3704,7 @@ public class HBaseFsck extends Configured implements Closeable { } HRegionInfo hri = rl.getRegionLocation(HRegionInfo.DEFAULT_REPLICA_ID).getRegionInfo(); if (!(isTableIncluded(hri.getTable()) - || hri.isMetaRegion())) { + || hri.isSystemTable())) { return true; } PairOfSameType daughters = HRegionInfo.getDaughterRegions(result); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java index f1dc1a2..3387e07 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestHBaseFsck.java @@ -246,60 +246,63 @@ public class TestHBaseFsck { // We created 1 table, should be fine assertNoErrors(doFsck(conf, false)); - - // Now let's mess it up and change the assignment in hbase:meta to - // point to a different region server - Table meta = connection.getTable(TableName.META_TABLE_NAME, tableExecutorService); - Scan scan = new Scan(); - scan.setStartRow(Bytes.toBytes(table+",,")); - ResultScanner scanner = meta.getScanner(scan); - HRegionInfo hri = null; - - Result res = scanner.next(); - ServerName currServer = - ServerName.parseFrom(res.getValue(HConstants.CATALOG_FAMILY, - HConstants.SERVER_QUALIFIER)); - long startCode = Bytes.toLong(res.getValue(HConstants.CATALOG_FAMILY, + try { + // Now let's mess it up and change the assignment in hbase:meta to + // point to a different region server + Table meta = connection.getTable(TableName.META_TABLE_NAME, tableExecutorService); + Scan scan = new Scan(); + scan.setStartRow(Bytes.toBytes(table+",,")); + ResultScanner scanner = meta.getScanner(scan); + HRegionInfo hri = null; + + Result res = scanner.next(); + ServerName currServer = + ServerName.parseFrom(res.getValue(HConstants.CATALOG_FAMILY, + HConstants.SERVER_QUALIFIER)); + long startCode = Bytes.toLong(res.getValue(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER)); - for (JVMClusterUtil.RegionServerThread rs : + for (JVMClusterUtil.RegionServerThread rs : TEST_UTIL.getHBaseCluster().getRegionServerThreads()) { - ServerName sn = rs.getRegionServer().getServerName(); - - // When we find a diff RS, change the assignment and break - if (!currServer.getHostAndPort().equals(sn.getHostAndPort()) || - startCode != sn.getStartcode()) { - Put put = new Put(res.getRow()); - put.setDurability(Durability.SKIP_WAL); - put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER, - Bytes.toBytes(sn.getHostAndPort())); - put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER, - Bytes.toBytes(sn.getStartcode())); - meta.put(put); - hri = MetaTableAccessor.getHRegionInfo(res); - break; + ServerName sn = rs.getRegionServer().getServerName(); + + // When we find a diff RS, change the assignment and break + if (!currServer.getHostAndPort().equals(sn.getHostAndPort()) || + startCode != sn.getStartcode()) { + Put put = new Put(res.getRow()); + put.setDurability(Durability.SKIP_WAL); + put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER, + Bytes.toBytes(sn.getHostAndPort())); + put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER, + Bytes.toBytes(sn.getStartcode())); + meta.put(put); + hri = MetaTableAccessor.getHRegionInfo(res); + break; + } } - } - // Try to fix the data - assertErrors(doFsck(conf, true), new ERROR_CODE[]{ + // Try to fix the data + assertErrors(doFsck(conf, true), new ERROR_CODE[]{ ERROR_CODE.SERVER_DOES_NOT_MATCH_META}); - TEST_UTIL.getHBaseCluster().getMaster() + TEST_UTIL.getHBaseCluster().getMaster() .getAssignmentManager().waitForAssignment(hri); - // Should be fixed now - assertNoErrors(doFsck(conf, false)); + // Should be fixed now + assertNoErrors(doFsck(conf, false)); - // comment needed - what is the purpose of this line - Table t = connection.getTable(table, tableExecutorService); - ResultScanner s = t.getScanner(new Scan()); - s.close(); - t.close(); + // comment needed - what is the purpose of this line + Table t = connection.getTable(table, tableExecutorService); + ResultScanner s = t.getScanner(new Scan()); + s.close(); + t.close(); - scanner.close(); - meta.close(); + scanner.close(); + meta.close(); + } finally { + cleanupTable(table); + } } @Test(timeout=180000) @@ -1655,38 +1658,42 @@ public class TestHBaseFsck { @Test (timeout=180000) public void testNoHdfsTable() throws Exception { TableName table = TableName.valueOf("NoHdfsTable"); - setupTable(table); - assertEquals(ROWKEYS.length, countRows()); + try { + setupTable(table); + assertEquals(ROWKEYS.length, countRows()); - // make sure data in regions, if in wal only there is no data loss - admin.flush(table); + // make sure data in regions, if in wal only there is no data loss + admin.flush(table); - // Mess it up by deleting hdfs dirs - deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes(""), + // Mess it up by deleting hdfs dirs + deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes(""), Bytes.toBytes("A"), false, false, true); // don't rm meta - deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("A"), + deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("A"), Bytes.toBytes("B"), false, false, true); // don't rm meta - deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("B"), + deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("B"), Bytes.toBytes("C"), false, false, true); // don't rm meta - deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("C"), + deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("C"), Bytes.toBytes(""), false, false, true); // don't rm meta - // also remove the table directory in hdfs - deleteTableDir(table); + // also remove the table directory in hdfs + deleteTableDir(table); - HBaseFsck hbck = doFsck(conf, false); - assertErrors(hbck, new ERROR_CODE[] {ERROR_CODE.NOT_IN_HDFS, - ERROR_CODE.NOT_IN_HDFS, ERROR_CODE.NOT_IN_HDFS, - ERROR_CODE.NOT_IN_HDFS,}); - // holes are separate from overlap groups - assertEquals(0, hbck.getOverlapGroups(table).size()); + HBaseFsck hbck = doFsck(conf, false); + assertErrors(hbck, new ERROR_CODE[] {ERROR_CODE.NOT_IN_HDFS, + ERROR_CODE.NOT_IN_HDFS, ERROR_CODE.NOT_IN_HDFS, + ERROR_CODE.NOT_IN_HDFS,}); + // holes are separate from overlap groups + assertEquals(0, hbck.getOverlapGroups(table).size()); - // fix hole - doFsck(conf, true); // detect dangling regions and remove those + // fix hole + doFsck(conf, true); // detect dangling regions and remove those - // check that hole fixed - assertNoErrors(doFsck(conf,false)); - assertFalse("Table " + table + " should have been deleted", admin.tableExists(table)); + // check that hole fixed + assertNoErrors(doFsck(conf,false)); + assertFalse("Table " + table + " should have been deleted", admin.tableExists(table)); + } finally { + cleanupTable(table); + } } public void deleteTableDir(TableName table) throws IOException { @@ -2882,11 +2889,17 @@ public class TestHBaseFsck { */ @Test public void testOrphanedTableZNode() throws Exception { - TableName table = TableName.valueOf("testOrphanedZKTableEntry"); + testOrphanedTableZNode(ZooKeeperProtos.Table.State.ENABLING); + testOrphanedTableZNode(ZooKeeperProtos.Table.State.ENABLED); + } + + public void testOrphanedTableZNode(ZooKeeperProtos.Table.State state) throws Exception { + String tablename = "testOrphanedZKTableEntryIn" + state; + TableName table = TableName.valueOf(tablename); try { TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getTableStateManager() - .setTableState(table, ZooKeeperProtos.Table.State.ENABLING); + .setTableState(table, state); try { setupTable(table);