You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ns...@apache.org on 2011/10/11 04:24:53 UTC
svn commit: r1181602 -
/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
Author: nspiegelberg
Date: Tue Oct 11 02:24:52 2011
New Revision: 1181602
URL: http://svn.apache.org/viewvc?rev=1181602&view=rev
Log:
Fixed a bug that caused the createTable(splitKeys) to open regions asynchronously.
Summary: The code in createTable(splitKeys) should now make sure that all regions are opened before returning.
Task ID: #611387
Reviewers: kannan, nspiegelberg
Test Plan:
To reproduce the bug in unit test:
1. Add a delay (~1s) in the worker runnable that opens a region in HRegionServer.java if the region to open is not the first region.
2. Run the unit test that creates a table with 1000 regions.
3. A NoServerForRegionException should be thrown to indicate the bug (which was originally never caught in the "retry" block).
The unit test should pass after applying the fix.
Modified:
hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java?rev=1181602&r1=1181601&r2=1181602&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java Tue Oct 11 02:24:52 2011
@@ -33,6 +33,7 @@ import org.apache.hadoop.hbase.MasterNot
import org.apache.hadoop.hbase.RegionException;
import org.apache.hadoop.hbase.RemoteExceptionHandler;
import org.apache.hadoop.hbase.TableExistsException;
+import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.ipc.HMasterInterface;
import org.apache.hadoop.hbase.ipc.HRegionInterface;
@@ -44,11 +45,13 @@ import org.apache.hadoop.io.Writable;
import org.apache.hadoop.ipc.RemoteException;
import java.io.IOException;
+import java.io.InterruptedIOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Provides an interface to manage HBase database table metadata + general
@@ -229,7 +232,7 @@ public class HBaseAdmin {
* and attempt-at-creation).
* @throws IOException
*/
- public void createTable(HTableDescriptor desc, byte [][] splitKeys)
+ public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
throws IOException {
HTableDescriptor.isLegalTableName(desc.getName());
if(splitKeys != null && splitKeys.length > 1) {
@@ -244,22 +247,52 @@ public class HBaseAdmin {
}
}
createTableAsync(desc, splitKeys);
- for (int tries = 0; tries < numRetries; tries++) {
- try {
- // Wait for new table to come on-line
- connection.locateRegion(desc.getName(), HConstants.EMPTY_START_ROW);
- break;
-
- } catch (RegionException e) {
+ int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
+ int prevRegCount = 0;
+ for (int tries = 0; tries < numRetries; ++tries) {
+ // Wait for new table to come on-line
+ final AtomicInteger actualRegCount = new AtomicInteger(0);
+ MetaScannerVisitor visitor = new MetaScannerVisitor() {
+ @Override
+ public boolean processRow(Result rowResult) throws IOException {
+ HRegionInfo info = Writables.getHRegionInfo(
+ rowResult.getValue(HConstants.CATALOG_FAMILY,
+ HConstants.REGIONINFO_QUALIFIER));
+ if (!(Bytes.equals(info.getTableDesc().getName(), desc.getName()))) {
+ return false;
+ }
+ String hostAndPort = null;
+ byte [] value = rowResult.getValue(HConstants.CATALOG_FAMILY,
+ HConstants.SERVER_QUALIFIER);
+ // Make sure that regions are assigned to server
+ if (value != null && value.length > 0) {
+ hostAndPort = Bytes.toString(value);
+ }
+ if (!(info.isOffline() || info.isSplit()) && hostAndPort != null) {
+ actualRegCount.incrementAndGet();
+ }
+ return true;
+ }
+ };
+ MetaScanner.metaScan(conf, visitor, desc.getName());
+ if (actualRegCount.get() != numRegs) {
if (tries == numRetries - 1) {
- // Ran out of tries
- throw e;
+ throw new RegionOfflineException("Only " + actualRegCount.get() +
+ " of " + numRegs + " regions are online; retries exhausted.");
}
- }
- try {
- Thread.sleep(getPauseTime(tries));
- } catch (InterruptedException e) {
- // continue
+ try { // Sleep
+ Thread.sleep(getPauseTime(tries));
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException("Interrupted when opening" +
+ " regions; " + actualRegCount.get() + " of " + numRegs +
+ " regions processed so far");
+ }
+ if (actualRegCount.get() > prevRegCount) { // Making progress
+ prevRegCount = actualRegCount.get();
+ tries = -1;
+ }
+ } else {
+ return;
}
}
}