HBASE-11659 Region state RPC call is not idempotent (Virag Kothari)

This commit is contained in:
Jimmy Xiang 2014-08-08 14:56:38 -07:00
parent 4b8a38ebb5
commit fa46724f36
2 changed files with 53 additions and 1 deletions

View File

@ -2512,6 +2512,11 @@ public class AssignmentManager {
String errorMsg = null;
switch (code) {
case OPENED:
if (current != null && current.isOpened() && current.isOnServer(serverName)) {
LOG.info("Region " + hri.getShortNameToLog() + " is already " + current.getState() + " on "
+ serverName);
break;
}
case FAILED_OPEN:
if (current == null
|| !current.isPendingOpenOrOpeningOnServer(serverName)) {

View File

@ -57,6 +57,7 @@ import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
import org.apache.hadoop.hbase.coprocessor.RegionObserver;
import org.apache.hadoop.hbase.master.RegionState.State;
import org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer;
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;
import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.util.Bytes;
@ -136,7 +137,7 @@ public class TestAssignmentManagerOnCluster {
TEST_UTIL.deleteTable(Bytes.toBytes(table));
}
}
/**
* This tests region assignment on a simulated restarted server
*/
@ -970,6 +971,40 @@ public class TestAssignmentManagerOnCluster {
cluster.startRegionServer();
}
}
/**
* Test that region state transition call is idempotent
*/
@Test(timeout = 60000)
public void testReportRegionStateTransition() throws Exception {
String table = "testReportRegionStateTransition";
try {
MyRegionServer.simulateRetry = true;
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(table));
desc.addFamily(new HColumnDescriptor(FAMILY));
admin.createTable(desc);
HTable meta = new HTable(conf, TableName.META_TABLE_NAME);
HRegionInfo hri =
new HRegionInfo(desc.getTableName(), Bytes.toBytes("A"), Bytes.toBytes("Z"));
MetaTableAccessor.addRegionToMeta(meta, hri);
HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
master.assignRegion(hri);
AssignmentManager am = master.getAssignmentManager();
am.waitForAssignment(hri);
RegionStates regionStates = am.getRegionStates();
ServerName serverName = regionStates.getRegionServerOfRegion(hri);
// Assert the the region is actually open on the server
TEST_UTIL.assertRegionOnServer(hri, serverName, 200);
// Closing region should just work fine
admin.disableTable(TableName.valueOf(table));
assertTrue(regionStates.isRegionOffline(hri));
List<HRegionInfo> regions = TEST_UTIL.getHBaseAdmin().getOnlineRegions(serverName);
assertTrue(!regions.contains(hri));
} finally {
MyRegionServer.simulateRetry = false;
TEST_UTIL.deleteTable(Bytes.toBytes(table));
}
}
static class MyLoadBalancer extends StochasticLoadBalancer {
// For this region, if specified, always assign to nowhere
@ -1009,6 +1044,7 @@ public class TestAssignmentManagerOnCluster {
public static class MyRegionServer extends MiniHBaseClusterRegionServer {
static volatile ServerName abortedServer = null;
static volatile boolean simulateRetry = false;
public MyRegionServer(Configuration conf, CoordinatedStateManager cp)
throws IOException, KeeperException,
@ -1016,6 +1052,17 @@ public class TestAssignmentManagerOnCluster {
super(conf, cp);
}
@Override
public boolean reportRegionStateTransition(TransitionCode code, long openSeqNum,
HRegionInfo... hris) {
if (simulateRetry) {
// Simulate retry by calling the method twice
super.reportRegionStateTransition(code, openSeqNum, hris);
return super.reportRegionStateTransition(code, openSeqNum, hris);
}
return super.reportRegionStateTransition(code, openSeqNum, hris);
}
@Override
public boolean isAborted() {
return getServerName().equals(abortedServer) || super.isAborted();