Index: src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/handler/TableEventHandler.java (revision ) @@ -30,14 +30,16 @@ import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.TableNotDisabledException; import org.apache.hadoop.hbase.catalog.MetaReader; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.executor.EventHandler; import org.apache.hadoop.hbase.master.BulkReOpen; import org.apache.hadoop.hbase.master.MasterServices; +import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.zookeeper.ZKTable; import org.apache.zookeeper.KeeperException; +import org.apache.hadoop.hbase.zookeeper.MasterSchemaChangeTracker; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -52,26 +54,22 @@ public abstract class TableEventHandler extends EventHandler { private static final Log LOG = LogFactory.getLog(TableEventHandler.class); protected final MasterServices masterServices; + protected HMasterInterface master = null; protected final byte [] tableName; protected final String tableNameStr; + protected boolean instantAction = false; public TableEventHandler(EventType eventType, byte [] tableName, Server server, - MasterServices masterServices) + MasterServices masterServices, HMasterInterface masterInterface, + boolean instantSchemaChange) throws IOException { super(server, eventType); this.masterServices = masterServices; this.tableName = tableName; - try { - this.masterServices.checkTableModifiable(tableName); - } catch (TableNotDisabledException ex) { - if (eventType.isOnlineSchemaChangeSupported()) { - LOG.debug("Ignoring table not disabled exception " + - "for supporting online schema changes."); - } else { - throw ex; - } - } + this.masterServices.checkTableModifiable(tableName, eventType); this.tableNameStr = Bytes.toString(this.tableName); + this.instantAction = instantSchemaChange; + this.master = masterInterface; } @Override @@ -83,23 +81,45 @@ MetaReader.getTableRegions(this.server.getCatalogTracker(), tableName); handleTableOperation(hris); - if (eventType.isOnlineSchemaChangeSupported() && this.masterServices. + handleSchemaChanges(hris); + } catch (IOException e) { + LOG.error("Error manipulating table " + Bytes.toString(tableName), e); + } catch (KeeperException e) { + LOG.error("Error manipulating table " + Bytes.toString(tableName), e); + } + } + + private void handleSchemaChanges(List regions) + throws IOException { + if (instantAction) { + handleInstantSchemaChanges(); + } else { + handleRegularSchemaChanges(regions); + } + } + + /** + * Perform schema changes only if the table is in enabled state. + * @return + */ + private boolean canPerformSchemaChange() { + return (eventType.isSchemaChangeEvent() && this.masterServices. - getAssignmentManager().getZKTable(). + getAssignmentManager().getZKTable(). - isEnabledTable(Bytes.toString(tableName))) { - this.masterServices.getAssignmentManager().setRegionsToReopen(hris); - if (reOpenAllRegions(hris)) { + isEnabledTable(Bytes.toString(tableName))); + } + + private void handleRegularSchemaChanges(List regions) + throws IOException { + if (canPerformSchemaChange()) { + this.masterServices.getAssignmentManager().setRegionsToReopen(regions); + if (reOpenAllRegions(regions)) { - LOG.info("Completed table operation " + eventType + " on table " + - Bytes.toString(tableName)); - } else { - LOG.warn("Error on reopening the regions"); - } - } + LOG.info("Completed table operation " + eventType + " on table " + + Bytes.toString(tableName)); + } else { + LOG.warn("Error on reopening the regions"); + } + } - } catch (IOException e) { - LOG.error("Error manipulating table " + Bytes.toString(tableName), e); - } catch (KeeperException e) { - LOG.error("Error manipulating table " + Bytes.toString(tableName), e); - } + } - } public boolean reOpenAllRegions(List regions) throws IOException { boolean done = false; @@ -107,7 +127,8 @@ HTable table = new HTable(masterServices.getConfiguration(), tableName); TreeMap> serverToRegions = Maps .newTreeMap(); - NavigableMap hriHserverMapping = table.getRegionLocations(); + NavigableMap hriHserverMapping + = table.getRegionLocations(); for (HRegionInfo hri : regions) { ServerName rsLocation = hriHserverMapping.get(hri); @@ -138,6 +159,34 @@ } return done; } + + protected void handleInstantSchemaChanges() { + if (canPerformSchemaChange()) { + try { + MasterSchemaChangeTracker masterSchemaChangeTracker = + this.masterServices.getSchemaChangeTracker(); + // Turn the load balancer off if necessary. + boolean currentBalanceSwitch = master.balanceSwitch(false); + masterSchemaChangeTracker + .createSchemaChangeNode(Bytes.toString(tableName)); + while(!masterSchemaChangeTracker.doesSchemaChangeNodeExists( + Bytes.toString(tableName))) { + try { + Thread.sleep(50); + } catch (InterruptedException e) { + + } + } + if (currentBalanceSwitch) { + LOG.info("Schema change operation completed. Enabling load balancer now."); + this.master.balanceSwitch(true); + } + } catch (KeeperException e) { + LOG.warn("Instant schema change failed for table " + tableName, e); + } + } + } + protected abstract void handleTableOperation(List regions) throws IOException, KeeperException; } Index: src/main/java/org/apache/hadoop/hbase/master/MasterServices.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/MasterServices.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/MasterServices.java (revision ) @@ -26,7 +26,10 @@ import org.apache.hadoop.hbase.TableNotDisabledException; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.executor.ExecutorService; +import org.apache.hadoop.hbase.executor.EventHandler; +import org.apache.hadoop.hbase.zookeeper.MasterSchemaChangeTracker; + /** * Services Master supplies */ @@ -52,15 +55,26 @@ public ExecutorService getExecutorService(); /** - * Check table is modifiable; i.e. exists and is offline. - * @param tableName Name of table to check. - * @throws TableNotDisabledException - * @throws TableNotFoundException + * Check table modifiable. i.e not ROOT or META and offlined for all commands except + * alter commands + * @param tableName + * @param eventType + * @throws IOException */ - public void checkTableModifiable(final byte [] tableName) throws IOException; + public void checkTableModifiable(final byte [] tableName, + EventHandler.EventType eventType) + throws IOException; + /** * @return Return table descriptors implementation. */ public TableDescriptors getTableDescriptors(); + + /** + * Get Master Schema change tracker + * @return + */ + public MasterSchemaChangeTracker getSchemaChangeTracker(); + } Index: src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/ipc/HMasterInterface.java (revision ) @@ -223,13 +223,6 @@ public HTableDescriptor[] getHTableDescriptors(); /** - * Get current HTD for a given tablename - * @param tableName - * @return HTableDescriptor for the table - */ - //public HTableDescriptor getHTableDescriptor(final byte[] tableName); - - /** * Get array of HTDs for requested tables. * @param tableNames * @return array of HTableDescriptor Index: src/main/java/org/apache/hadoop/hbase/master/handler/ModifyTableHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/ModifyTableHandler.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/handler/ModifyTableHandler.java (revision ) @@ -25,6 +25,7 @@ import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.Server; +import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.util.Bytes; @@ -33,11 +34,19 @@ public ModifyTableHandler(final byte [] tableName, final HTableDescriptor htd, final Server server, - final MasterServices masterServices) throws IOException { - super(EventType.C_M_MODIFY_TABLE, tableName, server, masterServices); + final MasterServices masterServices, + final HMasterInterface masterInterface, + boolean instantModify) throws IOException { + super(EventType.C_M_MODIFY_TABLE, tableName, server, masterServices, + masterInterface, instantModify); this.htd = htd; + validateTable(tableName, htd); + } + + private void validateTable(final byte[] tableName, HTableDescriptor htd) + throws IOException { if (!Bytes.equals(tableName, htd.getName())) { - throw new IOException("TableDescriptor name & tableName must match: " + throw new IOException("TableDescriptor name & tableName must match: " + htd.getNameAsString() + " vs " + Bytes.toString(tableName)); } } Index: src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision ) @@ -135,6 +135,7 @@ import org.apache.hadoop.hbase.util.Threads; import org.apache.hadoop.hbase.util.VersionInfo; import org.apache.hadoop.hbase.zookeeper.ClusterStatusTracker; +import org.apache.hadoop.hbase.zookeeper.SchemaChangeTracker; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperNodeTracker; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; @@ -269,6 +270,9 @@ // Cluster Status Tracker private ClusterStatusTracker clusterStatusTracker; + // Schema change Tracker + private SchemaChangeTracker schemaChangeTracker; + // Log Splitting Worker private SplitLogWorker splitLogWorker; @@ -543,6 +547,11 @@ this.catalogTracker = new CatalogTracker(this.zooKeeper, this.conf, this, this.conf.getInt("hbase.regionserver.catalog.timeout", Integer.MAX_VALUE)); catalogTracker.start(); + + // Schema change tracker + this.schemaChangeTracker = new SchemaChangeTracker(this.zooKeeper, + this, this); + this.schemaChangeTracker.start(); } /** @@ -3114,4 +3123,81 @@ HLog wal = this.getWAL(); return wal.rollWriter(true); } + + /** + * Refresh schema changes for given regions. + * @param onlineRegionsOfTable + * @throws IOException + */ + private void reopenRegions(List onlineRegionsOfTable) throws IOException { + + if (!onlineRegionsOfTable.isEmpty()) { + for (HRegion hRegion : onlineRegionsOfTable) { + HRegionInfo regionInfo = hRegion.getRegionInfo(); + // Close the region + hRegion.close(); + // Remove from online regions + removeFromOnlineRegions(regionInfo.getEncodedName()); + // Get new HTD + HTableDescriptor htd = this.tableDescriptors.get(regionInfo.getTableName()); + LOG.debug("HTD for region = " + regionInfo.getRegionNameAsString() + + " Is = " + htd ); + HRegion region = + HRegion.openHRegion(hRegion.getRegionInfo(), htd, hlog, conf); + // Add new region to the onlineRegions + addToOnlineRegions(region); -} + } + } + } + + /** + * Gets the online regions of the specified table. + * This method looks at the in-memory onlineRegions. It does not go to .META.. + * Only returns online regions. If a region on this table has been + * closed during a disable, etc., it will not be included in the returned list. + * So, the returned list may not necessarily be ALL regions in this table, its + * all the ONLINE regions in the table. + * @param tableName + * @return Online regions from tableName + */ + private List getOnlineRegionsForTable(byte[] tableName) { + List tableRegions = new ArrayList(); + synchronized (this.onlineRegions) { + for (HRegion region: this.onlineRegions.values()) { + HRegionInfo regionInfo = region.getRegionInfo(); + if(Bytes.equals(regionInfo.getTableName(), tableName)) { + tableRegions.add(region); + } + } + } + return tableRegions; + + } + + /** + * Refresh schema changes to all online regions of given table. + * @param tableName + */ + public void refreshSchema(byte[] tableName) throws IOException { + List onlineRegionsForTable = null; + try { + onlineRegionsForTable = getOnlineRegionsForTable(tableName); + if (!onlineRegionsForTable.isEmpty()) { + LOG.debug("refreshSchema found " + onlineRegionsForTable + + " online regions for table = " + Bytes.toString(tableName) + + " Refreshing them now.."); + reopenRegions(onlineRegionsForTable); + } else { + LOG.debug("refreshSchema found no onlineRegions for table = " + + Bytes.toString(tableName) + ". Skipping refreshSchema..."); + } + } catch (IOException ioe) { + LOG.warn("refreshSchema failed with exception " + + " for table = " + Bytes.toString(tableName) + + " Number of regions online = " + + onlineRegionsForTable == null ? 0 : onlineRegionsForTable.size(), ioe); + throw ioe; + } + } + +} Index: src/main/java/org/apache/hadoop/hbase/master/handler/DeleteTableHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/DeleteTableHandler.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/handler/DeleteTableHandler.java (revision ) @@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.catalog.MetaEditor; +import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.master.AssignmentManager; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.util.Bytes; @@ -37,9 +38,10 @@ private static final Log LOG = LogFactory.getLog(DeleteTableHandler.class); public DeleteTableHandler(byte [] tableName, Server server, - final MasterServices masterServices) + final MasterServices masterServices, HMasterInterface masterInterface) throws IOException { - super(EventType.C_M_DELETE_TABLE, tableName, server, masterServices); + super(EventType.C_M_DELETE_TABLE, tableName, server, masterServices, + masterInterface); } @Override Index: src/test/java/org/apache/hadoop/hbase/regionserver/handler/MockRegionServerServices.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/regionserver/handler/MockRegionServerServices.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/test/java/org/apache/hadoop/hbase/regionserver/handler/MockRegionServerServices.java (revision ) @@ -54,6 +54,10 @@ return this.regions.get(encodedRegionName); } + public void refreshSchema(byte[] tableName) throws IOException { + // do nothing + } + @Override public void addToOnlineRegions(HRegion r) { this.regions.put(r.getRegionInfo().getEncodedName(), r); Index: src/main/ruby/hbase/admin.rb =================================================================== --- src/main/ruby/hbase/admin.rb (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/ruby/hbase/admin.rb (revision ) @@ -372,6 +372,9 @@ end end + #---------------------------------------------------------------------------------------------- + # Change table structure or table options + def status(format) status = @admin.getClusterStatus() if format == "detailed" Index: src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java (revision ) @@ -46,12 +46,14 @@ import org.apache.hadoop.hbase.TableExistsException; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.executor.EventHandler; import org.apache.hadoop.hbase.executor.ExecutorService; import org.apache.hadoop.hbase.io.Reference; import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.regionserver.Store; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Writables; +import org.apache.hadoop.hbase.zookeeper.MasterSchemaChangeTracker; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.junit.Test; import org.mockito.Mockito; @@ -128,11 +130,6 @@ } @Override - public void checkTableModifiable(byte[] tableName) throws IOException { - //no-op - } - - @Override public AssignmentManager getAssignmentManager() { return this.asm; } @@ -143,6 +140,12 @@ } @Override + public void checkTableModifiable(byte[] tableName, + EventHandler.EventType eventType) + throws IOException { + } + + @Override public MasterFileSystem getMasterFileSystem() { return this.mfs; } @@ -223,7 +226,11 @@ } }; } + + public MasterSchemaChangeTracker getSchemaChangeTracker() { + return null; - } + } + } @Test public void testGetHRegionInfo() throws IOException { Index: src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWatcher.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWatcher.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWatcher.java (revision ) @@ -85,6 +85,8 @@ public String clusterIdZNode; // znode used for log splitting work assignment public String splitLogZNode; + // znode used to record table schema changes + public String schemaZNode; private final Configuration conf; @@ -140,6 +142,7 @@ ZKUtil.createAndFailSilent(this, rsZNode); ZKUtil.createAndFailSilent(this, tableZNode); ZKUtil.createAndFailSilent(this, splitLogZNode); + ZKUtil.createAndFailSilent(this, schemaZNode); } catch (KeeperException e) { throw new ZooKeeperConnectionException( prefix("Unexpected KeeperException creating base node"), e); @@ -187,6 +190,9 @@ conf.get("zookeeper.znode.clusterId", "hbaseid")); splitLogZNode = ZKUtil.joinZNode(baseZNode, conf.get("zookeeper.znode.splitlog", HConstants.SPLIT_LOGDIR_NAME)); + schemaZNode = ZKUtil.joinZNode(baseZNode, + conf.get("zookeeper.znode.schema", "schema")); + } /** Index: src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision ) @@ -56,6 +56,7 @@ import org.apache.hadoop.hbase.client.MetaScanner; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; +import org.apache.hadoop.hbase.executor.EventHandler; import org.apache.hadoop.hbase.executor.ExecutorService; import org.apache.hadoop.hbase.executor.ExecutorService.ExecutorType; import org.apache.hadoop.hbase.ipc.HBaseRPC; @@ -90,6 +91,7 @@ import org.apache.hadoop.hbase.util.VersionInfo; import org.apache.hadoop.hbase.zookeeper.ClusterId; import org.apache.hadoop.hbase.zookeeper.ClusterStatusTracker; +import org.apache.hadoop.hbase.zookeeper.MasterSchemaChangeTracker; import org.apache.hadoop.hbase.zookeeper.RegionServerTracker; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.apache.hadoop.io.MapWritable; @@ -157,7 +159,10 @@ private CatalogTracker catalogTracker; // Cluster status zk tracker and local setter private ClusterStatusTracker clusterStatusTracker; - + + // Schema change tracker + private MasterSchemaChangeTracker schemaChangeTracker; + // buffer for "fatal error" notices from region servers // in the cluster. This is only used for assisting // operations/debugging. @@ -188,7 +193,9 @@ private final ServerName serverName; private TableDescriptors tableDescriptors; - + + private boolean supportInstantSchemaChanges = false; + /** * Initializes the HMaster. The steps are as follows: *

@@ -249,7 +256,18 @@ } this.zooKeeper = new ZooKeeperWatcher(conf, MASTER + ":" + isa.getPort(), this, true); this.metrics = new MasterMetrics(getServerName().toString()); + // initialize instant schema change settings + this.supportInstantSchemaChanges = conf.getBoolean( + "hbase.instant.schema.alter.enabled", false); + if (supportInstantSchemaChanges) { + LOG.info("Instant schema change enabled. All schema alter operations will " + + "happen through ZK."); - } + } + else { + LOG.info("Instant schema change disabled. All schema alter operations will " + + "happen normally."); + } + } /** * Stall startup if we are designated a backup master; i.e. we want someone @@ -377,6 +395,11 @@ boolean wasUp = this.clusterStatusTracker.isClusterUp(); if (!wasUp) this.clusterStatusTracker.setClusterUp(); + // initialize schema change tracker + this.schemaChangeTracker = new MasterSchemaChangeTracker(getZooKeeper(), + this); + this.schemaChangeTracker.start(); + LOG.info("Server active/primary master; " + this.serverName + ", sessionid=0x" + Long.toHexString(this.zooKeeper.getRecoverableZooKeeper().getSessionId()) + @@ -605,6 +628,11 @@ return this.tableDescriptors; } + @Override + public MasterSchemaChangeTracker getSchemaChangeTracker() { + return this.schemaChangeTracker; + } + /** @return InfoServer object. Maybe null.*/ public InfoServer getInfoServer() { return this.infoServer; @@ -987,7 +1015,7 @@ if (cpHost != null) { cpHost.preDeleteTable(tableName); } - this.executorService.submit(new DeleteTableHandler(tableName, this, this)); + this.executorService.submit(new DeleteTableHandler(tableName, this, this, this)); if (cpHost != null) { cpHost.postDeleteTable(tableName); @@ -1013,7 +1041,8 @@ return; } } - new TableAddFamilyHandler(tableName, column, this, this).process(); + new TableAddFamilyHandler(tableName, column, this, this, + this, supportInstantSchemaChanges).process(); if (cpHost != null) { cpHost.postAddColumn(tableName, column); } @@ -1026,7 +1055,8 @@ return; } } - new TableModifyFamilyHandler(tableName, descriptor, this, this).process(); + new TableModifyFamilyHandler(tableName, descriptor, this, this, + this, supportInstantSchemaChanges).process(); if (cpHost != null) { cpHost.postModifyColumn(tableName, descriptor); } @@ -1039,7 +1069,8 @@ return; } } - new TableDeleteFamilyHandler(tableName, c, this, this).process(); + new TableDeleteFamilyHandler(tableName, c, this, this, + this, supportInstantSchemaChanges).process(); if (cpHost != null) { cpHost.postDeleteColumn(tableName, c); } @@ -1106,22 +1137,32 @@ @Override public void modifyTable(final byte[] tableName, HTableDescriptor htd) - throws IOException { + throws IOException { if (cpHost != null) { cpHost.preModifyTable(tableName, htd); } - this.executorService.submit(new ModifyTableHandler(tableName, htd, this, - this)); - + this, this, supportInstantSchemaChanges)); if (cpHost != null) { cpHost.postModifyTable(tableName, htd); } } @Override - public void checkTableModifiable(final byte [] tableName) + public void checkTableModifiable(final byte [] tableName, + EventHandler.EventType eventType) throws IOException { + preCheckTableModifiable(tableName); + if (!eventType.isSchemaChangeEvent()) { + if (!getAssignmentManager().getZKTable(). + isDisabledTable(Bytes.toString(tableName))) { + throw new TableNotDisabledException(tableName); + } + } + } + + private void preCheckTableModifiable(final byte[] tableName) + throws IOException { String tableNameStr = Bytes.toString(tableName); if (isCatalogTable(tableName)) { throw new IOException("Can't modify catalog tables"); @@ -1129,12 +1170,9 @@ if (!MetaReader.tableExists(getCatalogTracker(), tableNameStr)) { throw new TableNotFoundException(tableNameStr); } - if (!getAssignmentManager().getZKTable(). - isDisabledTable(Bytes.toString(tableName))) { - throw new TableNotDisabledException(tableName); - } + } - } + public void clearFromTransition(HRegionInfo hri) { if (this.assignmentManager.isRegionInTransition(hri) != null) { this.assignmentManager.clearRegionFromTransition(hri); Index: src/main/java/org/apache/hadoop/hbase/master/handler/TableAddFamilyHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/TableAddFamilyHandler.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/master/handler/TableAddFamilyHandler.java (revision ) @@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.InvalidFamilyOperationException; import org.apache.hadoop.hbase.Server; +import org.apache.hadoop.hbase.ipc.HMasterInterface; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.util.Bytes; @@ -38,8 +39,10 @@ private final HColumnDescriptor familyDesc; public TableAddFamilyHandler(byte[] tableName, HColumnDescriptor familyDesc, - Server server, final MasterServices masterServices) throws IOException { - super(EventType.C_M_ADD_FAMILY, tableName, server, masterServices); + Server server, final MasterServices masterServices, + HMasterInterface masterInterface, boolean instantChange) throws IOException { + super(EventType.C_M_ADD_FAMILY, tableName, server, masterServices, + masterInterface, instantChange); this.familyDesc = familyDesc; } Index: src/main/resources/hbase-default.xml =================================================================== --- src/main/resources/hbase-default.xml (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/resources/hbase-default.xml (revision ) @@ -513,6 +513,15 @@ used for client / server RPC call marshalling. + + hbase.instant.schema.alter.enabled + false + Whether or not to handle alter schema changes instantly or not. + If enabled, all schema change alter operations will be instant, as the master will not + explicitly unassign/assign the impacted regions and instead will rely on Region servers to + refresh their schema changes. + +