HBASE-27147 [HBCK2] extraRegionsInMeta does not work If RegionInfo is… (#110)
Signed-off-by: Peter Somogyi <psomogyi@apache.org>
diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/FsRegionsMetaRecoverer.java b/hbase-hbck2/src/main/java/org/apache/hbase/FsRegionsMetaRecoverer.java
index e8a9df7..cbd2456 100644
--- a/hbase-hbck2/src/main/java/org/apache/hbase/FsRegionsMetaRecoverer.java
+++ b/hbase-hbck2/src/main/java/org/apache/hbase/FsRegionsMetaRecoverer.java
@@ -86,25 +86,25 @@
return missingChecker.reportTablesRegions(namespacesOrTables, this::findMissingRegionsInMETA);
}
- public Map<TableName,List<RegionInfo>>
+ public Map<TableName,List<HBCKMetaEntry>>
reportTablesExtraRegions(final List<String> namespacesOrTables) throws IOException {
- InternalMetaChecker<RegionInfo> extraChecker = new InternalMetaChecker<>();
+ InternalMetaChecker<HBCKMetaEntry> extraChecker = new InternalMetaChecker<>();
return extraChecker.reportTablesRegions(namespacesOrTables, this::findExtraRegionsInMETA);
}
List<Path> findMissingRegionsInMETA(String table) throws IOException {
InternalMetaChecker<Path> missingChecker = new InternalMetaChecker<>();
return missingChecker.checkRegionsInMETA(table, (regions, dirs) -> {
- ListUtils<Path, RegionInfo> utils = new ListUtils<>();
- return utils.complement(dirs, regions, d -> d.getName(), r -> r.getEncodedName());
+ ListUtils<Path, HBCKMetaEntry> utils = new ListUtils<>();
+ return utils.complement(dirs, regions, d -> d.getName(), r -> r.getEncodedRegionName());
});
}
- List<RegionInfo> findExtraRegionsInMETA(String table) throws IOException {
- InternalMetaChecker<RegionInfo> extraChecker = new InternalMetaChecker<>();
+ List<HBCKMetaEntry> findExtraRegionsInMETA(String table) throws IOException {
+ InternalMetaChecker<HBCKMetaEntry> extraChecker = new InternalMetaChecker<>();
return extraChecker.checkRegionsInMETA(table, (regions,dirs) -> {
- ListUtils<RegionInfo, Path> utils = new ListUtils<>();
- return utils.complement(regions, dirs, r -> r.getEncodedName(), d -> d.getName());
+ ListUtils<HBCKMetaEntry, Path> utils = new ListUtils<>();
+ return utils.complement(regions, dirs, r -> r.getEncodedRegionName(), d -> d.getName());
});
}
@@ -132,18 +132,18 @@
public List<Future<List<String>>> removeExtraRegionsFromMetaForTables(
List<String> nameSpaceOrTable) throws IOException {
if(nameSpaceOrTable.size()>0) {
- InternalMetaChecker<RegionInfo> extraChecker = new InternalMetaChecker<>();
+ InternalMetaChecker<HBCKMetaEntry> extraChecker = new InternalMetaChecker<>();
return extraChecker.processRegionsMetaCleanup(this::reportTablesExtraRegions,
this::deleteAllRegions, nameSpaceOrTable);
}
return null;
}
- private List<String> deleteAllRegions(List<RegionInfo> regions) throws IOException {
+ private List<String> deleteAllRegions(List<HBCKMetaEntry> regions) throws IOException {
List<String> resulting = new ArrayList<>();
- for(RegionInfo r : regions){
- HBCKMetaTableAccessor.deleteRegionInfo(conn, r);
- resulting.add(r.getEncodedName());
+ for(HBCKMetaEntry r : regions){
+ HBCKMetaTableAccessor.deleteRegion(conn, r);
+ resulting.add(r.getEncodedRegionName());
}
return resulting;
}
@@ -156,11 +156,11 @@
private class InternalMetaChecker<T> {
List<T> checkRegionsInMETA(String table,
- CheckingFunction<List<RegionInfo>, List<Path>, T> checkingFunction) throws IOException {
+ CheckingFunction<List<HBCKMetaEntry>, List<Path>, T> checkingFunction) throws IOException {
final List<Path> regionsDirs = getTableRegionsDirs(table);
TableName tableName = TableName.valueOf(table);
- List<RegionInfo> regions = HBCKMetaTableAccessor.
- getTableRegions(FsRegionsMetaRecoverer.this.conn, tableName);
+ List<HBCKMetaEntry> regions = HBCKMetaTableAccessor.
+ getTableRegionsAsMetaEntries(FsRegionsMetaRecoverer.this.conn, tableName);
return checkingFunction.check(regions, regionsDirs);
}
diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java b/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java
index a4e180b..ca1597d 100644
--- a/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java
+++ b/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java
@@ -344,12 +344,12 @@
new FsRegionsMetaRecoverer(this.conf)) {
List<String> namespacesTables =
getFromArgsOrFiles(commandLine.getArgList(), inputFileFlag);
- Map<TableName, List<RegionInfo>> reportMap =
+ Map<TableName, List<HBCKMetaEntry>> reportMap =
fsRegionsMetaRecoverer.reportTablesExtraRegions(namespacesTables);
final List<String> toFix = new ArrayList<>();
reportMap.entrySet().forEach(e -> {
result.put(e.getKey(),
- e.getValue().stream().map(r->r.getEncodedName()).collect(Collectors.toList()));
+ e.getValue().stream().map(r->r.getEncodedRegionName()).collect(Collectors.toList()));
if(fix && e.getValue().size()>0){
toFix.add(e.getKey().getNameWithNamespaceInclAsString());
}
diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/HBCKActions.java b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKActions.java
index a1126b6..01dc209 100644
--- a/hbase-hbck2/src/main/java/org/apache/hbase/HBCKActions.java
+++ b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKActions.java
@@ -87,7 +87,7 @@
System.out.println(String.format("Current Regions of the table " + tn.getNameAsString()
+ " in Meta before deletion of the region are: " + ris));
RegionInfo ri = ris.get(ris.size() / 2);
- System.out.println("Deleting Region " + ri.getRegionNameAsString());
+ System.out.println("Deleting Region " + ri);
byte[] key = HBCKMetaTableAccessor.getMetaKeyForRegion(ri);
Delete delete = new Delete(key);
diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaEntry.java b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaEntry.java
new file mode 100644
index 0000000..2c60139
--- /dev/null
+++ b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaEntry.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hbase;
+
+/**
+ * A conveninent representation of a row in meta, composing the encoded name and the related
+ * rowkey (region name).
+ */
+public class HBCKMetaEntry {
+
+ private String encodedRegionName;
+ private byte[] regionName;
+
+ public HBCKMetaEntry(byte[] regionName, String encodedRegionName) {
+ this.regionName = regionName;
+ this.encodedRegionName = encodedRegionName;
+ }
+
+ public byte[] getRegionName() {
+ return regionName;
+ }
+
+ public String getEncodedRegionName() {
+ return encodedRegionName;
+ }
+}
diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaTableAccessor.java b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaTableAccessor.java
index 8d50bb5..ed7e507 100644
--- a/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaTableAccessor.java
+++ b/hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaTableAccessor.java
@@ -128,13 +128,44 @@
* @throws IOException if it's not able to delete the regionInfo
*/
public static void deleteRegionInfo(Connection connection, RegionInfo regionInfo)
- throws IOException {
+ throws IOException {
Delete delete = new Delete(regionInfo.getRegionName());
delete.addFamily(HConstants.CATALOG_FAMILY, HConstants.LATEST_TIMESTAMP);
deleteFromMetaTable(connection, delete);
LOG.info("Deleted {}", regionInfo.getRegionNameAsString());
}
+ /**
+ * Delete the passed <code>RegionInfo</code> from the <code>hbase:meta</code> table.
+ *
+ * @param connection connection we're using
+ * @param regionInfo the regionInfo to delete from the meta table
+ * @throws IOException if it's not able to delete the regionInfo
+ */
+ public static void deleteRegionInfoColumn(Connection connection, RegionInfo regionInfo)
+ throws IOException {
+ Delete delete = new Delete(regionInfo.getRegionName());
+ delete.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
+ HConstants.LATEST_TIMESTAMP);
+ deleteFromMetaTable(connection, delete);
+ LOG.info("Deleted regioninfo for {}", regionInfo.getRegionNameAsString());
+ }
+
+ /**
+ * Delete the passed <code>HBCKMetaEntry</code> from the <code>hbase:meta</code> table.
+ *
+ * @param connection connection we're using
+ * @param region the region to be deleted from the meta table
+ * @throws IOException if it's not able to delete the regionInfo
+ */
+ public static void deleteRegion(Connection connection, HBCKMetaEntry region)
+ throws IOException {
+ Delete delete = new Delete(region.getRegionName());
+ delete.addFamily(HConstants.CATALOG_FAMILY, HConstants.LATEST_TIMESTAMP);
+ deleteFromMetaTable(connection, delete);
+ LOG.info("Deleted {}", region.getEncodedRegionName());
+ }
+
// Private helper methods
// COPIED from MetaTableAccessor.isMergeQualifierPrefix()
@@ -187,11 +218,49 @@
* Returns all regions in meta for the given table.
* @param conn a valid, open connection.
* @param table the table to list regions in meta.
- * @return a list of <code>RegionInfo</code> for all table regions present in meta.
+ * @return a list of <code>HBCKMetaEntry</code> with encoded region names, and the meta row key
+ * for all table regions present in meta.
+ * @throws IOException on any issues related with scanning meta table
+ * */
+ public static List<HBCKMetaEntry> getTableRegionsAsMetaEntries(final Connection conn,
+ final TableName table) throws IOException {
+ final MetaScanner<HBCKMetaEntry> scanner = new MetaScanner<>();
+ final String startRow = Bytes.toString(table.getName()) + ",,";
+ final String stopRow = Bytes.toString(table.getName()) + " ,,";
+ return scanner.scanMeta(conn,
+ scan -> {
+ scan.withStartRow(Bytes.toBytes(startRow));
+ scan.withStopRow(Bytes.toBytes(stopRow));
+ },
+ r -> {
+ if (r.getRow() != null) {
+ boolean encodedNameOffset = false;
+ StringBuilder encodedNameBuilder = new StringBuilder();
+ for(int i=0; i<r.getRow().length; i++){
+ if (r.getRow()[i]=='.'){
+ encodedNameOffset = !encodedNameOffset;
+ continue;
+ }
+ if(encodedNameOffset){
+ encodedNameBuilder.append((char)r.getRow()[i]);
+ }
+ }
+ return new HBCKMetaEntry(r.getRow(), encodedNameBuilder.toString());
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Returns all regions in meta for the given table.
+ * @param conn a valid, open connection.
+ * @param table the table to list regions in meta.
+ * @return a list of <code>String</code> of encoded region names,
+ * for all table regions present in meta.
* @throws IOException on any issues related with scanning meta table
*/
public static List<RegionInfo> getTableRegions(final Connection conn, final TableName table)
- throws IOException {
+ throws IOException {
final MetaScanner<RegionInfo> scanner = new MetaScanner<>();
final String startRow = Bytes.toString(table.getName()) + ",,";
final String stopRow = Bytes.toString(table.getName()) + " ,,";
diff --git a/hbase-hbck2/src/test/java/org/apache/hbase/TestFsRegionsMetaRecoverer.java b/hbase-hbck2/src/test/java/org/apache/hbase/TestFsRegionsMetaRecoverer.java
index 2093996..68101a6 100644
--- a/hbase-hbck2/src/test/java/org/apache/hbase/TestFsRegionsMetaRecoverer.java
+++ b/hbase-hbck2/src/test/java/org/apache/hbase/TestFsRegionsMetaRecoverer.java
@@ -210,10 +210,10 @@
@Test
public void testFindExtraRegionsInMETAOneExtra() throws Exception {
RegionInfo info = createRegionInMeta(Mockito.mock(ResultScanner.class));
- List<RegionInfo> missingRegions = fixer.findExtraRegionsInMETA("test-tbl");
+ List<HBCKMetaEntry> missingRegions = fixer.findExtraRegionsInMETA("test-tbl");
assertEquals("Should had returned 1 extra region",
1, missingRegions.size());
- assertEquals(info.getEncodedName(),missingRegions.get(0).getEncodedName());
+ assertEquals(info.getEncodedName(),missingRegions.get(0).getEncodedRegionName());
}
@Test
@@ -243,7 +243,7 @@
cells.add(createCellForTableState(TableName.valueOf("test-tbl")));
Result result = Result.create(cells);
Mockito.when(mockedRS.next()).thenReturn(result,(Result)null);
- Map<TableName, List<RegionInfo>> report = fixer.reportTablesExtraRegions(null);
+ Map<TableName, List<HBCKMetaEntry>> report = fixer.reportTablesExtraRegions(null);
assertEquals("Should had returned 1 extra region.",
1,report.size());
}
diff --git a/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java b/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java
index 09f9559..e795650 100644
--- a/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java
+++ b/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java
@@ -696,6 +696,20 @@
}
}
+ @Test
+ public void testRemoveExtraRegionWithoutInfo() throws Exception {
+ TableName tableName = createTestTable(5);
+ HBCK2 hbck = new HBCK2(TEST_UTIL.getConfiguration());
+ List<RegionInfo> regions = HBCKMetaTableAccessor
+ .getTableRegions(TEST_UTIL.getConnection(), tableName);
+ deleteRegionDir(tableName, regions.get(0).getEncodedName());
+ HBCKMetaTableAccessor.deleteRegionInfoColumn(TEST_UTIL.getConnection(), regions.get(0));
+ assertEquals(1, hbck.extraRegionsInMeta(new String[]{"-f",
+ "default:" + tableName.getNameAsString()}).get(tableName).size());
+ assertEquals("Table regions should had been removed from META.", 4,
+ HBCKMetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tableName).size());
+ }
+
private String testFormatExtraRegionsInMetaReport() throws IOException {
return testRunWithArgs(new String[]{EXTRA_REGIONS_IN_META});
}
@@ -735,7 +749,7 @@
assertEquals(extraRegions, hbck.extraRegionsInMeta(new String[]{"-f",
"default:" + tableName.getNameAsString()}).get(tableName).size());
assertEquals("Table regions should had been removed from META.", remaining,
- HBCKMetaTableAccessor.getRegionCount(TEST_UTIL.getConnection(), tableName));
+ HBCKMetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tableName).size());
}
private void testReportExtraRegionsInMeta(int extraRegionsInTestTbl,