HBASE-20817 Infinite loop when executing ReopenTableRegionsProcedure

Signed-off-by: zhangduo <zhangduo@apache.org>
This commit is contained in:
Ankit Singhal 2018-07-02 16:07:34 +08:00 committed by zhangduo
parent 7c5188f39e
commit cfdabe9267
3 changed files with 43 additions and 16 deletions

View File

@ -66,9 +66,11 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
throws HBaseIOException { throws HBaseIOException {
super(env, plan.getRegionInfo()); super(env, plan.getRegionInfo());
this.plan = plan; this.plan = plan;
if (check) {
preflightChecks(env, true); preflightChecks(env, true);
checkOnline(env, plan.getRegionInfo()); checkOnline(env, plan.getRegionInfo());
} }
}
@Override @Override
protected Flow executeFromState(final MasterProcedureEnv env, final MoveRegionState state) protected Flow executeFromState(final MasterProcedureEnv env, final MoveRegionState state)
@ -135,7 +137,7 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
@Override @Override
protected MoveRegionState getState(final int stateId) { protected MoveRegionState getState(final int stateId) {
return MoveRegionState.valueOf(stateId); return MoveRegionState.forNumber(stateId);
} }
@Override @Override

View File

@ -974,8 +974,11 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
long maxSeqIdFromFile = long maxSeqIdFromFile =
WALSplitter.getMaxRegionSequenceId(fs.getFileSystem(), fs.getRegionDir()); WALSplitter.getMaxRegionSequenceId(fs.getFileSystem(), fs.getRegionDir());
long nextSeqId = Math.max(maxSeqId, maxSeqIdFromFile) + 1; long nextSeqId = Math.max(maxSeqId, maxSeqIdFromFile) + 1;
if (writestate.writesEnabled) { // The openSeqNum will always be increase even for read only region, as we rely on it to
LOG.debug("writing seq id for " + this.getRegionInfo().getEncodedName()); // determine whether a region has been successfully reopend, so here we always need to update
// the max sequence id file.
if (RegionReplicaUtil.isDefaultReplica(getRegionInfo())) {
LOG.debug("writing seq id for {}", this.getRegionInfo().getEncodedName());
WALSplitter.writeRegionSequenceIdFile(fs.getFileSystem(), fs.getRegionDir(), nextSeqId - 1); WALSplitter.writeRegionSequenceIdFile(fs.getFileSystem(), fs.getRegionDir(), nextSeqId - 1);
} }
@ -1657,7 +1660,10 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
} }
status.setStatus("Writing region close event to WAL"); status.setStatus("Writing region close event to WAL");
if (!abort && wal != null && getRegionServerServices() != null && !writestate.readOnly) { // Always write close marker to wal even for read only table. This is not a big problem as we
// do not write any data into the region.
if (!abort && wal != null && getRegionServerServices() != null &&
RegionReplicaUtil.isDefaultReplica(getRegionInfo())) {
writeRegionCloseMarker(wal); writeRegionCloseMarker(wal);
} }
@ -7050,7 +7056,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
* HRegion#getMinSequenceId() to ensure the wal id is properly kept * HRegion#getMinSequenceId() to ensure the wal id is properly kept
* up. HRegionStore does this every time it opens a new region. * up. HRegionStore does this every time it opens a new region.
* @return new HRegion * @return new HRegion
* @throws IOException
*/ */
public static HRegion openHRegion(final Configuration conf, final FileSystem fs, public static HRegion openHRegion(final Configuration conf, final FileSystem fs,
final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal) final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal)
@ -7072,7 +7077,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
* @param rsServices An interface we can request flushes against. * @param rsServices An interface we can request flushes against.
* @param reporter An interface we can report progress against. * @param reporter An interface we can report progress against.
* @return new HRegion * @return new HRegion
* @throws IOException
*/ */
public static HRegion openHRegion(final Configuration conf, final FileSystem fs, public static HRegion openHRegion(final Configuration conf, final FileSystem fs,
final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal, final Path rootDir, final RegionInfo info, final TableDescriptor htd, final WAL wal,
@ -7096,7 +7100,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
* @param rsServices An interface we can request flushes against. * @param rsServices An interface we can request flushes against.
* @param reporter An interface we can report progress against. * @param reporter An interface we can report progress against.
* @return new HRegion * @return new HRegion
* @throws IOException
*/ */
public static HRegion openHRegion(final Configuration conf, final FileSystem fs, public static HRegion openHRegion(final Configuration conf, final FileSystem fs,
final Path rootDir, final Path tableDir, final RegionInfo info, final TableDescriptor htd, final Path rootDir, final Path tableDir, final RegionInfo info, final TableDescriptor htd,
@ -7121,7 +7124,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
* @param other original object * @param other original object
* @param reporter An interface we can report progress against. * @param reporter An interface we can report progress against.
* @return new HRegion * @return new HRegion
* @throws IOException
*/ */
public static HRegion openHRegion(final HRegion other, final CancelableProgressable reporter) public static HRegion openHRegion(final HRegion other, final CancelableProgressable reporter)
throws IOException { throws IOException {
@ -7154,8 +7156,11 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
checkClassLoading(); checkClassLoading();
this.openSeqNum = initialize(reporter); this.openSeqNum = initialize(reporter);
this.mvcc.advanceTo(openSeqNum); this.mvcc.advanceTo(openSeqNum);
if (wal != null && getRegionServerServices() != null && !writestate.readOnly) { // The openSeqNum must be increased every time when a region is assigned, as we rely on it to
// Only write the region open event marker to WAL if we are not read-only. // determine whether a region has been successfully reopened. So here we always write open
// marker, even if the table is read only.
if (wal != null && getRegionServerServices() != null &&
RegionReplicaUtil.isDefaultReplica(getRegionInfo())) {
writeRegionOpenMarker(wal, openSeqNum); writeRegionOpenMarker(wal, openSeqNum);
} }
return this; return this;
@ -7168,7 +7173,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
* @param info Info for region to be opened. * @param info Info for region to be opened.
* @param htd the table descriptor * @param htd the table descriptor
* @return new HRegion * @return new HRegion
* @throws IOException e
*/ */
public static HRegion openReadOnlyFileSystemHRegion(final Configuration conf, final FileSystem fs, public static HRegion openReadOnlyFileSystemHRegion(final Configuration conf, final FileSystem fs,
final Path tableDir, RegionInfo info, final TableDescriptor htd) throws IOException { final Path tableDir, RegionInfo info, final TableDescriptor htd) throws IOException {

View File

@ -31,7 +31,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HColumnDescriptor;
@ -69,6 +68,7 @@ import org.junit.experimental.categories.Category;
import org.junit.rules.TestName; import org.junit.rules.TestName;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest;
@ -500,10 +500,31 @@ public class TestAdmin1 {
} }
} }
/**
* Verify schema change for read only table
*/
@Test
public void testReadOnlyTableModify() throws IOException, InterruptedException {
final TableName tableName = TableName.valueOf(name.getMethodName());
TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
// Make table read only
TableDescriptor htd = TableDescriptorBuilder.newBuilder(this.admin.getDescriptor(tableName))
.setReadOnly(true).build();
admin.modifyTable(htd);
// try to modify the read only table now
htd = TableDescriptorBuilder.newBuilder(this.admin.getDescriptor(tableName))
.setCompactionEnabled(false).build();
admin.modifyTable(htd);
// Delete the table
this.admin.disableTable(tableName);
this.admin.deleteTable(tableName);
assertFalse(this.admin.tableExists(tableName));
}
/** /**
* Verify schema modification takes. * Verify schema modification takes.
* @throws IOException
* @throws InterruptedException
*/ */
@Test @Test
public void testOnlineChangeTableSchema() throws IOException, InterruptedException { public void testOnlineChangeTableSchema() throws IOException, InterruptedException {