ndimiduk commented on a change in pull request #917: HBASE-23383 [hbck2]
`fixHoles` should queue assignment procedures for any regions its fixing
URL: https://github.com/apache/hbase/pull/917#discussion_r362929553
##########
File path:
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java
##########
@@ -86,74 +87,176 @@ void fix() throws IOException {
* If hole, it papers it over by adding a region in the filesystem and to
hbase:meta.
* Does not assign.
*/
- void fixHoles(CatalogJanitor.Report report) throws IOException {
- List<Pair<RegionInfo, RegionInfo>> holes = report.getHoles();
+ void fixHoles(CatalogJanitor.Report report) {
+ final List<Pair<RegionInfo, RegionInfo>> holes = report.getHoles();
if (holes.isEmpty()) {
- LOG.debug("No holes.");
+ LOG.info("CatalogJanitor Report contains no holes to fix. Skipping.");
return;
}
- for (Pair<RegionInfo, RegionInfo> p: holes) {
- RegionInfo ri = getHoleCover(p);
- if (ri == null) {
- continue;
- }
- Configuration configuration = this.masterServices.getConfiguration();
- HRegion.createRegionDir(configuration, ri,
FSUtils.getRootDir(configuration));
- // If an error here, then we'll have a region in the filesystem but not
- // in hbase:meta (if the below fails). Should be able to rerun the fix.
- // Add to hbase:meta and then update in-memory state so it knows of new
- // Region; addRegionToMeta adds region and adds a state column set to
CLOSED.
- MetaTableAccessor.addRegionToMeta(this.masterServices.getConnection(),
ri);
- this.masterServices.getAssignmentManager().getRegionStates().
- updateRegionState(ri, RegionState.State.CLOSED);
- LOG.info("Fixed hole by adding {} in CLOSED state; region NOT assigned
(assign to ONLINE).",
- ri);
- }
+
+ LOG.info("Identified {} region holes to fix.", holes.size());
+
+ final List<RegionInfo> newRegionInfos = mapHolesToRegionInfos(holes);
+ final List<RegionInfo> newRegionDirectories =
+ createRegionDirectories(masterServices, newRegionInfos);
+ final List<RegionInfo> newMetaEntries = createMetaEntries(masterServices,
newRegionDirectories);
+ final List<TransitRegionStateProcedure> scheduledProcedures =
+
masterServices.getAssignmentManager().createAssignProceduresBestEffort(newMetaEntries);
+ LOG.info(
+ "Scheduled {}/{} new regions for assignment.",
scheduledProcedures.size(), holes.size());
}
/**
- * @return Calculated RegionInfo that covers the hole <code>hole</code>
+ * Create a new {@link RegionInfo} corresponding to each provided "hole"
pair.
*/
- private RegionInfo getHoleCover(Pair<RegionInfo, RegionInfo> hole) {
- RegionInfo holeCover = null;
- RegionInfo left = hole.getFirst();
- RegionInfo right = hole.getSecond();
+ private static List<RegionInfo> mapHolesToRegionInfos(
+ final List<Pair<RegionInfo, RegionInfo>> holes) {
+ final List<RegionInfo> newRegionInfos = holes.stream()
+ .map(MetaFixer::getHoleCover)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.toList());
+ LOG.debug("Constructed {}/{} RegionInfo descriptors corresponding to
identified holes.",
+ newRegionInfos.size(), holes.size());
+ return newRegionInfos;
+ }
+
+ /**
+ * @return Attempts to calculate a new {@link RegionInfo} that covers the
region range described
+ * in {@code hole}.
+ */
+ private static Optional<RegionInfo> getHoleCover(Pair<RegionInfo,
RegionInfo> hole) {
+ final RegionInfo left = hole.getFirst();
+ final RegionInfo right = hole.getSecond();
+
if (left.getTable().equals(right.getTable())) {
// Simple case.
if (Bytes.compareTo(left.getEndKey(), right.getStartKey()) >= 0) {
- LOG.warn("Skipping hole fix; left-side endKey is not less than
right-side startKey; " +
- "left=<{}>, right=<{}>", left, right);
- return holeCover;
- }
- holeCover = buildRegionInfo(left.getTable(), left.getEndKey(),
right.getStartKey());
- } else {
- boolean leftUndefined = left.equals(RegionInfo.UNDEFINED);
- boolean rightUnefined = right.equals(RegionInfo.UNDEFINED);
- boolean last = left.isLast();
- boolean first = right.isFirst();
- if (leftUndefined && rightUnefined) {
- LOG.warn("Skipping hole fix; both the hole left-side and right-side
RegionInfos are " +
- "UNDEFINED; left=<{}>, right=<{}>", left, right);
- return holeCover;
- }
- if (leftUndefined || last) {
- holeCover = buildRegionInfo(right.getTable(),
HConstants.EMPTY_START_ROW,
- right.getStartKey());
- } else if (rightUnefined || first) {
- holeCover = buildRegionInfo(left.getTable(), left.getEndKey(),
HConstants.EMPTY_END_ROW);
- } else {
- LOG.warn("Skipping hole fix; don't know what to do with left=<{}>,
right=<{}>",
- left, right);
- return holeCover;
+ LOG.warn("Skipping hole fix; left-side endKey is not less than
right-side startKey;"
+ + " left=<{}>, right=<{}>", left, right);
+ return Optional.empty();
}
+ return Optional.of(buildRegionInfo(left.getTable(), left.getEndKey(),
right.getStartKey()));
}
- return holeCover;
+
+ final boolean leftUndefined = left.equals(RegionInfo.UNDEFINED);
+ final boolean rightUndefined = right.equals(RegionInfo.UNDEFINED);
+ final boolean last = left.isLast();
+ final boolean first = right.isFirst();
+ if (leftUndefined && rightUndefined) {
+ LOG.warn("Skipping hole fix; both the hole left-side and right-side
RegionInfos are " +
+ "UNDEFINED; left=<{}>, right=<{}>", left, right);
+ return Optional.empty();
+ }
+ if (leftUndefined || last) {
+ return Optional.of(
+ buildRegionInfo(right.getTable(), HConstants.EMPTY_START_ROW,
right.getStartKey()));
+ }
+ if (rightUndefined || first) {
+ return Optional.of(
+ buildRegionInfo(left.getTable(), left.getEndKey(),
HConstants.EMPTY_END_ROW));
+ }
+ LOG.warn("Skipping hole fix; don't know what to do with left=<{}>,
right=<{}>", left, right);
+ return Optional.empty();
}
- private RegionInfo buildRegionInfo(TableName tn, byte [] start, byte [] end)
{
+ private static RegionInfo buildRegionInfo(TableName tn, byte [] start, byte
[] end) {
return
RegionInfoBuilder.newBuilder(tn).setStartKey(start).setEndKey(end).build();
}
+ /**
+ * Create entries in the filesystem for each provided {@link RegionInfo}.
Best effort.
Review comment:
We have 9 method variants for opening a region...
Ah yes. Looks like it's done through the `Region#initialize` method, called
as part of `HRegion#open`.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services