Skip to content

Commit c73b2b9

Browse files
authored
HBASE-24705 MetaFixer#fixHoles() does not include the case for read replicas (i.e, replica regions are not created) (#2062) (#2067)
Signed-off-by: Viraj Jasani <[email protected]>
1 parent 15c8c2f commit c73b2b9

File tree

6 files changed

+66
-25
lines changed

6 files changed

+66
-25
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,13 @@ private static int compareRegionInfosWithoutReplicaId(RegionInfo regionInfoA,
147147
/**
148148
* Create any replicas for the regions (the default replicas that was already created is passed to
149149
* the method)
150-
* @param tableDescriptor descriptor to use
151150
* @param regions existing regions
152151
* @param oldReplicaCount existing replica count
153152
* @param newReplicaCount updated replica count due to modify table
154153
* @return the combined list of default and non-default replicas
155154
*/
156-
public static List<RegionInfo> addReplicas(final TableDescriptor tableDescriptor,
157-
final List<RegionInfo> regions, int oldReplicaCount, int newReplicaCount) {
155+
public static List<RegionInfo> addReplicas(final List<RegionInfo> regions, int oldReplicaCount,
156+
int newReplicaCount) {
158157
if ((newReplicaCount - 1) <= 0) {
159158
return regions;
160159
}

hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232
import org.apache.hadoop.hbase.TableName;
3333
import org.apache.hadoop.hbase.client.RegionInfo;
3434
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
35+
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
36+
import org.apache.hadoop.hbase.client.TableDescriptor;
3537
import org.apache.hadoop.hbase.exceptions.MergeRegionException;
3638
import org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure;
3739
import org.apache.hadoop.hbase.util.Bytes;
3840
import org.apache.hadoop.hbase.util.Pair;
41+
import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
3942
import org.apache.yetus.audience.InterfaceAudience;
4043
import org.slf4j.Logger;
4144
import org.slf4j.LoggerFactory;
@@ -174,22 +177,35 @@ private static RegionInfo buildRegionInfo(TableName tn, byte [] start, byte [] e
174177
private static List<RegionInfo> createMetaEntries(final MasterServices masterServices,
175178
final List<RegionInfo> newRegionInfos) {
176179

177-
final List<Either<RegionInfo, IOException>> addMetaEntriesResults = newRegionInfos.stream()
178-
.map(regionInfo -> {
180+
final List<Either<List<RegionInfo>, IOException>> addMetaEntriesResults = newRegionInfos.
181+
stream().map(regionInfo -> {
179182
try {
180-
MetaTableAccessor.addRegionToMeta(masterServices.getConnection(), regionInfo);
181-
masterServices.getAssignmentManager()
182-
.getRegionStates()
183-
.updateRegionState(regionInfo, RegionState.State.CLOSED);
184-
return Either.<RegionInfo, IOException>ofLeft(regionInfo);
183+
TableDescriptor td = masterServices.getTableDescriptors().get(regionInfo.getTable());
184+
185+
// Add replicas if needed
186+
// we need to create regions with replicaIds starting from 1
187+
List<RegionInfo> newRegions = RegionReplicaUtil.addReplicas(
188+
Collections.singletonList(regionInfo), 1, td.getRegionReplication());
189+
190+
// Add regions to META
191+
MetaTableAccessor.addRegionsToMeta(masterServices.getConnection(), newRegions,
192+
td.getRegionReplication());
193+
194+
// Setup replication for region replicas if needed
195+
if (td.getRegionReplication() > 1) {
196+
ServerRegionReplicaUtil.setupRegionReplicaReplication(
197+
masterServices.getConfiguration());
198+
}
199+
return Either.<List<RegionInfo>, IOException>ofLeft(newRegions);
185200
} catch (IOException e) {
186-
return Either.<RegionInfo, IOException>ofRight(e);
201+
return Either.<List<RegionInfo>, IOException>ofRight(e);
187202
}
188203
})
189204
.collect(Collectors.toList());
190205
final List<RegionInfo> createMetaEntriesSuccesses = addMetaEntriesResults.stream()
191206
.filter(Either::hasLeft)
192207
.map(Either::getLeft)
208+
.flatMap(List::stream)
193209
.collect(Collectors.toList());
194210
final List<IOException> createMetaEntriesFailures = addMetaEntriesResults.stream()
195211
.filter(Either::hasRight)

hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ protected static List<RegionInfo> addTableToMeta(final MasterProcedureEnv env,
349349

350350
// Add replicas if needed
351351
// we need to create regions with replicaIds starting from 1
352-
List<RegionInfo> newRegions = RegionReplicaUtil.addReplicas(tableDescriptor, regions, 1,
352+
List<RegionInfo> newRegions = RegionReplicaUtil.addReplicas(regions, 1,
353353
tableDescriptor.getRegionReplication());
354354

355355
// Add regions to META

hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/EnableTableProcedure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ protected Flow executeFromState(final MasterProcedureEnv env, final EnableTableS
144144
LOG.info("Number of replicas has increased. Assigning new region replicas." +
145145
"The previous replica count was {}. The current replica count is {}.",
146146
(currentMaxReplica + 1), configuredReplicaCount);
147-
regionsOfTable = RegionReplicaUtil.addReplicas(tableDescriptor, regionsOfTable,
147+
regionsOfTable = RegionReplicaUtil.addReplicas(regionsOfTable,
148148
currentMaxReplica + 1, configuredReplicaCount);
149149
}
150150
// Assign all the table regions. (including region replicas if added).

hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,19 @@ public Table createMultiRegionTable(TableName tableName, byte[][] families) thro
16001600
return createTable(tableName, families, KEYS_FOR_HBA_CREATE_TABLE);
16011601
}
16021602

1603+
/**
1604+
* Create a table with multiple regions.
1605+
* @param tableName
1606+
* @param replicaCount replica count.
1607+
* @param families
1608+
* @return A Table instance for the created table.
1609+
* @throws IOException
1610+
*/
1611+
public Table createMultiRegionTable(TableName tableName, int replicaCount, byte[][] families)
1612+
throws IOException {
1613+
return createTable(tableName, families, KEYS_FOR_HBA_CREATE_TABLE, replicaCount);
1614+
}
1615+
16031616
/**
16041617
* Create a table.
16051618
* @param tableName

hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaFixer.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,24 @@ private void deleteRegion(MasterServices services, RegionInfo ri) throws IOExcep
8383
services.getAssignmentManager().getRegionStates().deleteRegion(ri);
8484
}
8585

86-
@Test
87-
public void testPlugsHoles() throws Exception {
88-
TableName tn = TableName.valueOf(this.name.getMethodName());
89-
TEST_UTIL.createMultiRegionTable(tn, HConstants.CATALOG_FAMILY);
86+
private void testPlugsHolesWithReadReplicaInternal(final TableName tn, final int replicaCount)
87+
throws Exception {
88+
TEST_UTIL.createMultiRegionTable(tn, replicaCount, new byte[][] { HConstants.CATALOG_FAMILY });
9089
List<RegionInfo> ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn);
9190
MasterServices services = TEST_UTIL.getHBaseCluster().getMaster();
9291
int initialSize = services.getAssignmentManager().getRegionStates().getRegionStates().size();
9392
services.getCatalogJanitor().scan();
9493
CatalogJanitor.Report report = services.getCatalogJanitor().getLastReport();
9594
assertTrue(report.isEmpty());
9695
int originalCount = ris.size();
97-
// Remove first, last and middle region. See if hole gets plugged. Table has 26 regions.
98-
deleteRegion(services, ris.get(ris.size() -1));
99-
deleteRegion(services, ris.get(3));
100-
deleteRegion(services, ris.get(0));
101-
assertEquals(initialSize - 3,
102-
services.getAssignmentManager().getRegionStates().getRegionStates().size());
96+
// Remove first, last and middle region. See if hole gets plugged. Table has 26 * replicaCount regions.
97+
for (int i = 0; i < replicaCount; i ++) {
98+
deleteRegion(services, ris.get(3 * replicaCount + i));
99+
deleteRegion(services, ris.get(i));
100+
deleteRegion(services, ris.get(ris.size() - 1 - i));
101+
}
102+
assertEquals(initialSize - 3 * replicaCount,
103+
services.getAssignmentManager().getRegionStates().getRegionStates().size());
103104
services.getCatalogJanitor().scan();
104105
report = services.getCatalogJanitor().getLastReport();
105106
assertEquals(report.toString(), 3, report.getHoles().size());
@@ -109,17 +110,29 @@ public void testPlugsHoles() throws Exception {
109110
report = services.getCatalogJanitor().getLastReport();
110111
assertTrue(report.toString(), report.isEmpty());
111112
assertEquals(initialSize,
112-
services.getAssignmentManager().getRegionStates().getRegionStates().size());
113+
services.getAssignmentManager().getRegionStates().getRegionStates().size());
113114

114115
// wait for RITs to settle -- those are the fixed regions being assigned -- or until the
115116
// watchdog TestRule terminates the test.
116117
HBaseTestingUtility.await(50,
117-
() -> isNotEmpty(services.getAssignmentManager().getRegionsInTransition()));
118+
() -> services.getMasterProcedureExecutor().getActiveProcIds().size() == 0);
118119

119120
ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn);
120121
assertEquals(originalCount, ris.size());
121122
}
122123

124+
@Test
125+
public void testPlugsHoles() throws Exception {
126+
TableName tn = TableName.valueOf(this.name.getMethodName());
127+
testPlugsHolesWithReadReplicaInternal(tn, 1);
128+
}
129+
130+
@Test
131+
public void testPlugsHolesWithReadReplica() throws Exception {
132+
TableName tn = TableName.valueOf(this.name.getMethodName());
133+
testPlugsHolesWithReadReplicaInternal(tn, 3);
134+
}
135+
123136
/**
124137
* Just make sure running fixMeta does right thing for the case
125138
* of a single-region Table where the region gets dropped.

0 commit comments

Comments
 (0)