Search in sources :

Example 1 with MergeRegionException

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;
    }
}
Also used : RegionInfo(org.apache.hadoop.hbase.client.RegionInfo) MergeRegionException(org.apache.hadoop.hbase.exceptions.MergeRegionException) DoNotRetryRegionException(org.apache.hadoop.hbase.client.DoNotRetryRegionException)

Example 2 with MergeRegionException

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;
}
Also used : TableName(org.apache.hadoop.hbase.TableName) RegionState(org.apache.hadoop.hbase.master.RegionState) UnknownRegionException(org.apache.hadoop.hbase.UnknownRegionException) RegionInfo(org.apache.hadoop.hbase.client.RegionInfo) MergeRegionException(org.apache.hadoop.hbase.exceptions.MergeRegionException) IOException(java.io.IOException)

Example 3 with MergeRegionException

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);
}
Also used : ArrayList(java.util.ArrayList) TableName(org.apache.hadoop.hbase.TableName) HRegion(org.apache.hadoop.hbase.regionserver.HRegion) MergeTableRegionsRequest(org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest) MergeRegionException(org.apache.hadoop.hbase.exceptions.MergeRegionException) Pair(org.apache.hadoop.hbase.util.Pair) Test(org.junit.Test)

Example 4 with MergeRegionException

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);
    }
}
Also used : RegionState(org.apache.hadoop.hbase.master.RegionState) RegionStates(org.apache.hadoop.hbase.master.RegionStates) CatalogJanitor(org.apache.hadoop.hbase.master.CatalogJanitor) UnknownRegionException(org.apache.hadoop.hbase.UnknownRegionException) MergeRegionException(org.apache.hadoop.hbase.exceptions.MergeRegionException)

Example 5 with MergeRegionException

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";
        }
    });
}
Also used : TableName(org.apache.hadoop.hbase.TableName) MergeTableRegionsProcedure(org.apache.hadoop.hbase.master.procedure.MergeTableRegionsProcedure) UnknownRegionException(org.apache.hadoop.hbase.UnknownRegionException) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) DoNotRetryIOException(org.apache.hadoop.hbase.DoNotRetryIOException) HBaseIOException(org.apache.hadoop.hbase.HBaseIOException) MergeRegionException(org.apache.hadoop.hbase.exceptions.MergeRegionException) MasterProcedureUtil(org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil)

Aggregations

MergeRegionException (org.apache.hadoop.hbase.exceptions.MergeRegionException)6 TableName (org.apache.hadoop.hbase.TableName)4 UnknownRegionException (org.apache.hadoop.hbase.UnknownRegionException)4 IOException (java.io.IOException)3 RegionInfo (org.apache.hadoop.hbase.client.RegionInfo)3 DoNotRetryRegionException (org.apache.hadoop.hbase.client.DoNotRetryRegionException)2 RegionState (org.apache.hadoop.hbase.master.RegionState)2 Test (org.junit.Test)2 InterruptedIOException (java.io.InterruptedIOException)1 ArrayList (java.util.ArrayList)1 DoNotRetryIOException (org.apache.hadoop.hbase.DoNotRetryIOException)1 HBaseIOException (org.apache.hadoop.hbase.HBaseIOException)1 Admin (org.apache.hadoop.hbase.client.Admin)1 Table (org.apache.hadoop.hbase.client.Table)1 CatalogJanitor (org.apache.hadoop.hbase.master.CatalogJanitor)1 RegionStates (org.apache.hadoop.hbase.master.RegionStates)1 AssignmentManager (org.apache.hadoop.hbase.master.assignment.AssignmentManager)1 MasterProcedureUtil (org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil)1 MergeTableRegionsProcedure (org.apache.hadoop.hbase.master.procedure.MergeTableRegionsProcedure)1 HRegion (org.apache.hadoop.hbase.regionserver.HRegion)1