/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.coprocessor;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.CoprocessorEnvironment;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MiniHBaseCluster;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.ProcedureInfo;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.MasterSwitchType;
import org.apache.hadoop.hbase.client.Mutation;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
import org.apache.hadoop.hbase.master.RegionPlan;
import org.apache.hadoop.hbase.master.locking.LockProcedure;
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
import org.apache.hadoop.hbase.net.Address;
import org.apache.hadoop.hbase.procedure2.LockInfo;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;
import org.apache.hadoop.hbase.testclassification.CoprocessorTests;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Threads;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;
/**
* Tests invocation of the {@link org.apache.hadoop.hbase.coprocessor.MasterObserver}
* interface hooks at all appropriate times during normal HMaster operations.
*/
@Category({CoprocessorTests.class, MediumTests.class})
public class TestMasterObserver {
private static final Log LOG = LogFactory.getLog(TestMasterObserver.class);
public static CountDownLatch tableCreationLatch = new CountDownLatch(1);
public static CountDownLatch tableDeletionLatch = new CountDownLatch(1);
public static class CPMasterObserver implements MasterObserver {
private boolean bypass = false;
private boolean preCreateTableCalled;
private boolean postCreateTableCalled;
private boolean preDeleteTableCalled;
private boolean postDeleteTableCalled;
private boolean preTruncateTableCalled;
private boolean postTruncateTableCalled;
private boolean preModifyTableCalled;
private boolean postModifyTableCalled;
private boolean preCreateNamespaceCalled;
private boolean postCreateNamespaceCalled;
private boolean preDeleteNamespaceCalled;
private boolean postDeleteNamespaceCalled;
private boolean preModifyNamespaceCalled;
private boolean postModifyNamespaceCalled;
private boolean preGetNamespaceDescriptorCalled;
private boolean postGetNamespaceDescriptorCalled;
private boolean preListNamespaceDescriptorsCalled;
private boolean postListNamespaceDescriptorsCalled;
private boolean preAddColumnCalled;
private boolean postAddColumnCalled;
private boolean preModifyColumnCalled;
private boolean postModifyColumnCalled;
private boolean preDeleteColumnCalled;
private boolean postDeleteColumnCalled;
private boolean preEnableTableCalled;
private boolean postEnableTableCalled;
private boolean preDisableTableCalled;
private boolean postDisableTableCalled;
private boolean preAbortProcedureCalled;
private boolean postAbortProcedureCalled;
private boolean preListProceduresCalled;
private boolean postListProceduresCalled;
private boolean preListLocksCalled;
private boolean postListLocksCalled;
private boolean preMoveCalled;
private boolean postMoveCalled;
private boolean preAssignCalled;
private boolean postAssignCalled;
private boolean preUnassignCalled;
private boolean postUnassignCalled;
private boolean preRegionOfflineCalled;
private boolean postRegionOfflineCalled;
private boolean preBalanceCalled;
private boolean postBalanceCalled;
private boolean preBalanceSwitchCalled;
private boolean postBalanceSwitchCalled;
private boolean preShutdownCalled;
private boolean preStopMasterCalled;
private boolean preMasterInitializationCalled;
private boolean postStartMasterCalled;
private boolean startCalled;
private boolean stopCalled;
private boolean preSnapshotCalled;
private boolean postSnapshotCalled;
private boolean preListSnapshotCalled;
private boolean postListSnapshotCalled;
private boolean preCloneSnapshotCalled;
private boolean postCloneSnapshotCalled;
private boolean preRestoreSnapshotCalled;
private boolean postRestoreSnapshotCalled;
private boolean preDeleteSnapshotCalled;
private boolean postDeleteSnapshotCalled;
private boolean preCreateTableActionCalled;
private boolean postCompletedCreateTableActionCalled;
private boolean preDeleteTableActionCalled;
private boolean postCompletedDeleteTableActionCalled;
private boolean preTruncateTableActionCalled;
private boolean postCompletedTruncateTableActionCalled;
private boolean preAddColumnFamilyActionCalled;
private boolean postCompletedAddColumnFamilyActionCalled;
private boolean preModifyColumnFamilyActionCalled;
private boolean postCompletedModifyColumnFamilyActionCalled;
private boolean preDeleteColumnFamilyActionCalled;
private boolean postCompletedDeleteColumnFamilyActionCalled;
private boolean preEnableTableActionCalled;
private boolean postCompletedEnableTableActionCalled;
private boolean preDisableTableActionCalled;
private boolean postCompletedDisableTableActionCalled;
private boolean preModifyTableActionCalled;
private boolean postCompletedModifyTableActionCalled;
private boolean preGetTableDescriptorsCalled;
private boolean postGetTableDescriptorsCalled;
private boolean postGetTableNamesCalled;
private boolean preGetTableNamesCalled;
private boolean preDispatchMergeCalled;
private boolean postDispatchMergeCalled;
private boolean preMergeRegionsCalled;
private boolean postMergeRegionsCalled;
private boolean preRequestLockCalled;
private boolean postRequestLockCalled;
private boolean preLockHeartbeatCalled;
private boolean postLockHeartbeatCalled;
public void enableBypass(boolean bypass) {
this.bypass = bypass;
}
public void resetStates() {
preCreateTableCalled = false;
postCreateTableCalled = false;
preDeleteTableCalled = false;
postDeleteTableCalled = false;
preTruncateTableCalled = false;
postTruncateTableCalled = false;
preModifyTableCalled = false;
postModifyTableCalled = false;
preCreateNamespaceCalled = false;
postCreateNamespaceCalled = false;
preDeleteNamespaceCalled = false;
postDeleteNamespaceCalled = false;
preModifyNamespaceCalled = false;
postModifyNamespaceCalled = false;
preGetNamespaceDescriptorCalled = false;
postGetNamespaceDescriptorCalled = false;
preListNamespaceDescriptorsCalled = false;
postListNamespaceDescriptorsCalled = false;
preAddColumnCalled = false;
postAddColumnCalled = false;
preModifyColumnCalled = false;
postModifyColumnCalled = false;
preDeleteColumnCalled = false;
postDeleteColumnCalled = false;
preEnableTableCalled = false;
postEnableTableCalled = false;
preDisableTableCalled = false;
postDisableTableCalled = false;
preAbortProcedureCalled = false;
postAbortProcedureCalled = false;
preListProceduresCalled = false;
postListProceduresCalled = false;
preMoveCalled= false;
postMoveCalled = false;
preAssignCalled = false;
postAssignCalled = false;
preUnassignCalled = false;
postUnassignCalled = false;
preRegionOfflineCalled = false;
postRegionOfflineCalled = false;
preBalanceCalled = false;
postBalanceCalled = false;
preBalanceSwitchCalled = false;
postBalanceSwitchCalled = false;
preShutdownCalled = false;
preStopMasterCalled = false;
preSnapshotCalled = false;
postSnapshotCalled = false;
preListSnapshotCalled = false;
postListSnapshotCalled = false;
preCloneSnapshotCalled = false;
postCloneSnapshotCalled = false;
preRestoreSnapshotCalled = false;
postRestoreSnapshotCalled = false;
preDeleteSnapshotCalled = false;
postDeleteSnapshotCalled = false;
preCreateTableActionCalled = false;
postCompletedCreateTableActionCalled = false;
preDeleteTableActionCalled = false;
postCompletedDeleteTableActionCalled = false;
preTruncateTableActionCalled = false;
postCompletedTruncateTableActionCalled = false;
preModifyTableActionCalled = false;
postCompletedModifyTableActionCalled = false;
preAddColumnFamilyActionCalled = false;
postCompletedAddColumnFamilyActionCalled = false;
preModifyColumnFamilyActionCalled = false;
postCompletedModifyColumnFamilyActionCalled = false;
preDeleteColumnFamilyActionCalled = false;
postCompletedDeleteColumnFamilyActionCalled = false;
preEnableTableActionCalled = false;
postCompletedEnableTableActionCalled = false;
preDisableTableActionCalled = false;
postCompletedDisableTableActionCalled = false;
preGetTableDescriptorsCalled = false;
postGetTableDescriptorsCalled = false;
postGetTableNamesCalled = false;
preGetTableNamesCalled = false;
preDispatchMergeCalled = false;
postDispatchMergeCalled = false;
preMergeRegionsCalled = false;
postMergeRegionsCalled = false;
preRequestLockCalled = false;
postRequestLockCalled = false;
preLockHeartbeatCalled = false;
postLockHeartbeatCalled = false;
}
@Override
public void preMergeRegions(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge) throws IOException {
preMergeRegionsCalled = true;
}
@Override
public void postMergeRegions(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge) throws IOException {
postMergeRegionsCalled = true;
}
public boolean wasMergeRegionsCalled() {
return preMergeRegionsCalled && postMergeRegionsCalled;
}
@Override
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
preDispatchMergeCalled = true;
}
@Override
public void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
postDispatchMergeCalled = true;
}
public boolean wasDispatchMergeCalled() {
return preDispatchMergeCalled && postDispatchMergeCalled;
}
@Override
public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
if (bypass) {
env.bypass();
}
preCreateTableCalled = true;
}
@Override
public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
postCreateTableCalled = true;
}
public boolean wasCreateTableCalled() {
return preCreateTableCalled && postCreateTableCalled;
}
public boolean preCreateTableCalledOnly() {
return preCreateTableCalled && !postCreateTableCalled;
}
@Override
public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
if (bypass) {
env.bypass();
}
preDeleteTableCalled = true;
}
@Override
public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
postDeleteTableCalled = true;
}
public boolean wasDeleteTableCalled() {
return preDeleteTableCalled && postDeleteTableCalled;
}
public boolean preDeleteTableCalledOnly() {
return preDeleteTableCalled && !postDeleteTableCalled;
}
@Override
public void preTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
if (bypass) {
env.bypass();
}
preTruncateTableCalled = true;
}
@Override
public void postTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
postTruncateTableCalled = true;
}
public boolean wasTruncateTableCalled() {
return preTruncateTableCalled && postTruncateTableCalled;
}
public boolean preTruncateTableCalledOnly() {
return preTruncateTableCalled && !postTruncateTableCalled;
}
@Override
public boolean preSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final boolean newValue, final MasterSwitchType switchType) throws IOException {
return false;
}
@Override
public void postSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final boolean newValue, final MasterSwitchType switchType) throws IOException {
}
@Override
public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName, HTableDescriptor htd) throws IOException {
if (bypass) {
env.bypass();
}else{
env.shouldBypass();
}
preModifyTableCalled = true;
}
@Override
public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName, HTableDescriptor htd) throws IOException {
postModifyTableCalled = true;
}
public boolean wasModifyTableCalled() {
return preModifyTableCalled && postModifyTableCalled;
}
public boolean preModifyTableCalledOnly() {
return preModifyTableCalled && !postModifyTableCalled;
}
@Override
public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
NamespaceDescriptor ns) throws IOException {
if (bypass) {
env.bypass();
}
preCreateNamespaceCalled = true;
}
@Override
public void postCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
NamespaceDescriptor ns) throws IOException {
postCreateNamespaceCalled = true;
}
public boolean wasCreateNamespaceCalled() {
return preCreateNamespaceCalled && postCreateNamespaceCalled;
}
public boolean preCreateNamespaceCalledOnly() {
return preCreateNamespaceCalled && !postCreateNamespaceCalled;
}
@Override
public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
String name) throws IOException {
if (bypass) {
env.bypass();
}
preDeleteNamespaceCalled = true;
}
@Override
public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
String name) throws IOException {
postDeleteNamespaceCalled = true;
}
public boolean wasDeleteNamespaceCalled() {
return preDeleteNamespaceCalled && postDeleteNamespaceCalled;
}
public boolean preDeleteNamespaceCalledOnly() {
return preDeleteNamespaceCalled && !postDeleteNamespaceCalled;
}
@Override
public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
NamespaceDescriptor ns) throws IOException {
if (bypass) {
env.bypass();
}
preModifyNamespaceCalled = true;
}
@Override
public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
NamespaceDescriptor ns) throws IOException {
postModifyNamespaceCalled = true;
}
public boolean wasModifyNamespaceCalled() {
return preModifyNamespaceCalled && postModifyNamespaceCalled;
}
public boolean preModifyNamespaceCalledOnly() {
return preModifyNamespaceCalled && !postModifyNamespaceCalled;
}
@Override
public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
String namespace) throws IOException {
preGetNamespaceDescriptorCalled = true;
}
@Override
public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
NamespaceDescriptor ns) throws IOException {
postGetNamespaceDescriptorCalled = true;
}
public boolean wasGetNamespaceDescriptorCalled() {
return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
}
@Override
public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
List<NamespaceDescriptor> descriptors) throws IOException {
if (bypass) {
env.bypass();
}
preListNamespaceDescriptorsCalled = true;
}
@Override
public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
List<NamespaceDescriptor> descriptors) throws IOException {
postListNamespaceDescriptorsCalled = true;
}
public boolean wasListNamespaceDescriptorsCalled() {
return preListNamespaceDescriptorsCalled && postListNamespaceDescriptorsCalled;
}
public boolean preListNamespaceDescriptorsCalledOnly() {
return preListNamespaceDescriptorsCalled && !postListNamespaceDescriptorsCalled;
}
@Deprecated
@Override
public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily
) throws IOException {
}
@Override
public void preAddColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily
) throws IOException {
if (bypass) {
ctx.bypass();
}else{
ctx.shouldBypass();
}
preAddColumnCalled = true;
}
@Deprecated
@Override
public void postAddColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void postAddColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
postAddColumnCalled = true;
}
public boolean wasAddColumnCalled() {
return preAddColumnCalled && postAddColumnCalled;
}
public boolean preAddColumnCalledOnly() {
return preAddColumnCalled && !postAddColumnCalled;
}
@Deprecated
@Override
public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void preModifyColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
if (bypass) {
ctx.bypass();
}
preModifyColumnCalled = true;
}
@Deprecated
@Override
public void postModifyColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void postModifyColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, HColumnDescriptor columnFamily) throws IOException {
postModifyColumnCalled = true;
}
public boolean wasModifyColumnCalled() {
return preModifyColumnCalled && postModifyColumnCalled;
}
public boolean preModifyColumnCalledOnly() {
return preModifyColumnCalled && !postModifyColumnCalled;
}
@Deprecated
@Override
public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, byte[] columnFamily) throws IOException {
}
@Override
public void preDeleteColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, byte[] columnFamily) throws IOException {
if (bypass) {
ctx.bypass();
}
preDeleteColumnCalled = true;
}
@Deprecated
@Override
public void postDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, byte[] columnFamily) throws IOException {
}
@Override
public void postDeleteColumnFamily(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, byte[] columnFamily) throws IOException {
postDeleteColumnCalled = true;
}
public boolean wasDeleteColumnCalled() {
return preDeleteColumnCalled && postDeleteColumnCalled;
}
public boolean preDeleteColumnCalledOnly() {
return preDeleteColumnCalled && !postDeleteColumnCalled;
}
@Override
public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
if (bypass) {
env.bypass();
}
preEnableTableCalled = true;
}
@Override
public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
postEnableTableCalled = true;
}
public boolean wasEnableTableCalled() {
return preEnableTableCalled && postEnableTableCalled;
}
public boolean preEnableTableCalledOnly() {
return preEnableTableCalled && !postEnableTableCalled;
}
@Override
public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
if (bypass) {
env.bypass();
}
preDisableTableCalled = true;
}
@Override
public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
TableName tableName) throws IOException {
postDisableTableCalled = true;
}
public boolean wasDisableTableCalled() {
return preDisableTableCalled && postDisableTableCalled;
}
public boolean preDisableTableCalledOnly() {
return preDisableTableCalled && !postDisableTableCalled;
}
@Override
public void preAbortProcedure(
ObserverContext<MasterCoprocessorEnvironment> ctx,
final ProcedureExecutor<MasterProcedureEnv> procEnv,
final long procId) throws IOException {
preAbortProcedureCalled = true;
}
@Override
public void postAbortProcedure(
ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
postAbortProcedureCalled = true;
}
public boolean wasAbortProcedureCalled() {
return preAbortProcedureCalled && postAbortProcedureCalled;
}
public boolean wasPreAbortProcedureCalledOnly() {
return preAbortProcedureCalled && !postAbortProcedureCalled;
}
@Override
public void preListProcedures(
ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
preListProceduresCalled = true;
}
@Override
public void postListProcedures(
ObserverContext<MasterCoprocessorEnvironment> ctx,
List<ProcedureInfo> procInfoList) throws IOException {
postListProceduresCalled = true;
}
public boolean wasListProceduresCalled() {
return preListProceduresCalled && postListProceduresCalled;
}
public boolean wasPreListProceduresCalledOnly() {
return preListProceduresCalled && !postListProceduresCalled;
}
@Override
public void preListLocks(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
preListLocksCalled = true;
}
@Override
public void postListLocks(ObserverContext<MasterCoprocessorEnvironment> ctx, List<LockInfo> lockInfoList)
throws IOException {
postListLocksCalled = true;
}
public boolean wasListLocksCalled() {
return preListLocksCalled && postListLocksCalled;
}
public boolean wasPreListLocksCalledOnly() {
return preListLocksCalled && !postListLocksCalled;
}
@Override
public void preMove(ObserverContext<MasterCoprocessorEnvironment> env,
HRegionInfo region, ServerName srcServer, ServerName destServer)
throws IOException {
if (bypass) {
env.bypass();
}
preMoveCalled = true;
}
@Override
public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, HRegionInfo region,
ServerName srcServer, ServerName destServer)
throws IOException {
postMoveCalled = true;
}
public boolean wasMoveCalled() {
return preMoveCalled && postMoveCalled;
}
public boolean preMoveCalledOnly() {
return preMoveCalled && !postMoveCalled;
}
@Override
public void preAssign(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo) throws IOException {
if (bypass) {
env.bypass();
}
preAssignCalled = true;
}
@Override
public void postAssign(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo) throws IOException {
postAssignCalled = true;
}
public boolean wasAssignCalled() {
return preAssignCalled && postAssignCalled;
}
public boolean preAssignCalledOnly() {
return preAssignCalled && !postAssignCalled;
}
@Override
public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo, final boolean force) throws IOException {
if (bypass) {
env.bypass();
}
preUnassignCalled = true;
}
@Override
public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
final HRegionInfo regionInfo, final boolean force) throws IOException {
postUnassignCalled = true;
}
public boolean wasUnassignCalled() {
return preUnassignCalled && postUnassignCalled;
}
public boolean preUnassignCalledOnly() {
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 {
if (bypass) {
env.bypass();
}
preBalanceCalled = true;
}
@Override
public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env,
List<RegionPlan> plans) throws IOException {
postBalanceCalled = true;
}
public boolean wasBalanceCalled() {
return preBalanceCalled && postBalanceCalled;
}
public boolean preBalanceCalledOnly() {
return preBalanceCalled && !postBalanceCalled;
}
@Override
public boolean preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env, boolean b)
throws IOException {
if (bypass) {
env.bypass();
}
preBalanceSwitchCalled = true;
return b;
}
@Override
public void postBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env,
boolean oldValue, boolean newValue) throws IOException {
postBalanceSwitchCalled = true;
}
public boolean wasBalanceSwitchCalled() {
return preBalanceSwitchCalled && postBalanceSwitchCalled;
}
public boolean preBalanceSwitchCalledOnly() {
return preBalanceSwitchCalled && !postBalanceSwitchCalled;
}
@Override
public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> env)
throws IOException {
preShutdownCalled = true;
}
public boolean wasShutdownCalled() {
return preShutdownCalled;
}
@Override
public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
throws IOException {
preStopMasterCalled = true;
}
public boolean wasStopMasterCalled() {
return preStopMasterCalled;
}
@Override
public void preMasterInitialization(
ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
preMasterInitializationCalled = true;
}
public boolean wasMasterInitializationCalled(){
return preMasterInitializationCalled;
}
@Override
public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
throws IOException {
postStartMasterCalled = true;
}
public boolean wasStartMasterCalled() {
return postStartMasterCalled;
}
@Override
public void start(CoprocessorEnvironment env) throws IOException {
startCalled = true;
}
@Override
public void stop(CoprocessorEnvironment env) throws IOException {
stopCalled = true;
}
public boolean wasStarted() { return startCalled; }
public boolean wasStopped() { return stopCalled; }
@Override
public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
preSnapshotCalled = true;
}
@Override
public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
postSnapshotCalled = true;
}
public boolean wasSnapshotCalled() {
return preSnapshotCalled && postSnapshotCalled;
}
@Override
public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot) throws IOException {
preListSnapshotCalled = true;
}
@Override
public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot) throws IOException {
postListSnapshotCalled = true;
}
public boolean wasListSnapshotCalled() {
return preListSnapshotCalled && postListSnapshotCalled;
}
@Override
public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
preCloneSnapshotCalled = true;
}
@Override
public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
postCloneSnapshotCalled = true;
}
public boolean wasCloneSnapshotCalled() {
return preCloneSnapshotCalled && postCloneSnapshotCalled;
}
@Override
public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
preRestoreSnapshotCalled = true;
}
@Override
public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
postRestoreSnapshotCalled = true;
}
public boolean wasRestoreSnapshotCalled() {
return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
}
@Override
public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot) throws IOException {
preDeleteSnapshotCalled = true;
}
@Override
public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot) throws IOException {
postDeleteSnapshotCalled = true;
}
public boolean wasDeleteSnapshotCalled() {
return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
}
@Deprecated
@Override
public void preCreateTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env,
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
}
@Override
public void preCreateTableAction(
final ObserverContext<MasterCoprocessorEnvironment> env,
final HTableDescriptor desc,
final HRegionInfo[] regions) throws IOException {
if (bypass) {
env.bypass();
}
preCreateTableActionCalled = true;
}
@Deprecated
@Override
public void postCreateTableHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx,
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
}
@Override
public void postCompletedCreateTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HTableDescriptor desc,
final HRegionInfo[] regions) throws IOException {
postCompletedCreateTableActionCalled = true;
tableCreationLatch.countDown();
}
public boolean wasPreCreateTableActionCalled(){
return preCreateTableActionCalled;
}
public boolean wasCreateTableActionCalled() {
return preCreateTableActionCalled && postCompletedCreateTableActionCalled;
}
public boolean wasCreateTableActionCalledOnly() {
return preCreateTableActionCalled && !postCompletedCreateTableActionCalled;
}
@Deprecated
@Override
public void preDeleteTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
throws IOException {
}
@Deprecated
@Override
public void postDeleteTableHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
throws IOException {
}
@Override
public void preDeleteTableAction(
final ObserverContext<MasterCoprocessorEnvironment> env, final TableName tableName)
throws IOException {
if (bypass) {
env.bypass();
}
preDeleteTableActionCalled = true;
}
@Override
public void postCompletedDeleteTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
postCompletedDeleteTableActionCalled = true;
tableDeletionLatch.countDown();
}
public boolean wasDeleteTableActionCalled() {
return preDeleteTableActionCalled && postCompletedDeleteTableActionCalled;
}
public boolean wasDeleteTableActionCalledOnly() {
return preDeleteTableActionCalled && !postCompletedDeleteTableActionCalled;
}
@Deprecated
@Override
public void preTruncateTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
throws IOException {
}
@Deprecated
@Override
public void postTruncateTableHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
throws IOException {
}
@Override
public void preTruncateTableAction(
final ObserverContext<MasterCoprocessorEnvironment> env, final TableName tableName)
throws IOException {
if (bypass) {
env.bypass();
}
preTruncateTableActionCalled = true;
}
@Override
public void postCompletedTruncateTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
postCompletedTruncateTableActionCalled = true;
}
public boolean wasTruncateTableActionCalled() {
return preTruncateTableActionCalled && postCompletedTruncateTableActionCalled;
}
public boolean wasTruncateTableActionCalledOnly() {
return preTruncateTableActionCalled && !postCompletedTruncateTableActionCalled;
}
@Deprecated
@Override
public void preModifyTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
HTableDescriptor htd) throws IOException {
}
@Deprecated
@Override
public void postModifyTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
HTableDescriptor htd) throws IOException {
}
@Override
public void preModifyTableAction(
final ObserverContext<MasterCoprocessorEnvironment> env,
final TableName tableName,
final HTableDescriptor htd) throws IOException {
if (bypass) {
env.bypass();
}
preModifyTableActionCalled = true;
}
@Override
public void postCompletedModifyTableAction(
final ObserverContext<MasterCoprocessorEnvironment> env,
final TableName tableName,
final HTableDescriptor htd) throws IOException {
postCompletedModifyTableActionCalled = true;
}
public boolean wasModifyTableActionCalled() {
return preModifyTableActionCalled && postCompletedModifyTableActionCalled;
}
public boolean wasModifyTableActionCalledOnly() {
return preModifyTableActionCalled && !postCompletedModifyTableActionCalled;
}
@Deprecated
@Override
public void preAddColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void preAddColumnFamilyAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName,
final HColumnDescriptor columnFamily) throws IOException {
if (bypass) {
ctx.bypass();
}
preAddColumnFamilyActionCalled = true;
}
@Deprecated
@Override
public void postAddColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void postCompletedAddColumnFamilyAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName,
final HColumnDescriptor columnFamily) throws IOException {
postCompletedAddColumnFamilyActionCalled = true;
}
public boolean wasAddColumnFamilyActionCalled() {
return preAddColumnFamilyActionCalled && postCompletedAddColumnFamilyActionCalled;
}
public boolean preAddColumnFamilyActionCalledOnly() {
return preAddColumnFamilyActionCalled && !postCompletedAddColumnFamilyActionCalled;
}
@Deprecated
@Override
public void preModifyColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void preModifyColumnFamilyAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName,
final HColumnDescriptor columnFamily) throws IOException {
if (bypass) {
ctx.bypass();
}
preModifyColumnFamilyActionCalled = true;
}
@Deprecated
@Override
public void postModifyColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
HColumnDescriptor columnFamily) throws IOException {
}
@Override
public void postCompletedModifyColumnFamilyAction(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
HColumnDescriptor columnFamily) throws IOException {
postCompletedModifyColumnFamilyActionCalled = true;
}
public boolean wasModifyColumnFamilyActionCalled() {
return preModifyColumnFamilyActionCalled && postCompletedModifyColumnFamilyActionCalled;
}
public boolean preModifyColumnFamilyActionCalledOnly() {
return preModifyColumnFamilyActionCalled && !postCompletedModifyColumnFamilyActionCalled;
}
@Deprecated
@Override
public void preDeleteColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
byte[] columnFamily) throws IOException {
}
@Override
public void preDeleteColumnFamilyAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName,
final byte[] columnFamily) throws IOException {
if (bypass) {
ctx.bypass();
}
preDeleteColumnFamilyActionCalled = true;
}
@Deprecated
@Override
public void postDeleteColumnHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
byte[] columnFamily) throws IOException {
}
@Override
public void postCompletedDeleteColumnFamilyAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName,
final byte[] columnFamily) throws IOException {
postCompletedDeleteColumnFamilyActionCalled = true;
}
public boolean wasDeleteColumnFamilyActionCalled() {
return preDeleteColumnFamilyActionCalled && postCompletedDeleteColumnFamilyActionCalled;
}
public boolean preDeleteColumnFamilyActionCalledOnly() {
return preDeleteColumnFamilyActionCalled && !postCompletedDeleteColumnFamilyActionCalled;
}
@Deprecated
@Override
public void preEnableTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
throws IOException {
}
@Deprecated
@Override
public void postEnableTableHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
throws IOException {
}
@Override
public void preEnableTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
if (bypass) {
ctx.bypass();
}
preEnableTableActionCalled = true;
}
@Override
public void postCompletedEnableTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
postCompletedEnableTableActionCalled = true;
}
public boolean wasEnableTableActionCalled() {
return preEnableTableActionCalled && postCompletedEnableTableActionCalled;
}
public boolean preEnableTableActionCalledOnly() {
return preEnableTableActionCalled && !postCompletedEnableTableActionCalled;
}
@Override
public void preDisableTableHandler(
ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
throws IOException {
}
@Override
public void postDisableTableHandler(
ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
throws IOException {
}
@Override
public void preDisableTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
if (bypass) {
ctx.bypass();
}
preDisableTableActionCalled = true;
}
@Override
public void postCompletedDisableTableAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
throws IOException {
postCompletedDisableTableActionCalled = true;
}
public boolean wasDisableTableActionCalled() {
return preDisableTableActionCalled && postCompletedDisableTableActionCalled;
}
public boolean preDisableTableActionCalledOnly() {
return preDisableTableActionCalled && !postCompletedDisableTableActionCalled;
}
@Override
public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<TableName> tableNamesList, List<HTableDescriptor> descriptors, String regex)
throws IOException {
preGetTableDescriptorsCalled = true;
}
@Override
public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<TableName> tableNamesList, List<HTableDescriptor> descriptors,
String regex) throws IOException {
postGetTableDescriptorsCalled = true;
}
public boolean wasGetTableDescriptorsCalled() {
return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
}
@Override
public void preGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<HTableDescriptor> descriptors, String regex) throws IOException {
preGetTableNamesCalled = true;
}
@Override
public void postGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<HTableDescriptor> descriptors, String regex) throws IOException {
postGetTableNamesCalled = true;
}
public boolean wasGetTableNamesCalled() {
return preGetTableNamesCalled && postGetTableNamesCalled;
}
@Override
public void preTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName) throws IOException {
}
@Override
public void postTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName) throws IOException {
}
@Override
public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final Quotas quotas) throws IOException {
}
@Override
public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final Quotas quotas) throws IOException {
}
@Override
public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final TableName tableName, final Quotas quotas) throws IOException {
}
@Override
public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final TableName tableName, final Quotas quotas) throws IOException {
}
@Override
public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final String namespace, final Quotas quotas) throws IOException {
}
@Override
public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String userName, final String namespace, final Quotas quotas) throws IOException {
}
@Override
public void preSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName, final Quotas quotas) throws IOException {
}
@Override
public void postSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final TableName tableName, final Quotas quotas) throws IOException {
}
@Override
public void preSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String namespace, final Quotas quotas) throws IOException {
}
@Override
public void postSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final String namespace, final Quotas quotas) throws IOException {
}
@Override
public void preMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
}
@Override
public void postMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<Address> servers, Set<TableName> tables,String targetGroup) throws IOException {
}
@Override
public void preMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<Address> servers, String targetGroup) throws IOException {
}
@Override
public void postMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<Address> servers, String targetGroup) throws IOException {
}
@Override
public void preMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<TableName> tables, String targetGroupGroup) throws IOException {
}
@Override
public void postMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
Set<TableName> tables, String targetGroup) throws IOException {
}
@Override
public void preAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String name) throws IOException {
}
@Override
public void postAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String name) throws IOException {
}
@Override
public void preRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String name) throws IOException {
}
@Override
public void postRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String name) throws IOException {
}
@Override
public void preBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String groupName) throws IOException {
}
@Override
public void postBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
String groupName, boolean balancerRan) throws IOException {
}
@Override
public void preRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
TableName tableName, HRegionInfo[] regionInfos, LockProcedure.LockType type,
String description) throws IOException {
preRequestLockCalled = true;
}
@Override
public void postRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
TableName tableName, HRegionInfo[] regionInfos, LockProcedure.LockType type,
String description) throws IOException {
postRequestLockCalled = true;
}
@Override
public void preLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx,
LockProcedure proc, boolean keepAlive) throws IOException {
preLockHeartbeatCalled = true;
}
@Override
public void postLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx,
LockProcedure proc, boolean keepAlive) throws IOException {
postLockHeartbeatCalled = true;
}
public boolean preAndPostForQueueLockAndHeartbeatLockCalled() {
return preRequestLockCalled && postRequestLockCalled && preLockHeartbeatCalled &&
postLockHeartbeatCalled;
}
@Override
public void preSplitRegion(
final ObserverContext<MasterCoprocessorEnvironment> c,
final TableName tableName,
final byte[] splitRow) throws IOException {
}
@Override
public void preSplitRegionAction(
final ObserverContext<MasterCoprocessorEnvironment> c,
final TableName tableName,
final byte[] splitRow) throws IOException {
}
@Override
public void postCompletedSplitRegionAction(
final ObserverContext<MasterCoprocessorEnvironment> c,
final HRegionInfo regionInfoA,
final HRegionInfo regionInfoB) throws IOException {
}
@Override
public void preSplitRegionBeforePONRAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final byte[] splitKey,
final List<Mutation> metaEntries) throws IOException {
}
@Override
public void preSplitRegionAfterPONRAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
}
@Override
public void postRollBackSplitRegionAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
}
@Override
public void preMergeRegionsAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge) throws IOException {
}
@Override
public void postCompletedMergeRegionsAction(
final ObserverContext<MasterCoprocessorEnvironment> c,
final HRegionInfo[] regionsToMerge,
final HRegionInfo mergedRegion) throws IOException {
}
@Override
public void preMergeRegionsCommitAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge,
final List<Mutation> metaEntries) throws IOException {
}
@Override
public void postMergeRegionsCommitAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge,
final HRegionInfo mergedRegion) throws IOException {
}
@Override
public void postRollBackMergeRegionsAction(
final ObserverContext<MasterCoprocessorEnvironment> ctx,
final HRegionInfo[] regionsToMerge) throws IOException {
}
}
private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
private static byte[] TEST_SNAPSHOT = Bytes.toBytes("observed_snapshot");
private static TableName TEST_CLONE = TableName.valueOf("observed_clone");
private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
private static byte[] TEST_FAMILY2 = Bytes.toBytes("fam2");
@Rule public TestName name = new TestName();
@BeforeClass
public static void setupBeforeClass() throws Exception {
Configuration conf = UTIL.getConfiguration();
conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
CPMasterObserver.class.getName());
// We need more than one data server on this test
UTIL.startMiniCluster(2);
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
UTIL.shutdownMiniCluster();
}
@Test (timeout=180000)
public void testStarted() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
assertTrue("Master should be active", master.isActiveMaster());
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
assertNotNull("CoprocessorHost should not be null", host);
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
// check basic lifecycle
assertTrue("MasterObserver should have been started", cp.wasStarted());
assertTrue("preMasterInitialization() hook should have been called",
cp.wasMasterInitializationCalled());
assertTrue("postStartMaster() hook should have been called",
cp.wasStartMasterCalled());
}
@Test (timeout=180000)
public void testTableOperations() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
final TableName tableName = TableName.valueOf(name.getMethodName());
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.enableBypass(true);
cp.resetStates();
assertFalse("No table created yet", cp.wasCreateTableCalled());
// create a table
HTableDescriptor htd = new HTableDescriptor(tableName);
htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
try(Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
Admin admin = connection.getAdmin()) {
tableCreationLatch = new CountDownLatch(1);
admin.createTable(htd, Arrays.copyOfRange(HBaseTestingUtility.KEYS,
1, HBaseTestingUtility.KEYS.length));
// preCreateTable can't bypass default action.
assertTrue("Test table should be created", cp.wasCreateTableCalled());
tableCreationLatch.await();
assertTrue("Table pre create handler called.", cp
.wasPreCreateTableActionCalled());
assertTrue("Table create handler should be called.",
cp.wasCreateTableActionCalled());
RegionLocator regionLocator = connection.getRegionLocator(htd.getTableName());
List<HRegionLocation> regions = regionLocator.getAllRegionLocations();
admin.mergeRegionsAsync(regions.get(0).getRegionInfo().getEncodedNameAsBytes(),
regions.get(1).getRegionInfo().getEncodedNameAsBytes(), true);
assertTrue("Coprocessor should have been called on region merge",
cp.wasMergeRegionsCalled());
tableCreationLatch = new CountDownLatch(1);
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
// preDisableTable can't bypass default action.
assertTrue("Coprocessor should have been called on table disable",
cp.wasDisableTableCalled());
assertTrue("Disable table handler should be called.",
cp.wasDisableTableActionCalled());
// enable
assertFalse(cp.wasEnableTableCalled());
admin.enableTable(tableName);
assertTrue(admin.isTableEnabled(tableName));
// preEnableTable can't bypass default action.
assertTrue("Coprocessor should have been called on table enable",
cp.wasEnableTableCalled());
assertTrue("Enable table handler should be called.",
cp.wasEnableTableActionCalled());
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
// modify table
htd.setMaxFileSize(512 * 1024 * 1024);
modifyTableSync(admin, tableName, htd);
// preModifyTable can't bypass default action.
assertTrue("Test table should have been modified",
cp.wasModifyTableCalled());
// add a column family
admin.addColumnFamily(tableName, new HColumnDescriptor(TEST_FAMILY2));
assertTrue("New column family shouldn't have been added to test table",
cp.preAddColumnCalledOnly());
// modify a column family
HColumnDescriptor hcd1 = new HColumnDescriptor(TEST_FAMILY2);
hcd1.setMaxVersions(25);
admin.modifyColumnFamily(tableName, hcd1);
assertTrue("Second column family should be modified",
cp.preModifyColumnCalledOnly());
// truncate table
admin.truncateTable(tableName, false);
// delete table
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
deleteTable(admin, tableName);
assertFalse("Test table should have been deleted",
admin.tableExists(tableName));
// preDeleteTable can't bypass default action.
assertTrue("Coprocessor should have been called on table delete",
cp.wasDeleteTableCalled());
assertTrue("Delete table handler should be called.",
cp.wasDeleteTableActionCalled());
// turn off bypass, run the tests again
cp.enableBypass(false);
cp.resetStates();
admin.createTable(htd);
assertTrue("Test table should be created", cp.wasCreateTableCalled());
tableCreationLatch.await();
assertTrue("Table pre create handler called.", cp
.wasPreCreateTableActionCalled());
assertTrue("Table create handler should be called.",
cp.wasCreateTableActionCalled());
// disable
assertFalse(cp.wasDisableTableCalled());
assertFalse(cp.wasDisableTableActionCalled());
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
assertTrue("Coprocessor should have been called on table disable",
cp.wasDisableTableCalled());
assertTrue("Disable table handler should be called.",
cp.wasDisableTableActionCalled());
// modify table
htd.setMaxFileSize(512 * 1024 * 1024);
modifyTableSync(admin, tableName, htd);
assertTrue("Test table should have been modified",
cp.wasModifyTableCalled());
// add a column family
admin.addColumnFamily(tableName, new HColumnDescriptor(TEST_FAMILY2));
assertTrue("New column family should have been added to test table",
cp.wasAddColumnCalled());
assertTrue("Add column handler should be called.",
cp.wasAddColumnFamilyActionCalled());
// modify a column family
HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
hcd.setMaxVersions(25);
admin.modifyColumnFamily(tableName, hcd);
assertTrue("Second column family should be modified",
cp.wasModifyColumnCalled());
assertTrue("Modify table handler should be called.",
cp.wasModifyColumnFamilyActionCalled());
// enable
assertFalse(cp.wasEnableTableCalled());
assertFalse(cp.wasEnableTableActionCalled());
admin.enableTable(tableName);
assertTrue(admin.isTableEnabled(tableName));
assertTrue("Coprocessor should have been called on table enable",
cp.wasEnableTableCalled());
assertTrue("Enable table handler should be called.",
cp.wasEnableTableActionCalled());
// disable again
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
// delete column
assertFalse("No column family deleted yet", cp.wasDeleteColumnCalled());
assertFalse("Delete table column handler should not be called.",
cp.wasDeleteColumnFamilyActionCalled());
admin.deleteColumnFamily(tableName, TEST_FAMILY2);
HTableDescriptor tableDesc = admin.getTableDescriptor(tableName);
assertNull("'"+Bytes.toString(TEST_FAMILY2)+"' should have been removed",
tableDesc.getFamily(TEST_FAMILY2));
assertTrue("Coprocessor should have been called on column delete",
cp.wasDeleteColumnCalled());
assertTrue("Delete table column handler should be called.",
cp.wasDeleteColumnFamilyActionCalled());
// delete table
assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
assertFalse("Delete table handler should not be called.",
cp.wasDeleteTableActionCalled());
deleteTable(admin, tableName);
assertFalse("Test table should have been deleted",
admin.tableExists(tableName));
assertTrue("Coprocessor should have been called on table delete",
cp.wasDeleteTableCalled());
assertTrue("Delete table handler should be called.",
cp.wasDeleteTableActionCalled());
}
}
@Test (timeout=180000)
public void testSnapshotOperations() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
// create a table
HTableDescriptor htd = new HTableDescriptor(tableName);
htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
Admin admin = UTIL.getAdmin();
tableCreationLatch = new CountDownLatch(1);
admin.createTable(htd);
tableCreationLatch.await();
tableCreationLatch = new CountDownLatch(1);
admin.disableTable(tableName);
assertTrue(admin.isTableDisabled(tableName));
try {
// Test snapshot operation
assertFalse("Coprocessor should not have been called yet",
cp.wasSnapshotCalled());
admin.snapshot(TEST_SNAPSHOT, tableName);
assertTrue("Coprocessor should have been called on snapshot",
cp.wasSnapshotCalled());
//Test list operation
admin.listSnapshots();
assertTrue("Coprocessor should have been called on snapshot list",
cp.wasListSnapshotCalled());
// Test clone operation
admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
assertTrue("Coprocessor should have been called on snapshot clone",
cp.wasCloneSnapshotCalled());
assertFalse("Coprocessor restore should not have been called on snapshot clone",
cp.wasRestoreSnapshotCalled());
admin.disableTable(TEST_CLONE);
assertTrue(admin.isTableDisabled(tableName));
deleteTable(admin, TEST_CLONE);
// Test restore operation
cp.resetStates();
admin.restoreSnapshot(TEST_SNAPSHOT);
assertTrue("Coprocessor should have been called on snapshot restore",
cp.wasRestoreSnapshotCalled());
assertFalse("Coprocessor clone should not have been called on snapshot restore",
cp.wasCloneSnapshotCalled());
admin.deleteSnapshot(TEST_SNAPSHOT);
assertTrue("Coprocessor should have been called on snapshot delete",
cp.wasDeleteSnapshotCalled());
} finally {
deleteTable(admin, tableName);
}
}
@Test (timeout=180000)
public void testNamespaceOperations() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
String testNamespace = "observed_ns";
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.enableBypass(false);
cp.resetStates();
// create a table
Admin admin = UTIL.getAdmin();
admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
assertNotNull(admin.getNamespaceDescriptor(testNamespace));
assertTrue("Test namespace descriptor should have been called",
cp.wasGetNamespaceDescriptorCalled());
// turn off bypass, run the tests again
cp.enableBypass(true);
cp.resetStates();
boolean expected = false;
try {
admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
} catch (BypassCoprocessorException ce) {
expected = true;
}
assertTrue(expected);
assertTrue("Test namespace should not have been modified",
cp.preModifyNamespaceCalledOnly());
assertNotNull(admin.getNamespaceDescriptor(testNamespace));
assertTrue("Test namespace descriptor should have been called",
cp.wasGetNamespaceDescriptorCalled());
expected = false;
try {
admin.deleteNamespace(testNamespace);
} catch (BypassCoprocessorException ce) {
expected = true;
}
assertTrue(expected);
assertTrue("Test namespace should not have been deleted", cp.preDeleteNamespaceCalledOnly());
assertNotNull(admin.getNamespaceDescriptor(testNamespace));
assertTrue("Test namespace descriptor should have been called",
cp.wasGetNamespaceDescriptorCalled());
cp.enableBypass(false);
cp.resetStates();
// delete table
admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
assertTrue("Test namespace should have been modified", cp.wasModifyNamespaceCalled());
admin.deleteNamespace(testNamespace);
assertTrue("Test namespace should have been deleted", cp.wasDeleteNamespaceCalled());
cp.enableBypass(true);
cp.resetStates();
expected = false;
try {
admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
} catch (BypassCoprocessorException ce) {
expected = true;
}
assertTrue(expected);
assertTrue("Test namespace should not be created", cp.preCreateNamespaceCalledOnly());
// turn on bypass, run the test
cp.enableBypass(true);
cp.resetStates();
admin.listNamespaceDescriptors();
assertTrue("post listNamespace should not have been called",
cp.preListNamespaceDescriptorsCalledOnly());
// turn off bypass, run the tests again
cp.enableBypass(false);
cp.resetStates();
admin.listNamespaceDescriptors();
assertTrue("post listNamespace should have been called",
cp.wasListNamespaceDescriptorsCalled());
}
private void modifyTableSync(Admin admin, TableName tableName, HTableDescriptor htd)
throws IOException {
admin.modifyTable(tableName, htd);
//wait until modify table finishes
for (int t = 0; t < 100; t++) { //10 sec timeout
HTableDescriptor td = admin.getTableDescriptor(htd.getTableName());
if (td.equals(htd)) {
break;
}
Threads.sleep(100);
}
}
@Test (timeout=180000)
public void testRegionTransitionOperations() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName());
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.enableBypass(false);
cp.resetStates();
Table table = UTIL.createMultiRegionTable(tableName, TEST_FAMILY);
try (RegionLocator r = UTIL.getConnection().getRegionLocator(tableName)) {
UTIL.waitUntilAllRegionsAssigned(tableName);
List<HRegionLocation> regions = r.getAllRegionLocations();
HRegionLocation firstGoodPair = null;
for (HRegionLocation e: regions) {
if (e.getServerName() != null) {
firstGoodPair = e;
break;
}
}
assertNotNull("Found a non-null entry", firstGoodPair);
LOG.info("Found " + firstGoodPair.toString());
// Try to force a move
Collection<ServerName> servers = master.getClusterStatus().getServers();
String destName = null;
String serverNameForFirstRegion = firstGoodPair.getServerName().toString();
LOG.info("serverNameForFirstRegion=" + serverNameForFirstRegion);
ServerName masterServerName = master.getServerName();
boolean found = false;
// Find server that is NOT carrying the first region
for (ServerName info : servers) {
LOG.info("ServerName=" + info);
if (!serverNameForFirstRegion.equals(info.getServerName())
&& !masterServerName.equals(info)) {
destName = info.toString();
found = true;
break;
}
}
assertTrue("Found server", found);
LOG.info("Found " + destName);
master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
firstGoodPair.getRegionInfo().getEncodedNameAsBytes(),Bytes.toBytes(destName)));
assertTrue("Coprocessor should have been called on region move",
cp.wasMoveCalled());
// make sure balancer is on
master.balanceSwitch(true);
assertTrue("Coprocessor should have been called on balance switch",
cp.wasBalanceSwitchCalled());
// turn balancer off
master.balanceSwitch(false);
// wait for assignments to finish, if any
UTIL.waitUntilNoRegionsInTransition();
// move half the open regions from RS 0 to RS 1
HRegionServer rs = cluster.getRegionServer(0);
byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
//Make sure no regions are in transition now
UTIL.waitUntilNoRegionsInTransition();
List<HRegionInfo> openRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
int moveCnt = openRegions.size()/2;
for (int i=0; i<moveCnt; i++) {
HRegionInfo info = openRegions.get(i);
if (!info.isMetaTable()) {
master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
openRegions.get(i).getEncodedNameAsBytes(), destRS));
}
}
//Make sure no regions are in transition now
UTIL.waitUntilNoRegionsInTransition();
// now trigger a balance
master.balanceSwitch(true);
boolean balanceRun = master.balance();
assertTrue("Coprocessor should be called on region rebalancing",
cp.wasBalanceCalled());
} finally {
Admin admin = UTIL.getAdmin();
admin.disableTable(tableName);
deleteTable(admin, tableName);
}
}
@Test (timeout=180000)
public void testTableDescriptorsEnumeration() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
GetTableDescriptorsRequest req =
RequestConverter.buildGetTableDescriptorsRequest((List<TableName>)null);
master.getMasterRpcServices().getTableDescriptors(null, req);
assertTrue("Coprocessor should be called on table descriptors request",
cp.wasGetTableDescriptorsCalled());
}
@Test (timeout=180000)
public void testTableNamesEnumeration() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
master.getMasterRpcServices().getTableNames(null,
GetTableNamesRequest.newBuilder().build());
assertTrue("Coprocessor should be called on table names request",
cp.wasGetTableNamesCalled());
}
@Test (timeout=180000)
public void testAbortProcedureOperation() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
master.abortProcedure(1, true);
assertTrue(
"Coprocessor should be called on abort procedure request",
cp.wasAbortProcedureCalled());
}
@Test (timeout=180000)
public void testListProceduresOperation() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
master.listProcedures();
assertTrue(
"Coprocessor should be called on list procedures request",
cp.wasListProceduresCalled());
}
@Test (timeout=180000)
public void testListLocksOperation() throws Exception {
MiniHBaseCluster cluster = UTIL.getHBaseCluster();
HMaster master = cluster.getMaster();
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
master.listLocks();
assertTrue(
"Coprocessor should be called on list locks request",
cp.wasListLocksCalled());
}
private void deleteTable(Admin admin, TableName tableName) throws Exception {
// NOTE: We need a latch because admin is not sync,
// so the postOp coprocessor method may be called after the admin operation returned.
tableDeletionLatch = new CountDownLatch(1);
admin.deleteTable(tableName);
tableDeletionLatch.await();
tableDeletionLatch = new CountDownLatch(1);
}
@Test
public void testQueueLockAndLockHeartbeatOperations() throws Exception {
HMaster master = UTIL.getMiniHBaseCluster().getMaster();
CPMasterObserver cp = (CPMasterObserver)master.getMasterCoprocessorHost().findCoprocessor(
CPMasterObserver.class.getName());
cp.resetStates();
final TableName tableName = TableName.valueOf("testLockedTable");
long procId = master.getLockManager().remoteLocks().requestTableLock(tableName,
LockProcedure.LockType.EXCLUSIVE, "desc", null);
master.getLockManager().remoteLocks().lockHeartbeat(procId, false);
assertTrue(cp.preAndPostForQueueLockAndHeartbeatLockCalled());
ProcedureTestingUtility.waitNoProcedureRunning(master.getMasterProcedureExecutor());
ProcedureTestingUtility.assertProcNotFailed(master.getMasterProcedureExecutor(), procId);
}
}