use of org.apache.hadoop.hbase.exceptions.MergeRegionException in project hbase by apache.
the class MergeTableRegionsProcedure method checkRegionsToMerge.
/**
* @throws MergeRegionException If unable to merge regions for whatever reasons.
*/
private static void checkRegionsToMerge(MasterProcedureEnv env, final RegionInfo[] regions, final boolean force) throws MergeRegionException {
long count = Arrays.stream(regions).distinct().count();
if (regions.length != count) {
throw new MergeRegionException("Duplicate regions specified; cannot merge a region to " + "itself. Passed in " + regions.length + " but only " + count + " unique.");
}
if (count < 2) {
throw new MergeRegionException("Need two Regions at least to run a Merge");
}
RegionInfo previous = null;
for (RegionInfo ri : regions) {
if (previous != null) {
if (!previous.getTable().equals(ri.getTable())) {
String msg = "Can't merge regions from different tables: " + previous + ", " + ri;
LOG.warn(msg);
throw new MergeRegionException(msg);
}
if (!force && !ri.isAdjacent(previous) && !ri.isOverlap(previous)) {
String msg = "Unable to merge non-adjacent or non-overlapping regions '" + previous.getShortNameToLog() + "', '" + ri.getShortNameToLog() + "' when force=false";
LOG.warn(msg);
throw new MergeRegionException(msg);
}
}
if (ri.getReplicaId() != RegionInfo.DEFAULT_REPLICA_ID) {
throw new MergeRegionException("Can't merge non-default replicas; " + ri);
}
try {
checkOnline(env, ri);
} catch (DoNotRetryRegionException dnrre) {
throw new MergeRegionException(dnrre);
}
previous = ri;
}
}
use of org.apache.hadoop.hbase.exceptions.MergeRegionException in project hbase by apache.
the class MergeTableRegionsProcedure method prepareMergeRegion.
/**
* Prepare merge and do some check
*/
private boolean prepareMergeRegion(final MasterProcedureEnv env) throws IOException {
// Fail if we are taking snapshot for the given table
TableName tn = regionsToMerge[0].getTable();
if (env.getMasterServices().getSnapshotManager().isTakingSnapshot(tn)) {
throw new MergeRegionException("Skip merging regions " + RegionInfo.getShortNameToLog(regionsToMerge) + ", because we are snapshotting " + tn);
}
// the switch was set to false after submit.
if (!env.getMasterServices().isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {
String regionsStr = Arrays.deepToString(this.regionsToMerge);
LOG.warn("Merge switch is off! skip merge of " + regionsStr);
setFailure(getClass().getSimpleName(), new IOException("Merge of " + regionsStr + " failed because merge switch is off"));
return false;
}
if (!env.getMasterServices().getTableDescriptors().get(getTableName()).isMergeEnabled()) {
String regionsStr = Arrays.deepToString(regionsToMerge);
LOG.warn("Merge is disabled for the table! Skipping merge of {}", regionsStr);
setFailure(getClass().getSimpleName(), new IOException("Merge of " + regionsStr + " failed as region merge is disabled for the table"));
return false;
}
RegionStates regionStates = env.getAssignmentManager().getRegionStates();
RegionStateStore regionStateStore = env.getAssignmentManager().getRegionStateStore();
for (RegionInfo ri : this.regionsToMerge) {
if (regionStateStore.hasMergeRegions(ri)) {
String msg = "Skip merging " + RegionInfo.getShortNameToLog(regionsToMerge) + ", because a parent, " + RegionInfo.getShortNameToLog(ri) + ", has a merge qualifier " + "(if a 'merge column' in parent, it was recently merged but still has outstanding " + "references to its parents that must be cleared before it can participate in merge -- " + "major compact it to hurry clearing of its references)";
LOG.warn(msg);
throw new MergeRegionException(msg);
}
RegionState state = regionStates.getRegionState(ri.getEncodedName());
if (state == null) {
throw new UnknownRegionException(RegionInfo.getShortNameToLog(ri) + " UNKNOWN (Has it been garbage collected?)");
}
if (!state.isOpened()) {
throw new MergeRegionException("Unable to merge regions that are NOT online: " + ri);
}
// along with the failure, so we can see why regions are not mergeable at this time.
try {
if (!isMergeable(env, state)) {
setFailure(getClass().getSimpleName(), new MergeRegionException("Skip merging " + RegionInfo.getShortNameToLog(regionsToMerge) + ", because a parent, " + RegionInfo.getShortNameToLog(ri) + ", is not mergeable"));
return false;
}
} catch (IOException e) {
IOException ioe = new IOException(RegionInfo.getShortNameToLog(ri) + " NOT mergeable", e);
setFailure(getClass().getSimpleName(), ioe);
return false;
}
}
// Update region states to Merging
setRegionStateToMerging(env);
return true;
}
use of org.apache.hadoop.hbase.exceptions.MergeRegionException in project hbase by apache.
the class TestAdmin1 method testSplitAndMergeWithReplicaTable.
@Test
public void testSplitAndMergeWithReplicaTable() throws Exception {
// The test tries to directly split replica regions and directly merge replica regions. These
// are not allowed. The test validates that. Then the test does a valid split/merge of allowed
// regions.
// Set up a table with 3 regions and replication set to 3
TableName tableName = TableName.valueOf(name.getMethodName());
byte[] cf = Bytes.toBytes("f");
TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName).setRegionReplication(3).setColumnFamily(ColumnFamilyDescriptorBuilder.of(cf)).build();
byte[][] splitRows = new byte[2][];
splitRows[0] = new byte[] { (byte) '4' };
splitRows[1] = new byte[] { (byte) '7' };
TEST_UTIL.getAdmin().createTable(desc, splitRows);
List<HRegion> oldRegions;
do {
oldRegions = TEST_UTIL.getHBaseCluster().getRegions(tableName);
Thread.sleep(10);
} while (// 3 regions * 3 replicas
oldRegions.size() != 9);
// write some data to the table
Table ht = TEST_UTIL.getConnection().getTable(tableName);
List<Put> puts = new ArrayList<>();
byte[] qualifier = Bytes.toBytes("c");
Put put = new Put(new byte[] { (byte) '1' });
put.addColumn(cf, qualifier, Bytes.toBytes("100"));
puts.add(put);
put = new Put(new byte[] { (byte) '6' });
put.addColumn(cf, qualifier, Bytes.toBytes("100"));
puts.add(put);
put = new Put(new byte[] { (byte) '8' });
put.addColumn(cf, qualifier, Bytes.toBytes("100"));
puts.add(put);
ht.put(puts);
ht.close();
List<Pair<RegionInfo, ServerName>> regions = MetaTableAccessor.getTableRegionsAndLocations(TEST_UTIL.getConnection(), tableName);
boolean gotException = false;
// regions). Try splitting that region via the split API . Should fail
try {
FutureUtils.get(TEST_UTIL.getAdmin().splitRegionAsync(regions.get(1).getFirst().getRegionName()));
} catch (IllegalArgumentException ex) {
gotException = true;
}
assertTrue(gotException);
gotException = false;
// this API goes direct to the regionserver skipping any checks in the admin). Should fail
try {
FutureUtils.get(TEST_UTIL.getAdmin().splitRegionAsync(regions.get(1).getFirst().getEncodedNameAsBytes(), new byte[] { (byte) '1' }));
} catch (IllegalArgumentException ex) {
gotException = true;
}
assertTrue(gotException);
gotException = false;
// testing Sync split operation
try {
FutureUtils.get(TEST_UTIL.getAdmin().splitRegionAsync(regions.get(1).getFirst().getRegionName(), new byte[] { (byte) '1' }));
} catch (IllegalArgumentException ex) {
gotException = true;
}
assertTrue(gotException);
gotException = false;
// Try merging a replica with another. Should fail.
try {
FutureUtils.get(TEST_UTIL.getAdmin().mergeRegionsAsync(regions.get(1).getFirst().getEncodedNameAsBytes(), regions.get(2).getFirst().getEncodedNameAsBytes(), true));
} catch (IllegalArgumentException m) {
gotException = true;
}
assertTrue(gotException);
// Try going to the master directly (that will skip the check in admin)
try {
byte[][] nameofRegionsToMerge = new byte[2][];
nameofRegionsToMerge[0] = regions.get(1).getFirst().getEncodedNameAsBytes();
nameofRegionsToMerge[1] = regions.get(2).getFirst().getEncodedNameAsBytes();
MergeTableRegionsRequest request = RequestConverter.buildMergeTableRegionsRequest(nameofRegionsToMerge, true, HConstants.NO_NONCE, HConstants.NO_NONCE);
TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterRpcServices().mergeTableRegions(null, request);
} catch (org.apache.hbase.thirdparty.com.google.protobuf.ServiceException m) {
Throwable t = m.getCause();
do {
if (t instanceof MergeRegionException) {
gotException = true;
break;
}
t = t.getCause();
} while (t != null);
}
assertTrue(gotException);
}
use of org.apache.hadoop.hbase.exceptions.MergeRegionException in project hbase by apache.
the class MergeTableRegionsProcedure method prepareMergeRegion.
/**
* Prepare merge and do some check
* @param env MasterProcedureEnv
* @throws IOException
*/
private void prepareMergeRegion(final MasterProcedureEnv env) throws IOException {
// Note: the following logic assumes that we only have 2 regions to merge. In the future,
// if we want to extend to more than 2 regions, the code needs to modify a little bit.
//
CatalogJanitor catalogJanitor = env.getMasterServices().getCatalogJanitor();
boolean regionAHasMergeQualifier = !catalogJanitor.cleanMergeQualifier(regionsToMerge[0]);
if (regionAHasMergeQualifier || !catalogJanitor.cleanMergeQualifier(regionsToMerge[1])) {
String msg = "Skip merging regions " + getRegionsToMergeListFullNameString() + ", because region " + (regionAHasMergeQualifier ? regionsToMerge[0].getEncodedName() : regionsToMerge[1].getEncodedName()) + " has merge qualifier";
LOG.warn(msg);
throw new MergeRegionException(msg);
}
RegionStates regionStates = getAssignmentManager(env).getRegionStates();
RegionState regionStateA = regionStates.getRegionState(regionsToMerge[0].getEncodedName());
RegionState regionStateB = regionStates.getRegionState(regionsToMerge[1].getEncodedName());
if (regionStateA == null || regionStateB == null) {
throw new UnknownRegionException(regionStateA == null ? regionsToMerge[0].getEncodedName() : regionsToMerge[1].getEncodedName());
}
if (!regionStateA.isOpened() || !regionStateB.isOpened()) {
throw new MergeRegionException("Unable to merge regions not online " + regionStateA + ", " + regionStateB);
}
}
use of org.apache.hadoop.hbase.exceptions.MergeRegionException in project hbase by apache.
the class HMaster method mergeRegions.
@Override
public long mergeRegions(final HRegionInfo[] regionsToMerge, final boolean forcible, final long nonceGroup, final long nonce) throws IOException {
checkInitialized();
assert (regionsToMerge.length == 2);
TableName tableName = regionsToMerge[0].getTable();
if (tableName == null || regionsToMerge[1].getTable() == null) {
throw new UnknownRegionException("Can't merge regions without table associated");
}
if (!tableName.equals(regionsToMerge[1].getTable())) {
throw new IOException("Cannot merge regions from two different tables " + regionsToMerge[0].getTable() + " and " + regionsToMerge[1].getTable());
}
if (regionsToMerge[0].compareTo(regionsToMerge[1]) == 0) {
throw new MergeRegionException("Cannot merge a region to itself " + regionsToMerge[0] + ", " + regionsToMerge[1]);
}
return MasterProcedureUtil.submitProcedure(new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
@Override
protected void run() throws IOException {
getMaster().getMasterCoprocessorHost().preMergeRegions(regionsToMerge);
LOG.info(getClientIdAuditPrefix() + " Merge regions " + regionsToMerge[0].getEncodedName() + " and " + regionsToMerge[1].getEncodedName());
submitProcedure(new MergeTableRegionsProcedure(procedureExecutor.getEnvironment(), regionsToMerge, forcible));
getMaster().getMasterCoprocessorHost().postMergeRegions(regionsToMerge);
}
@Override
protected String getDescription() {
return "DisableTableProcedure";
}
});
}
Aggregations