void run()

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.");
      }
    }
  }