Skip to content

Commit

Permalink
HBASE-27250 MasterRpcService#setRegionStateInMeta does not support re…
Browse files Browse the repository at this point in the history
…plica region encodedNames or region names

- Added sanity check to make sure input region encoded name or region name is valid
- Assignment improvements pertaining to read replica regions
- make several MetaTableAccessor methods more precise in their handling of replica regions
- hbck2 setRegionStateInMeta and HBCKServerCrashProcedure handle read replicas
- separate AM helper methods -- loading RegionInfo from cache vs. refreshing cache from meta
- AM helper method support loading RegionInfo from cache via either region name and encoded region
  name (both caches are maintained, and under lock)
- consolidate, extend tests to cover read replica regions

Co-authored-by: Huaxiang Sun <[email protected]>
Co-authored-by: Nick Dimiduk <[email protected]>
Signed-off-by: Peter Somogyi <[email protected]>
  • Loading branch information
3 people committed Mar 6, 2023
1 parent 1ac6f16 commit 9a69a69
Show file tree
Hide file tree
Showing 20 changed files with 394 additions and 294 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ public static HRegionLocation getRegionLocation(Connection connection, byte[] re
RegionLocations locations = getRegionLocations(r);
return locations == null
? null
: locations.getRegionLocation(parsedInfo == null ? 0 : parsedInfo.getReplicaId());
: locations.getRegionLocation(
parsedInfo == null ? RegionInfo.DEFAULT_REPLICA_ID : parsedInfo.getReplicaId());
}

/**
Expand Down Expand Up @@ -333,12 +334,12 @@ public static RegionInfo parseRegionInfoFromRegionName(byte[] regionName) throws
/**
* Gets the result in hbase:meta for the specified region.
* @param connection connection we're using
* @param regionName region we're looking for
* @param regionInfo region we're looking for
* @return result of the specified region
*/
public static Result getRegionResult(Connection connection, byte[] regionName)
public static Result getRegionResult(Connection connection, RegionInfo regionInfo)
throws IOException {
Get get = new Get(regionName);
Get get = new Get(getMetaKeyForRegion(regionInfo));
get.addFamily(HConstants.CATALOG_FAMILY);
return get(getMetaHTable(connection), get);
}
Expand All @@ -364,20 +365,20 @@ public static Result scanByRegionEncodedName(Connection connection, String regio
}

/**
* Returns Return all regioninfos listed in the 'info:merge*' columns of the
* <code>regionName</code> row.
* Returns Return all regioninfos listed in the 'info:merge*' columns of the {@code regionInfo}
* row.
*/
@Nullable
public static List<RegionInfo> getMergeRegions(Connection connection, byte[] regionName)
public static List<RegionInfo> getMergeRegions(Connection connection, RegionInfo regionInfo)
throws IOException {
return getMergeRegions(getRegionResult(connection, regionName).rawCells());
return getMergeRegions(getRegionResult(connection, regionInfo).rawCells());
}

/**
* Check whether the given {@code regionName} has any 'info:merge*' columns.
* Check whether the given {@code regionInfo} has any 'info:merge*' columns.
*/
public static boolean hasMergeRegions(Connection conn, byte[] regionName) throws IOException {
return hasMergeRegions(getRegionResult(conn, regionName).rawCells());
public static boolean hasMergeRegions(Connection conn, RegionInfo regionInfo) throws IOException {
return hasMergeRegions(getRegionResult(conn, regionInfo).rawCells());
}

/**
Expand Down Expand Up @@ -1294,11 +1295,21 @@ public final boolean visit(Result rowResult) throws IOException {
////////////////////////
// Editing operations //
////////////////////////

/**
* Generates and returns a {@link Put} containing the {@link RegionInfo} for the catalog table.
* @throws IllegalArgumentException when the provided RegionInfo is not the default replica.
*/
public static Put makePutFromRegionInfo(RegionInfo regionInfo) throws IOException {
return makePutFromRegionInfo(regionInfo, EnvironmentEdgeManager.currentTime());
}

/**
* Generates and returns a Put containing the region into for the catalog table
* Generates and returns a {@link Put} containing the {@link RegionInfo} for the catalog table.
* @throws IllegalArgumentException when the provided RegionInfo is not the default replica.
*/
public static Put makePutFromRegionInfo(RegionInfo regionInfo, long ts) throws IOException {
return addRegionInfo(new Put(regionInfo.getRegionName(), ts), regionInfo);
return addRegionInfo(new Put(getMetaKeyForRegion(regionInfo), ts), regionInfo);
}

/**
Expand All @@ -1308,7 +1319,11 @@ public static Delete makeDeleteFromRegionInfo(RegionInfo regionInfo, long ts) {
if (regionInfo == null) {
throw new IllegalArgumentException("Can't make a delete for null region");
}
Delete delete = new Delete(regionInfo.getRegionName());
if (regionInfo.getReplicaId() != RegionInfo.DEFAULT_REPLICA_ID) {
throw new IllegalArgumentException(
"Can't make delete for a replica region. Operate on the primary");
}
Delete delete = new Delete(getMetaKeyForRegion(regionInfo));
delete.addFamily(getCatalogFamily(), ts);
return delete;
}
Expand Down Expand Up @@ -1399,9 +1414,14 @@ private static void deleteFromMetaTable(final Connection connection, final List<
}
}

private static Put addRegionStateToPut(Put put, RegionState.State state) throws IOException {
/**
* Set the column value corresponding to this {@code replicaId}'s {@link RegionState} to the
* provided {@code state}. Mutates the provided {@link Put}.
*/
private static Put addRegionStateToPut(Put put, int replicaId, RegionState.State state)
throws IOException {
put.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(put.getRow())
.setFamily(HConstants.CATALOG_FAMILY).setQualifier(getRegionStateColumn())
.setFamily(HConstants.CATALOG_FAMILY).setQualifier(getRegionStateColumn(replicaId))
.setTimestamp(put.getTimestamp()).setType(Cell.Type.Put).setValue(Bytes.toBytes(state.name()))
.build());
return put;
Expand All @@ -1412,9 +1432,9 @@ private static Put addRegionStateToPut(Put put, RegionState.State state) throws
*/
public static void updateRegionState(Connection connection, RegionInfo ri,
RegionState.State state) throws IOException {
Put put = new Put(RegionReplicaUtil.getRegionInfoForDefaultReplica(ri).getRegionName());
MetaTableAccessor.putsToMetaTable(connection,
Collections.singletonList(addRegionStateToPut(put, state)));
final Put put = makePutFromRegionInfo(ri);
addRegionStateToPut(put, ri.getReplicaId(), state);
putsToMetaTable(connection, Collections.singletonList(put));
}

/**
Expand All @@ -1432,7 +1452,7 @@ public static void updateRegionState(Connection connection, RegionInfo ri,
public static void addSplitsToParent(Connection connection, RegionInfo regionInfo,
RegionInfo splitA, RegionInfo splitB) throws IOException {
try (Table meta = getMetaHTable(connection)) {
Put put = makePutFromRegionInfo(regionInfo, EnvironmentEdgeManager.currentTime());
Put put = makePutFromRegionInfo(regionInfo);
addDaughtersToPut(put, splitA, splitB);
meta.put(put);
debugLogMutation(put);
Expand Down Expand Up @@ -1483,7 +1503,7 @@ private static void addRegionsToMeta(Connection connection, List<RegionInfo> reg
if (RegionReplicaUtil.isDefaultReplica(regionInfo)) {
Put put = makePutFromRegionInfo(regionInfo, ts);
// New regions are added with initial state of CLOSED.
addRegionStateToPut(put, RegionState.State.CLOSED);
addRegionStateToPut(put, regionInfo.getReplicaId(), RegionState.State.CLOSED);
// Add empty locations for region replicas so that number of replicas can be cached
// whenever the primary region is looked up from meta
for (int i = 1; i < regionReplication; i++) {
Expand Down Expand Up @@ -1548,7 +1568,7 @@ public static void mergeRegions(Connection connection, RegionInfo mergedRegion,
// default OFFLINE state. If Master gets restarted after this step, start up sequence of
// master tries to assign this offline region. This is followed by re-assignments of the
// merged region from resumed {@link MergeTableRegionsProcedure}
addRegionStateToPut(putOfMerged, RegionState.State.CLOSED);
addRegionStateToPut(putOfMerged, RegionInfo.DEFAULT_REPLICA_ID, RegionState.State.CLOSED);
mutations.add(putOfMerged);
// The merged is a new region, openSeqNum = 1 is fine. ServerName may be null
// if crash after merge happened but before we got to here.. means in-memory
Expand Down Expand Up @@ -1606,8 +1626,8 @@ public static void splitRegion(Connection connection, RegionInfo parent, long pa
// default OFFLINE state. If Master gets restarted after this step, start up sequence of
// master tries to assign these offline regions. This is followed by re-assignments of the
// daughter regions from resumed {@link SplitTableRegionProcedure}
addRegionStateToPut(putA, RegionState.State.CLOSED);
addRegionStateToPut(putB, RegionState.State.CLOSED);
addRegionStateToPut(putA, RegionInfo.DEFAULT_REPLICA_ID, RegionState.State.CLOSED);
addRegionStateToPut(putB, RegionInfo.DEFAULT_REPLICA_ID, RegionState.State.CLOSED);

addSequenceNum(putA, 1, splitA.getReplicaId()); // new regions, openSeqNum = 1 is fine.
addSequenceNum(putB, 1, splitB.getReplicaId());
Expand Down Expand Up @@ -1820,7 +1840,7 @@ public static void deleteMergeQualifiers(Connection connection, final RegionInfo
throws IOException {
Delete delete = new Delete(mergeRegion.getRegionName());
// NOTE: We are doing a new hbase:meta read here.
Cell[] cells = getRegionResult(connection, mergeRegion.getRegionName()).rawCells();
Cell[] cells = getRegionResult(connection, mergeRegion).rawCells();
if (cells == null || cells.length == 0) {
return;
}
Expand Down
Loading

0 comments on commit 9a69a69

Please sign in to comment.