in hbase-hbck2/src/main/java/org/apache/hbase/RegionInfoMismatchTool.java [123:189]
void run(PrintStream out, boolean fix) throws IOException, DeserializationException {
List<MalformedRegion> regionsToFix = getMalformedRegions();
if (!fix) {
out.println("Fix mode is disabled, printing all malformed regions detected:");
for (MalformedRegion r : regionsToFix) {
out.println("Rowkey " + HBCKRegionInfo.encodeRegionName(r.getRegionName())
+ " does not match " + r.getRegionInfo());
}
}
out.println("Found " + regionsToFix.size() + " regions to fix.");
try (Table meta = connection.getTable(TableName.META_TABLE_NAME)) {
for (MalformedRegion regionToFix : regionsToFix) {
final byte[] regionName = regionToFix.getRegionName();
final RegionInfo wrongRegionInfo = regionToFix.getRegionInfo();
// The encoded region name is an MD5 hash, but the regionID is what is actually
// broken by HBASE-23328
byte[][] regionNameParts = HBCKRegionInfo.parseRegionNameOrReturnNull(regionName);
if (regionNameParts == null) {
throw new RuntimeException("Couldn't parse parts from "
+ Bytes.toStringBinary(regionName));
}
int i = 0;
for (byte[] part : regionNameParts) {
LOG.debug("Region name part[{}]: {}", i++, Bytes.toStringBinary(part));
}
// Third component of a region name is just a literal numeric (not a binary-encoded long)
long regionId = Long.parseLong(Bytes.toString(regionNameParts[2]));
// HBASE-24500: We cannot use newBuilder(RegionInfo) because it will copy the NAME and
// encodedName from the original RegionInfo instead of re-computing it. Copy all of the
// fields by hand which will force the new RegionInfo to recompute the NAME/encodedName
// fields.
RegionInfo correctedRegionInfo = RegionInfoBuilder.newBuilder(wrongRegionInfo.getTable())
.setRegionId(regionId)
.setStartKey(wrongRegionInfo.getStartKey())
.setEndKey(wrongRegionInfo.getEndKey())
.setReplicaId(0)
.setOffline(wrongRegionInfo.isOffline())
.setSplit(wrongRegionInfo.isSplit())
.build();
String rowkeyEncodedRegionName = HBCKRegionInfo.encodeRegionName(regionName);
String updatedValueEncodedRegionName = correctedRegionInfo.getEncodedName();
if (!rowkeyEncodedRegionName.equals(updatedValueEncodedRegionName)) {
out.println("Aborting: sanity-check failed on updated RegionInfo. Expected encoded "
+ "region name " +rowkeyEncodedRegionName + " but got "
+ updatedValueEncodedRegionName + ".");
out.println("Incorrectly created RegionInfo was: " + correctedRegionInfo);
throw new RuntimeException("Failed sanity-check on corrected RegionInfo");
}
out.println("Updating RegionInfo for " + Bytes.toStringBinary(regionName) + " to "
+ correctedRegionInfo);
// Write the update back to meta.
if (fix) {
meta.put(HBCKMetaTableAccessor.makePutFromRegionInfo(correctedRegionInfo,
System.currentTimeMillis()));
}
}
if (!fix) {
out.println("Fix mode is not enabled, hbase:meta was not updated. See the tool output for"
+ " a list of detected problematic regions. Re-run the tool without the dry run option"
+ " to persist updates to hbase:meta.");
}
}
}