Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,25 +86,25 @@ public Map<TableName,List<Path>> reportTablesMissingRegions(final List<String> n
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());
});
}

Expand Down Expand Up @@ -132,18 +132,18 @@ public List<Future<List<String>>> addMissingRegionsInMetaForTables(
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;
}
Expand All @@ -156,11 +156,11 @@ public void close() throws IOException {
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);
}

Expand Down
4 changes: 2 additions & 2 deletions hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,12 @@ Map<TableName, List<String>> extraRegionsInMeta(String[] args)
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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private void deleteRegionFromMeta(String tname) throws IOException, InterruptedE
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);
Expand Down
41 changes: 41 additions & 0 deletions hbase-hbck2/src/main/java/org/apache/hbase/HBCKMetaEntry.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,44 @@ public static List<RegionInfo> getMergeRegions(Cell[] cells) {
* @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()
Expand Down Expand Up @@ -187,11 +218,49 @@ private static void deleteFromMetaTable(final Connection connection, final Delet
* 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()) + " ,,";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ private RegionInfo createRegionInMeta(ResultScanner mockedRS) throws Exception {
@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
Expand Down Expand Up @@ -243,7 +243,7 @@ public void testReportTablesExtraRegionsOneExtra() throws Exception {
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());
}
Expand Down
16 changes: 15 additions & 1 deletion hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,20 @@ public void testFunctionNotSupported() throws IOException {
}
}

@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});
}
Expand Down Expand Up @@ -735,7 +749,7 @@ private void testRemoveExtraRegionsInMetaForTables(int extraRegions, int totalRe
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,
Expand Down