Index: src/main/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/HConstants.java (revision 1042235) +++ src/main/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -299,6 +299,14 @@ } /** + * flags that are passed to createTable() + */ + public enum TableCreationFlag { + SYNC, // indicates waiting for assignment of regions before call to createTable() returns + ROUND_ROBIN // assigns the regions in round-robin fashion across all region servers + } + + /** * Scope tag for locally scoped data. * This data will not be replicated. */ Index: src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1042235) +++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy) @@ -25,6 +25,8 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -48,6 +50,7 @@ import org.apache.hadoop.hbase.TableNotDisabledException; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.UnknownRegionException; +import org.apache.hadoop.hbase.HConstants.TableCreationFlag; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.catalog.MetaEditor; import org.apache.hadoop.hbase.catalog.MetaReader; @@ -64,6 +67,7 @@ import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.ipc.HMasterRegionInterface; import org.apache.hadoop.hbase.ipc.RpcServer; +import org.apache.hadoop.hbase.master.AssignmentManager.BulkStartupAssigner; import org.apache.hadoop.hbase.master.LoadBalancer.RegionPlan; import org.apache.hadoop.hbase.master.handler.DeleteTableHandler; import org.apache.hadoop.hbase.master.handler.DisableTableHandler; @@ -721,14 +725,14 @@ this.assignmentManager.balance(rp); } } - + public void createTable(HTableDescriptor desc, byte [][] splitKeys) throws IOException { - createTable(desc, splitKeys, false); + createTable(desc, splitKeys, EnumSet.noneOf(TableCreationFlag.class)); } public void createTable(HTableDescriptor desc, byte [][] splitKeys, - boolean sync) + EnumSet flags) throws IOException { if (!isMasterRunning()) { throw new MasterNotRunningException(); @@ -757,11 +761,11 @@ LOG.warn("Interrupted waiting for meta availability", e); throw new IOException(e); } - createTable(newRegions, sync); + createTable(newRegions, flags); } private synchronized void createTable(final HRegionInfo [] newRegions, - boolean sync) + EnumSet flags) throws IOException { String tableName = newRegions[0].getTableDesc().getNameAsString(); if(MetaReader.tableExists(catalogTracker, tableName)) { @@ -789,11 +793,31 @@ region.getLog().closeAndDelete(); // 5. Trigger immediate assignment of this region - assignmentManager.assign(region.getRegionInfo(), true); + if (!flags.contains(TableCreationFlag.ROUND_ROBIN)) { + assignmentManager.assign(region.getRegionInfo(), true); + } } - + + if (flags.contains(TableCreationFlag.ROUND_ROBIN)) { + Map> bulkPlan = null; + List servers = serverManager.getOnlineServersList(); + // Generate a round-robin bulk assignment plan + bulkPlan = LoadBalancer.roundRobinAssignment( + Arrays.asList(newRegions), servers); + LOG.info("Bulk assigning " + newRegions.length + " region(s) across " + + servers.size() + " server(s)"); + // Use fixed count thread pool assigning. + BulkAssigner ba = new BulkStartupAssigner(this, bulkPlan, this.assignmentManager); + try { + ba.bulkAssign(); + } catch (InterruptedException ie) { + LOG.warn("Caught " + ie + " during round-robin assignment"); + } + LOG.info("Bulk assigning done"); + } + // 5. If sync, wait for assignment of regions - if(sync) { + if (flags.contains(TableCreationFlag.SYNC)) { LOG.debug("Waiting for " + newRegions.length + " region(s) to be " + "assigned before returning"); for(HRegionInfo regionInfo : newRegions) { Index: src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java (revision 1042235) +++ src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java (working copy) @@ -20,11 +20,13 @@ package org.apache.hadoop.hbase.ipc; import java.io.IOException; +import java.util.EnumSet; import org.apache.hadoop.hbase.ClusterStatus; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.UnknownRegionException; +import org.apache.hadoop.hbase.HConstants.TableCreationFlag; /** * Clients interact with the HMasterInterface to gain access to meta-level @@ -48,9 +50,10 @@ * the table will be created with a single region. * @param desc table descriptor * @param splitKeys + * @param flags table creation flags: sync, round-robin * @throws IOException */ - public void createTable(HTableDescriptor desc, byte [][] splitKeys) + public void createTable(HTableDescriptor desc, byte [][] splitKeys, EnumSet flags) throws IOException; /** Index: src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (revision 1042235) +++ src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (working copy) @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.NavigableMap; @@ -43,10 +44,12 @@ import org.apache.hadoop.hbase.TableExistsException; import org.apache.hadoop.hbase.UnknownRegionException; import org.apache.hadoop.hbase.ZooKeeperConnectionException; +import org.apache.hadoop.hbase.HConstants.TableCreationFlag; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.catalog.MetaReader; import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.ipc.HRegionInterface; +import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.Writables; @@ -224,7 +227,7 @@ */ public void createTable(HTableDescriptor desc) throws IOException { - createTable(desc, null); + createTable(desc, null, EnumSet.noneOf(TableCreationFlag.class)); } /** @@ -264,7 +267,7 @@ if(splitKeys == null || splitKeys.length != numRegions - 1) { throw new IllegalArgumentException("Unable to split key range into enough regions"); } - createTable(desc, splitKeys); + createTable(desc, splitKeys, EnumSet.of(TableCreationFlag.ROUND_ROBIN)); } /** @@ -284,7 +287,7 @@ * and attempt-at-creation). * @throws IOException */ - public void createTable(HTableDescriptor desc, byte [][] splitKeys) + public void createTable(HTableDescriptor desc, byte [][] splitKeys, EnumSet flags) throws IOException { HTableDescriptor.isLegalTableName(desc.getName()); if(splitKeys != null && splitKeys.length > 1) { @@ -300,7 +303,7 @@ lastKey = splitKey; } } - createTableAsync(desc, splitKeys); + createTableAsync(desc, splitKeys, flags); for (int tries = 0; tries < numRetries; tries++) { try { // Wait for new table to come on-line @@ -334,11 +337,11 @@ * and attempt-at-creation). * @throws IOException */ - public void createTableAsync(HTableDescriptor desc, byte [][] splitKeys) + public void createTableAsync(HTableDescriptor desc, byte [][] splitKeys, EnumSet flags) throws IOException { HTableDescriptor.isLegalTableName(desc.getName()); try { - getMaster().createTable(desc, splitKeys); + getMaster().createTable(desc, splitKeys, flags); } catch (RemoteException e) { throw e.unwrapRemoteException(); }