HBASE-18796 Admin#isTableAvailable returns incorrect result before daughter regions are opened
Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
parent
539fce3440
commit
2845ddaf9e
|
@ -1340,8 +1340,8 @@ public class MetaTableAccessor {
|
|||
Put putA = makePutFromRegionInfo(splitA);
|
||||
Put putB = makePutFromRegionInfo(splitB);
|
||||
|
||||
addLocation(putA, sn, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
|
||||
addLocation(putB, sn, 1, -1, splitB.getReplicaId());
|
||||
addSequenceNum(putA, 1, -1, splitA.getReplicaId()); //new regions, openSeqNum = 1 is fine.
|
||||
addSequenceNum(putB, 1, -1, splitB.getReplicaId());
|
||||
|
||||
// Add empty locations for region replicas of daughters so that number of replicas can be
|
||||
// cached whenever the primary region is looked up from meta
|
||||
|
@ -1612,6 +1612,15 @@ public class MetaTableAccessor {
|
|||
return p;
|
||||
}
|
||||
|
||||
public static Put addSequenceNum(final Put p, long openSeqNum, long time, int replicaId) {
|
||||
if (time <= 0) {
|
||||
time = EnvironmentEdgeManager.currentTime();
|
||||
}
|
||||
p.addImmutable(HConstants.CATALOG_FAMILY, getSeqNumColumn(replicaId), time,
|
||||
Bytes.toBytes(openSeqNum));
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get replication position for a peer in a region.
|
||||
* @param connection connection we're using
|
||||
|
|
|
@ -644,5 +644,46 @@ public class TestMetaTableAccessor {
|
|||
assertTrue(prevCalls < scheduler.numPriorityCalls);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyMetaDaughterLocationDuringSplit() throws IOException {
|
||||
long regionId = System.currentTimeMillis();
|
||||
ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
|
||||
HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
|
||||
HConstants.EMPTY_END_ROW, false, regionId, 0);
|
||||
HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"), HConstants.EMPTY_START_ROW,
|
||||
Bytes.toBytes("a"), false, regionId + 1, 0);
|
||||
HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"), Bytes.toBytes("a"),
|
||||
HConstants.EMPTY_END_ROW, false, regionId + 1, 0);
|
||||
|
||||
Table meta = MetaTableAccessor.getMetaHTable(connection);
|
||||
try {
|
||||
List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
|
||||
MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
|
||||
|
||||
MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3, false);
|
||||
Get get1 = new Get(splitA.getRegionName());
|
||||
Result resultA = meta.get(get1);
|
||||
Cell serverCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getServerColumn(splitA.getReplicaId()));
|
||||
Cell startCodeCellA = resultA.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getStartCodeColumn(splitA.getReplicaId()));
|
||||
assertNull(serverCellA);
|
||||
assertNull(startCodeCellA);
|
||||
|
||||
Get get2 = new Get(splitA.getRegionName());
|
||||
Result resultB = meta.get(get2);
|
||||
Cell serverCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getServerColumn(splitB.getReplicaId()));
|
||||
Cell startCodeCellB = resultB.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getStartCodeColumn(splitB.getReplicaId()));
|
||||
assertNull(serverCellB);
|
||||
assertNull(startCodeCellB);
|
||||
} finally {
|
||||
if (meta != null) {
|
||||
meta.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,11 @@ public class TestEndToEndSplitTransaction {
|
|||
regions.getSecond().getRegionInfo());
|
||||
}
|
||||
|
||||
// first daughter second
|
||||
if (split.useZKForAssignment) {
|
||||
server.postOpenDeployTasks(regions.getFirst());
|
||||
}
|
||||
|
||||
// Add to online regions
|
||||
server.addToOnlineRegions(regions.getSecond());
|
||||
// THIS is the crucial point:
|
||||
|
@ -161,6 +166,63 @@ public class TestEndToEndSplitTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTableAvailableWhileSplitting() throws Exception {
|
||||
TableName tableName = TableName.valueOf("TestTableAvailableWhileSplitting");
|
||||
byte[] familyName = Bytes.toBytes("fam");
|
||||
try (HTable ht = TEST_UTIL.createTable(tableName, familyName)) {
|
||||
TEST_UTIL.loadTable(ht, familyName, false);
|
||||
}
|
||||
Admin admin = TEST_UTIL.getHBaseAdmin();
|
||||
HRegionServer server = TEST_UTIL.getHBaseCluster().getRegionServer(0);
|
||||
byte[] splitRow = Bytes.toBytes("lll");
|
||||
try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
|
||||
byte[] regionName = conn.getRegionLocator(tableName).getRegionLocation(splitRow)
|
||||
.getRegionInfo().getRegionName();
|
||||
Region region = server.getRegion(regionName);
|
||||
SplitTransactionImpl split = new SplitTransactionImpl((HRegion) region, splitRow);
|
||||
split.prepare();
|
||||
assertTrue(admin.isTableAvailable(tableName));
|
||||
|
||||
// 1. phase I
|
||||
PairOfSameType<Region> regions = split.createDaughters(server, server, null);
|
||||
// Parent should be offline at this stage and daughters not yet open
|
||||
assertFalse(admin.isTableAvailable(tableName));
|
||||
|
||||
// passing null as services prevents final step of postOpenDeployTasks
|
||||
// 2, most of phase II
|
||||
split.openDaughters(server, null, regions.getFirst(), regions.getSecond());
|
||||
assertFalse(admin.isTableAvailable(tableName));
|
||||
|
||||
// Finish openeing daughters
|
||||
// 2nd daughter first
|
||||
if (split.useZKForAssignment) {
|
||||
server.postOpenDeployTasks(regions.getSecond());
|
||||
} else {
|
||||
server.reportRegionStateTransition(
|
||||
RegionServerStatusProtos.RegionStateTransition.TransitionCode.SPLIT,
|
||||
region.getRegionInfo(), regions.getFirst().getRegionInfo(),
|
||||
regions.getSecond().getRegionInfo());
|
||||
}
|
||||
|
||||
// first daughter second
|
||||
if (split.useZKForAssignment) {
|
||||
server.postOpenDeployTasks(regions.getFirst());
|
||||
}
|
||||
|
||||
// After postOpenDeploy daughters should have location in meta
|
||||
assertTrue(admin.isTableAvailable(tableName));
|
||||
|
||||
server.addToOnlineRegions(regions.getSecond());
|
||||
server.addToOnlineRegions(regions.getFirst());
|
||||
assertTrue(admin.isTableAvailable(tableName));
|
||||
} finally {
|
||||
if (admin != null) {
|
||||
admin.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* attempt to locate the region and perform a get and scan
|
||||
* @return True if successful, False otherwise.
|
||||
|
|
Loading…
Reference in New Issue