use of org.apache.hadoop.hbase.quotas.QuotaExceededException in project hbase by apache.
the class AssignmentManager method onRegionTransition.
/**
* Try to update some region states. If the state machine prevents
* such update, an error message is returned to explain the reason.
*
* It's expected that in each transition there should have just one
* region for opening/closing, 3 regions for splitting/merging.
* These regions should be on the server that requested the change.
*
* Region state machine. Only these transitions
* are expected to be triggered by a region server.
*
* On the state transition:
* (1) Open/Close should be initiated by master
* (a) Master sets the region to pending_open/pending_close
* in memory and hbase:meta after sending the request
* to the region server
* (b) Region server reports back to the master
* after open/close is done (either success/failure)
* (c) If region server has problem to report the status
* to master, it must be because the master is down or some
* temporary network issue. Otherwise, the region server should
* abort since it must be a bug. If the master is not accessible,
* the region server should keep trying until the server is
* stopped or till the status is reported to the (new) master
* (d) If region server dies in the middle of opening/closing
* a region, SSH picks it up and finishes it
* (e) If master dies in the middle, the new master recovers
* the state during initialization from hbase:meta. Region server
* can report any transition that has not been reported to
* the previous active master yet
* (2) Split/merge is initiated by region servers
* (a) To split a region, a region server sends a request
* to master to try to set a region to splitting, together with
* two daughters (to be created) to splitting new. If approved
* by the master, the splitting can then move ahead
* (b) To merge two regions, a region server sends a request to
* master to try to set the new merged region (to be created) to
* merging_new, together with two regions (to be merged) to merging.
* If it is ok with the master, the merge can then move ahead
* (c) Once the splitting/merging is done, the region server
* reports the status back to the master either success/failure.
* (d) Other scenarios should be handled similarly as for
* region open/close
*/
public String onRegionTransition(final ServerName serverName, final RegionStateTransition transition) {
TransitionCode code = transition.getTransitionCode();
HRegionInfo hri = HRegionInfo.convert(transition.getRegionInfo(0));
Lock lock = locker.acquireLock(hri.getEncodedName());
try {
RegionState current = regionStates.getRegionState(hri);
if (LOG.isDebugEnabled()) {
LOG.debug("Got transition " + code + " for " + (current != null ? current.toString() : hri.getShortNameToLog()) + " from " + serverName);
}
String errorMsg = null;
switch(code) {
case OPENED:
errorMsg = onRegionOpen(current, hri, serverName, transition);
break;
case FAILED_OPEN:
errorMsg = onRegionFailedOpen(current, hri, serverName);
break;
case CLOSED:
errorMsg = onRegionClosed(current, hri, serverName);
break;
case READY_TO_SPLIT:
try {
regionStateListener.onRegionSplit(hri);
errorMsg = onRegionReadyToSplit(current, hri, serverName, transition);
} catch (IOException exp) {
if (exp instanceof QuotaExceededException) {
server.getRegionNormalizer().planSkipped(hri, PlanType.SPLIT);
}
errorMsg = StringUtils.stringifyException(exp);
}
break;
case SPLIT_PONR:
errorMsg = onRegionSplitPONR(current, hri, serverName, transition);
break;
case SPLIT:
errorMsg = onRegionSplit(current, hri, serverName, transition);
break;
case SPLIT_REVERTED:
errorMsg = onRegionSplitReverted(current, hri, serverName, transition);
if (org.apache.commons.lang.StringUtils.isEmpty(errorMsg)) {
try {
regionStateListener.onRegionSplitReverted(hri);
} catch (IOException exp) {
LOG.warn(StringUtils.stringifyException(exp));
}
}
break;
case READY_TO_MERGE:
errorMsg = onRegionReadyToMerge(current, hri, serverName, transition);
break;
case MERGE_PONR:
errorMsg = onRegionMergePONR(current, hri, serverName, transition);
break;
case MERGED:
try {
errorMsg = onRegionMerged(current, hri, serverName, transition);
regionStateListener.onRegionMerged(hri);
} catch (IOException exp) {
errorMsg = StringUtils.stringifyException(exp);
}
break;
case MERGE_REVERTED:
errorMsg = onRegionMergeReverted(current, hri, serverName, transition);
break;
default:
errorMsg = "Unexpected transition code " + code;
}
if (errorMsg != null) {
LOG.info("Could not transition region from " + current + " on " + code + " by " + serverName + ": " + errorMsg);
}
return errorMsg;
} finally {
lock.unlock();
}
}
use of org.apache.hadoop.hbase.quotas.QuotaExceededException in project hbase by apache.
the class NamespaceStateManager method checkAndUpdateNamespaceTableCount.
synchronized void checkAndUpdateNamespaceTableCount(TableName table, int numRegions) throws IOException {
String namespace = table.getNamespaceAsString();
NamespaceDescriptor nspdesc = getNamespaceDescriptor(namespace);
if (nspdesc != null) {
NamespaceTableAndRegionInfo currentStatus;
currentStatus = getState(nspdesc.getName());
if ((currentStatus.getTables().size()) >= TableNamespaceManager.getMaxTables(nspdesc)) {
throw new QuotaExceededException("The table " + table.getNameAsString() + " cannot be created as it would exceed maximum number of tables allowed " + " in the namespace. The total number of tables permitted is " + TableNamespaceManager.getMaxTables(nspdesc));
}
if ((currentStatus.getRegionCount() + numRegions) > TableNamespaceManager.getMaxRegions(nspdesc)) {
throw new QuotaExceededException("The table " + table.getNameAsString() + " is not allowed to have " + numRegions + " regions. The total number of regions permitted is only " + TableNamespaceManager.getMaxRegions(nspdesc) + ", while current region count is " + currentStatus.getRegionCount() + ". This may be transient, please retry later if there are any" + " ongoing split operations in the namespace.");
}
} else {
throw new IOException("Namespace Descriptor found null for " + namespace + " This is unexpected.");
}
addTable(table, numRegions);
}
use of org.apache.hadoop.hbase.quotas.QuotaExceededException in project hbase by apache.
the class NamespaceStateManager method checkAndUpdateNamespaceRegionCount.
/**
* Check and update region count for an existing table. To handle scenarios like restore snapshot
* @param TableName name of the table for region count needs to be checked and updated
* @param incr count of regions
* @throws QuotaExceededException if quota exceeds for the number of regions allowed in a
* namespace
* @throws IOException Signals that an I/O exception has occurred.
*/
synchronized void checkAndUpdateNamespaceRegionCount(TableName name, int incr) throws IOException {
String namespace = name.getNamespaceAsString();
NamespaceDescriptor nspdesc = getNamespaceDescriptor(namespace);
if (nspdesc != null) {
NamespaceTableAndRegionInfo currentStatus = getState(namespace);
int regionCountOfTable = currentStatus.getRegionCountOfTable(name);
if ((currentStatus.getRegionCount() - regionCountOfTable + incr) > TableNamespaceManager.getMaxRegions(nspdesc)) {
throw new QuotaExceededException("The table " + name.getNameAsString() + " region count cannot be updated as it would exceed maximum number " + "of regions allowed in the namespace. The total number of regions permitted is " + TableNamespaceManager.getMaxRegions(nspdesc));
}
currentStatus.removeTable(name);
currentStatus.addTable(name, incr);
}
}
use of org.apache.hadoop.hbase.quotas.QuotaExceededException in project hbase by apache.
the class TestNamespaceAuditor method testRestoreSnapshotQuotaExceed.
@Test
public void testRestoreSnapshotQuotaExceed() throws Exception {
String nsp = prefix + "_testRestoreSnapshotQuotaExceed";
NamespaceDescriptor nspDesc = NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "10").build();
ADMIN.createNamespace(nspDesc);
NamespaceDescriptor ndesc = ADMIN.getNamespaceDescriptor(nsp);
assertNotNull("Namespace descriptor found null.", ndesc);
TableName tableName1 = TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1");
HTableDescriptor tableDescOne = new HTableDescriptor(tableName1);
HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
tableDescOne.addFamily(fam1);
ADMIN.createTable(tableDescOne, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"), 4);
NamespaceTableAndRegionInfo nstate = getNamespaceState(nsp);
assertEquals("Intial region count should be 4.", 4, nstate.getRegionCount());
String snapshot = "snapshot_testRestoreSnapshotQuotaExceed";
// snapshot has 4 regions
ADMIN.snapshot(snapshot, tableName1);
// recreate table with 1 region and set max regions to 3 for namespace
ADMIN.disableTable(tableName1);
ADMIN.deleteTable(tableName1);
ADMIN.createTable(tableDescOne);
ndesc.setConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "3");
ADMIN.modifyNamespace(ndesc);
ADMIN.disableTable(tableName1);
try {
ADMIN.restoreSnapshot(snapshot);
fail("Region quota is exceeded so QuotaExceededException should be thrown but HBaseAdmin" + " wraps IOException into RestoreSnapshotException");
} catch (RestoreSnapshotException ignore) {
assertTrue(ignore.getCause() instanceof QuotaExceededException);
}
assertEquals(1, getNamespaceState(nsp).getRegionCount());
ADMIN.enableTable(tableName1);
ADMIN.deleteSnapshot(snapshot);
}
Aggregations