HBASE-7992 provide pre/post region offline hooks for HMaster.offlineRegion() (Rajeshbabu)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1457854 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Zhihong Yu 2013-03-18 16:44:04 +00:00
parent c826a16e5d
commit a832f774c4
7 changed files with 130 additions and 1 deletions

View File

@ -232,6 +232,16 @@ public class BaseMasterObserver implements MasterObserver {
HRegionInfo regionInfo, boolean force) throws IOException {
}
@Override
public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> ctx,
HRegionInfo regionInfo) throws IOException {
}
@Override
public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> ctx,
HRegionInfo regionInfo) throws IOException {
}
@Override
public void preBalance(ObserverContext<MasterCoprocessorEnvironment> ctx)
throws IOException {

View File

@ -440,6 +440,23 @@ public interface MasterObserver extends Coprocessor {
void postUnassign(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo regionInfo, final boolean force) throws IOException;
/**
* Called prior to marking a given region as offline. <code>ctx.bypass()</code> will not have any
* impact on this hook.
* @param ctx the environment to interact with the framework and master
* @param regionInfo
*/
void preRegionOffline(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo regionInfo) throws IOException;
/**
* Called after the region has been marked offline.
* @param ctx the environment to interact with the framework and master
* @param regionInfo
*/
void postRegionOffline(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo regionInfo) throws IOException;
/**
* Called prior to requesting rebalancing of the cluster regions, though after
* the initial checks for regions in transition and the balance switch flag.

View File

@ -2252,7 +2252,11 @@ Server {
}
/**
* Special method, only used by hbck.
* Offline specified region from master's in-memory state. It will not attempt to
* reassign the region as in unassign.
*
* This is a special method that should be used by experts or hbck.
*
*/
@Override
public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request)
@ -2269,7 +2273,13 @@ Server {
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName));
HRegionInfo hri = pair.getFirst();
if (cpHost != null) {
cpHost.preRegionOffline(hri);
}
this.assignmentManager.regionOffline(hri);
if (cpHost != null) {
cpHost.postRegionOffline(hri);
}
} catch (IOException ioe) {
throw new ServiceException(ioe);
}

View File

@ -811,6 +811,40 @@ public class MasterCoprocessorHost
}
}
void preRegionOffline(final HRegionInfo regionInfo) throws IOException {
ObserverContext<MasterCoprocessorEnvironment> ctx = null;
for (MasterEnvironment env : coprocessors) {
if (env.getInstance() instanceof MasterObserver) {
ctx = ObserverContext.createAndPrepare(env, ctx);
try {
((MasterObserver) env.getInstance()).preRegionOffline(ctx, regionInfo);
} catch (Throwable e) {
handleCoprocessorThrowable(env, e);
}
if (ctx.shouldComplete()) {
break;
}
}
}
}
void postRegionOffline(final HRegionInfo regionInfo) throws IOException {
ObserverContext<MasterCoprocessorEnvironment> ctx = null;
for (MasterEnvironment env : coprocessors) {
if (env.getInstance() instanceof MasterObserver) {
ctx = ObserverContext.createAndPrepare(env, ctx);
try {
((MasterObserver) env.getInstance()).postRegionOffline(ctx, regionInfo);
} catch (Throwable e) {
handleCoprocessorThrowable(env, e);
}
if (ctx.shouldComplete()) {
break;
}
}
}
}
boolean preBalance() throws IOException {
boolean bypass = false;
ObserverContext<MasterCoprocessorEnvironment> ctx = null;

View File

@ -674,6 +674,17 @@ public class AccessController extends BaseRegionObserver
public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> c,
HRegionInfo regionInfo, boolean force) throws IOException {}
@Override
public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> c,
HRegionInfo regionInfo) throws IOException {
requirePermission("regionOffline", regionInfo.getTableName(), null, null, Action.ADMIN);
}
@Override
public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> c,
HRegionInfo regionInfo) throws IOException {
}
@Override
public void preBalance(ObserverContext<MasterCoprocessorEnvironment> c)
throws IOException {

View File

@ -90,6 +90,8 @@ public class TestMasterObserver {
private boolean postAssignCalled;
private boolean preUnassignCalled;
private boolean postUnassignCalled;
private boolean preRegionOfflineCalled;
private boolean postRegionOfflineCalled;
private boolean preBalanceCalled;
private boolean postBalanceCalled;
private boolean preBalanceSwitchCalled;
@ -151,6 +153,8 @@ public class TestMasterObserver {
postAssignCalled = false;
preUnassignCalled = false;
postUnassignCalled = false;
preRegionOfflineCalled = false;
postRegionOfflineCalled = false;
preBalanceCalled = false;
postBalanceCalled = false;
preBalanceSwitchCalled = false;
@ -441,6 +445,26 @@ public class TestMasterObserver {
return preUnassignCalled && !postUnassignCalled;
}
@Override
public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo) throws IOException {
preRegionOfflineCalled = true;
}
@Override
public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo) throws IOException {
postRegionOfflineCalled = true;
}
public boolean wasRegionOfflineCalled() {
return preRegionOfflineCalled && postRegionOfflineCalled;
}
public boolean preRegionOfflineCalledOnly() {
return preRegionOfflineCalled && !postRegionOfflineCalled;
}
@Override
public void preBalance(ObserverContext<MasterCoprocessorEnvironment> env)
throws IOException {

View File

@ -486,6 +486,29 @@ public class TestAccessController {
verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
}
@Test
public void testRegionOffline() throws Exception {
Map<HRegionInfo, ServerName> regions;
HTable table = new HTable(TEST_UTIL.getConfiguration(), TEST_TABLE);
try {
regions = table.getRegionLocations();
} finally {
table.close();
}
final Map.Entry<HRegionInfo, ServerName> firstRegion = regions.entrySet().iterator().next();
PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
public Object run() throws Exception {
ACCESS_CONTROLLER.preRegionOffline(ObserverContext.createAndPrepare(CP_ENV, null),
firstRegion.getKey());
return null;
}
};
verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER);
verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE);
}
@Test
public void testBalance() throws Exception {
PrivilegedExceptionAction action = new PrivilegedExceptionAction() {