Skip to content

Commit

Permalink
HBASE-20706 Prevent MTP from trying to reopen non-OPEN regions
Browse files Browse the repository at this point in the history
ModifyTableProcedure is using MoveRegionProcedure in a way
that was unintended from the original implementation. As such,
we have to guard against certain usages of it. We know we can
re-open OPEN regions, but regions in OPENING will similarly
soon be OPEN (thus, we want to reopen those regions too).

Signed-off-by: Michael Stack <stack@apache.org>
Signed-off-by: zhangduo <zhangduo@apache.org>
  • Loading branch information
joshelser committed Jun 20, 2018
1 parent d1cad1a commit e989a99
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 20 deletions.
Expand Up @@ -34,6 +34,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.ServerName;
Expand Down Expand Up @@ -569,23 +570,45 @@ public boolean hasTableRegionStates(final TableName tableName) {
return !getTableRegionStates(tableName).isEmpty();
}

/**
* @return Returns regions for a table which are open or about to be open (OPEN or OPENING)
*/
public List<RegionInfo> getOpenRegionsOfTable(final TableName table) {
// We want to get regions which are already open on the cluster or are about to be open.
// The use-case is for identifying regions which need to be re-opened to ensure they see some
// new configuration. Regions in OPENING now are presently being opened by a RS, so we can
// assume that they will imminently be OPEN but may not see our configuration change
return getRegionsOfTable(
table, (state) -> state.isInState(State.OPEN) || state.isInState(State.OPENING));
}

/**
* @return Return online regions of table; does not include OFFLINE or SPLITTING regions.
*/
public List<RegionInfo> getRegionsOfTable(final TableName table) {
return getRegionsOfTable(table, false);
}

/**
* @return Return online regions of table; does not include OFFLINE or SPLITTING regions.
*/
public List<RegionInfo> getRegionsOfTable(final TableName table, boolean offline) {
return getRegionsOfTable(table, (state) -> include(state, offline));
}

/**
* @return Return the regions of the table; does not include OFFLINE unless you set
* <code>offline</code> to true. Does not include regions that are in the
* {@link State#SPLIT} state.
*/
public List<RegionInfo> getRegionsOfTable(final TableName table, final boolean offline) {
public List<RegionInfo> getRegionsOfTable(
final TableName table, Predicate<RegionStateNode> filter) {
final ArrayList<RegionStateNode> nodes = getTableRegionStateNodes(table);
final ArrayList<RegionInfo> hris = new ArrayList<RegionInfo>(nodes.size());
for (RegionStateNode node: nodes) {
if (include(node, offline)) hris.add(node.getRegionInfo());
if (filter.test(node)) {
hris.add(node.getRegionInfo());
}
}
return hris;
}
Expand Down
Expand Up @@ -56,7 +56,6 @@ public class ModifyTableProcedure
private TableDescriptor modifiedTableDescriptor;
private boolean deleteColumnFamilyInModify;

private List<RegionInfo> regionInfoList;
private Boolean traceEnabled = null;

public ModifyTableProcedure() {
Expand All @@ -80,7 +79,6 @@ public ModifyTableProcedure(final MasterProcedureEnv env, final TableDescriptor

private void initilize() {
this.unmodifiedTableDescriptor = null;
this.regionInfoList = null;
this.traceEnabled = null;
this.deleteColumnFamilyInModify = false;
}
Expand Down Expand Up @@ -125,7 +123,7 @@ protected Flow executeFromState(final MasterProcedureEnv env, final ModifyTableS
case MODIFY_TABLE_REOPEN_ALL_REGIONS:
if (env.getAssignmentManager().isTableEnabled(getTableName())) {
addChildProcedure(env.getAssignmentManager()
.createReopenProcedures(getRegionInfoList(env)));
.createReopenProcedures(getOpenRegionInfoList(env)));
}
return Flow.NO_MORE_STATE;
default:
Expand Down Expand Up @@ -433,11 +431,20 @@ private void runCoprocessorAction(final MasterProcedureEnv env, final ModifyTabl
}
}

/**
* Fetches all Regions for a table. Cache the result of this method if you need to use it multiple
* times. Be aware that it may change over in between calls to this procedure.
*/
private List<RegionInfo> getRegionInfoList(final MasterProcedureEnv env) throws IOException {
if (regionInfoList == null) {
regionInfoList = env.getAssignmentManager().getRegionStates()
.getRegionsOfTable(getTableName());
}
return regionInfoList;
return env.getAssignmentManager().getRegionStates().getRegionsOfTable(getTableName());
}

/**
* Fetches all open or soon to be open Regions for a table. Cache the result of this method if
* you need to use it multiple times. Be aware that it may change over in between calls to this
* procedure.
*/
private List<RegionInfo> getOpenRegionInfoList(final MasterProcedureEnv env) throws IOException {
return env.getAssignmentManager().getRegionStates().getOpenRegionsOfTable(getTableName());
}
}
Expand Up @@ -26,7 +26,10 @@
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.procedure2.Procedure;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
Expand Down Expand Up @@ -201,24 +204,25 @@ public void testRecoveryAndDoubleExecutionOffline() throws Exception {
ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);

// Modify multiple properties of the table.
HTableDescriptor htd = new HTableDescriptor(UTIL.getAdmin().getTableDescriptor(tableName));
boolean newCompactionEnableOption = htd.isCompactionEnabled() ? false : true;
htd.setCompactionEnabled(newCompactionEnableOption);
htd.addFamily(new HColumnDescriptor(cf2));
htd.removeFamily(Bytes.toBytes(cf3));
htd.setRegionReplication(3);
TableDescriptor oldDescriptor = UTIL.getAdmin().getDescriptor(tableName);
TableDescriptor newDescriptor = TableDescriptorBuilder.newBuilder(oldDescriptor)
.setCompactionEnabled(!oldDescriptor.isCompactionEnabled())
.setColumnFamily(ColumnFamilyDescriptorBuilder.of(cf2))
.removeColumnFamily(Bytes.toBytes(cf3))
.setRegionReplication(3)
.build();

// Start the Modify procedure && kill the executor
long procId = procExec.submitProcedure(
new ModifyTableProcedure(procExec.getEnvironment(), htd));
new ModifyTableProcedure(procExec.getEnvironment(), newDescriptor));

// Restart the executor and execute the step twice
MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId);

// Validate descriptor
HTableDescriptor currentHtd = UTIL.getAdmin().getTableDescriptor(tableName);
assertEquals(newCompactionEnableOption, currentHtd.isCompactionEnabled());
assertEquals(2, currentHtd.getFamiliesKeys().size());
TableDescriptor currentDescriptor = UTIL.getAdmin().getDescriptor(tableName);
assertEquals(newDescriptor.isCompactionEnabled(), currentDescriptor.isCompactionEnabled());
assertEquals(2, newDescriptor.getColumnFamilyNames().size());

// cf2 should be added cf3 should be removed
MasterProcedureTestingUtility.validateTableCreation(UTIL.getHBaseCluster().getMaster(),
Expand Down

0 comments on commit e989a99

Please sign in to comment.