Index: src/main/java/org/apache/hadoop/hbase/avro/AvroServer.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/avro/AvroServer.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/avro/AvroServer.java (revision ) @@ -283,7 +283,7 @@ public Void modifyTable(ByteBuffer tableName, ATableDescriptor tableDescriptor) throws AIOError { try { admin.modifyTable(Bytes.toBytes(tableName), - AvroUtil.atdToHTD(tableDescriptor)); + AvroUtil.atdToHTD(tableDescriptor), false); return null; } catch (IOException e) { AIOError ioe = new AIOError(); @@ -353,7 +353,7 @@ public Void addFamily(ByteBuffer table, AFamilyDescriptor family) throws AIOError { try { admin.addColumn(Bytes.toBytes(table), - AvroUtil.afdToHCD(family)); + AvroUtil.afdToHCD(family), false); return null; } catch (IOException e) { AIOError ioe = new AIOError(); @@ -365,7 +365,7 @@ // NB: Asynchronous operation public Void deleteFamily(ByteBuffer table, ByteBuffer family) throws AIOError { try { - admin.deleteColumn(Bytes.toBytes(table), Bytes.toBytes(family)); + admin.deleteColumn(Bytes.toBytes(table), Bytes.toBytes(family), false); return null; } catch (IOException e) { AIOError ioe = new AIOError(); @@ -377,7 +377,7 @@ // NB: Asynchronous operation public Void modifyFamily(ByteBuffer table, ByteBuffer familyName, AFamilyDescriptor familyDescriptor) throws AIOError { try { - admin.modifyColumn(Bytes.toBytes(table), AvroUtil.afdToHCD(familyDescriptor)); + admin.modifyColumn(Bytes.toBytes(table), AvroUtil.afdToHCD(familyDescriptor), false); return null; } catch (IOException e) { AIOError ioe = new AIOError(); 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 ) @@ -89,8 +89,19 @@ * Adds a column to the specified table * @param tableName table to modify * @param column column descriptor + * @param instantAdd Set to True if the addColumn operation + * should happen instantly. * @throws IOException e */ + public void addColumn(final byte [] tableName, HColumnDescriptor column, + boolean instantAdd) throws IOException; + + /** + * Adds a column to the specified table + * @param tableName table to modify + * @param column column descriptor + * @throws IOException e + */ public void addColumn(final byte [] tableName, HColumnDescriptor column) throws IOException; @@ -98,8 +109,20 @@ * Modifies an existing column on the specified table * @param tableName table name * @param descriptor new column descriptor + * @param instantModify Set to True if the modifyColumn operation + * should happen instantly. * @throws IOException e */ + public void modifyColumn(final byte [] tableName, + HColumnDescriptor descriptor, + boolean instantModify) throws IOException; + + /** + * Modifies an existing column on the specified table + * @param tableName table name + * @param descriptor new column descriptor + * @throws IOException e + */ public void modifyColumn(final byte [] tableName, HColumnDescriptor descriptor) throws IOException; @@ -114,6 +137,17 @@ throws IOException; /** + * Deletes a column from the specified table. Table must be disabled. + * @param tableName table to alter + * @param columnName column family to remove + * @param instantDelete Set to True if the deleteColumn operation + * should happen instantly. + * @throws IOException e + */ + public void deleteColumn(final byte [] tableName, final byte [] columnName, + boolean instantDelete) throws IOException; + + /** * Puts the table on-line (only needed if table has been previously taken offline) * @param tableName table to enable * @throws IOException e @@ -133,8 +167,20 @@ * * @param tableName table to modify * @param htd new descriptor for table + * @param instantModify Set to true to if the modifyTable action should + * happen instantly. * @throws IOException e */ + public void modifyTable(byte[] tableName, HTableDescriptor htd, + boolean instantModify) throws IOException; + + /** + * Modify a table's metadata + * + * @param tableName table to modify + * @param htd new descriptor for table + * @throws IOException e + */ public void modifyTable(byte[] tableName, HTableDescriptor htd) throws IOException; @@ -223,13 +269,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/rest/SchemaResource.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913) +++ src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java (revision ) @@ -124,7 +124,7 @@ } if (admin.tableExists(name)) { admin.disableTable(name); - admin.modifyTable(name, htd); + admin.modifyTable(name, htd, false); admin.enableTable(name); } else try { admin.createTable(htd); @@ -154,9 +154,9 @@ hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString()); } if (htd.hasFamily(hcd.getName())) { - admin.modifyColumn(name, hcd); + admin.modifyColumn(name, hcd, false); } else { - admin.addColumn(name, hcd); + admin.addColumn(name, hcd, false); } } } catch (IOException e) { 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/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; } @@ -142,7 +139,17 @@ return null; } + public void checkTableModifiable(byte[] tableName) throws IOException { + + } + @Override + public void checkTableModifiable(byte[] tableName, + EventHandler.EventType eventType) + throws IOException { + } + + @Override public MasterFileSystem getMasterFileSystem() { return this.mfs; } @@ -223,7 +230,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,6 +256,9 @@
}
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);
}
/**
@@ -377,6 +387,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 +620,11 @@
return this.tableDescriptors;
}
+ @Override
+ public MasterSchemaChangeTracker getSchemaChangeTracker() {
+ return this.schemaChangeTracker;
+ }
+
/** @return InfoServer object. Maybe null.*/
public InfoServer getInfoServer() {
return this.infoServer;
@@ -987,7 +1007,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);
@@ -1008,12 +1028,22 @@
public void addColumn(byte [] tableName, HColumnDescriptor column)
throws IOException {
+ addColumn(tableName, column, false);
+ }
+
+ public void addColumn(byte [] tableName, HColumnDescriptor column, boolean insantAdd)
+ throws IOException {
if (cpHost != null) {
if (cpHost.preAddColumn(tableName, column)) {
return;
}
}
+ if (insantAdd || supportInstantSchemaChanges) {
+ new TableAddFamilyHandler(tableName, column, this, this,
+ this).process();
+ } else {
- new TableAddFamilyHandler(tableName, column, this, this).process();
+ new TableAddFamilyHandler(tableName, column, this, this).process();
+ }
if (cpHost != null) {
cpHost.postAddColumn(tableName, column);
}
@@ -1021,12 +1051,25 @@
public void modifyColumn(byte [] tableName, HColumnDescriptor descriptor)
throws IOException {
+ modifyColumn(tableName, descriptor, false);
+ }
+
+ public void modifyColumn(byte [] tableName, HColumnDescriptor descriptor,
+ boolean instantModify) throws IOException {
if (cpHost != null) {
if (cpHost.preModifyColumn(tableName, descriptor)) {
return;
}
}
- new TableModifyFamilyHandler(tableName, descriptor, this, this).process();
+ if (instantModify || supportInstantSchemaChanges) {
+ new TableModifyFamilyHandler(tableName, descriptor, this, this,
+ this).process();
+
+ } else {
+ new TableModifyFamilyHandler(tableName, descriptor, this,
+ this).process();
+ }
+
if (cpHost != null) {
cpHost.postModifyColumn(tableName, descriptor);
}
@@ -1034,12 +1077,22 @@
public void deleteColumn(final byte [] tableName, final byte [] c)
throws IOException {
+ deleteColumn(tableName, c, false);
+ }
+
+ public void deleteColumn(final byte [] tableName, final byte [] c,
+ boolean instantDelete) throws IOException {
if (cpHost != null) {
if (cpHost.preDeleteColumn(tableName, c)) {
return;
}
}
+ if (instantDelete || supportInstantSchemaChanges) {
+ new TableDeleteFamilyHandler(tableName, c, this, this,
+ this).process();
+ } else {
- new TableDeleteFamilyHandler(tableName, c, this, this).process();
+ new TableDeleteFamilyHandler(tableName, c, this, this).process();
+ }
if (cpHost != null) {
cpHost.postDeleteColumn(tableName, c);
}
@@ -1107,12 +1160,22 @@
@Override
public void modifyTable(final byte[] tableName, HTableDescriptor htd)
throws IOException {
+ modifyTable(tableName, htd, false);
+ }
+
+ @Override
+ public void modifyTable(final byte[] tableName, HTableDescriptor htd,
+ boolean instantModify) throws IOException {
if (cpHost != null) {
cpHost.preModifyTable(tableName, htd);
}
-
+ if (instantModify || supportInstantSchemaChanges) {
- this.executorService.submit(new ModifyTableHandler(tableName, htd, this,
+ this.executorService.submit(new ModifyTableHandler(tableName, htd, this,
+ this, this));
+ } else {
+ this.executorService.submit(new ModifyTableHandler(tableName, htd, this,
- this));
+ this));
+ }
if (cpHost != null) {
cpHost.postModifyTable(tableName, htd);
@@ -1120,8 +1183,20 @@
}
@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 +1204,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/client/HBaseAdmin.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913)
+++ src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (revision )
@@ -890,10 +890,12 @@
*
* @param tableName name of the table to add column to
* @param column column descriptor of column to be added
+ * @param instantAdd set to True if the addColumn should happen instantly
+ * through ZK. By default, addColumn
* @throws IOException if a remote or network exception occurs
*/
public void addColumn(final String tableName, HColumnDescriptor column)
- throws IOException {
+ throws IOException {
addColumn(Bytes.toBytes(tableName), column);
}
@@ -906,7 +908,7 @@
* @throws IOException if a remote or network exception occurs
*/
public void addColumn(final byte [] tableName, HColumnDescriptor column)
- throws IOException {
+ throws IOException {
HTableDescriptor.isLegalTableName(tableName);
try {
getMaster().addColumn(tableName, column);
@@ -916,16 +918,50 @@
}
/**
+ * Add a column to an existing table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of the table to add column to
+ * @param column column descriptor of column to be added
+ * @param instantAdd set to True if the addColumn should happen instantly.
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void addColumn(final String tableName, HColumnDescriptor column,
+ boolean instantAdd) throws IOException {
+ addColumn(Bytes.toBytes(tableName), column, instantAdd);
+ }
+
+ /**
+ * Add a column to an existing table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of the table to add column to
+ * @param column column descriptor of column to be added
+ * @param instantAdd set to True if the addColumn should happen instantly.
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void addColumn(final byte [] tableName, HColumnDescriptor column,
+ boolean instantAdd) throws IOException {
+ HTableDescriptor.isLegalTableName(tableName);
+ try {
+ getMaster().addColumn(tableName, column, instantAdd);
+ } catch (RemoteException e) {
+ throw RemoteExceptionHandler.decodeRemoteException(e);
+ }
+ }
+
+ /**
* Delete a column from a table.
* Asynchronous operation.
*
* @param tableName name of table
* @param columnName name of column to be deleted
+ * @param instantDelete set to True if the deleteColumn should happen instantly.
* @throws IOException if a remote or network exception occurs
*/
- public void deleteColumn(final String tableName, final String columnName)
- throws IOException {
- deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName));
+ public void deleteColumn(final String tableName, final String columnName,
+ boolean instantDelete) throws IOException {
+ deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName), instantDelete);
}
/**
@@ -937,7 +973,7 @@
* @throws IOException if a remote or network exception occurs
*/
public void deleteColumn(final byte [] tableName, final byte [] columnName)
- throws IOException {
+ throws IOException {
try {
getMaster().deleteColumn(tableName, columnName);
} catch (RemoteException e) {
@@ -946,6 +982,37 @@
}
/**
+ * Delete a column from a table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of table
+ * @param columnName name of column to be deleted
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void deleteColumn(final String tableName, final String columnName)
+ throws IOException {
+ deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName));
+ }
+
+ /**
+ * Delete a column from a table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of table
+ * @param columnName name of column to be deleted
+ * @param instantDelete set to True if the deleteColumn should happen instantly.
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void deleteColumn(final byte [] tableName, final byte [] columnName,
+ boolean instantDelete) throws IOException {
+ try {
+ getMaster().deleteColumn(tableName, columnName, instantDelete);
+ } catch (RemoteException e) {
+ throw RemoteExceptionHandler.decodeRemoteException(e);
+ }
+ }
+
+ /**
* Modify an existing column family on a table.
* Asynchronous operation.
*
@@ -1011,6 +1078,41 @@
}
/**
+ * Modify an existing column family on a table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of table
+ * @param descriptor new column descriptor to use
+ * @param instantModify Set to true if modifyColumn should happen instantly
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void modifyColumn(final String tableName, HColumnDescriptor descriptor,
+ boolean instantModify) throws IOException {
+ modifyColumn(Bytes.toBytes(tableName), descriptor);
+ }
+
+ /**
+ * Modify an existing column family on a table.
+ * Asynchronous operation.
+ *
+ * @param tableName name of table
+ * @param descriptor new column descriptor to use
+ * @param instantModify Set to true if modifyColumn should happen instantly
+ * @throws IOException if a remote or network exception occurs
+ */
+ public void modifyColumn(final byte [] tableName, HColumnDescriptor descriptor,
+ boolean instantModify) throws IOException {
+ try {
+ getMaster().modifyColumn(tableName, descriptor, instantModify);
+ } catch (RemoteException re) {
+ // Convert RE exceptions in here; client shouldn't have to deal with them,
+ // at least w/ the type of exceptions that come out of this method:
+ // TableNotFoundException, etc.
+ throw RemoteExceptionHandler.decodeRemoteException(re);
+ }
+ }
+
+ /**
* Close a region. For expert-admins. Runs close on the regionserver. The
* master will not be informed of the close.
* @param regionname region name to close
@@ -1444,10 +1546,10 @@
* @param htd modified description of the table
* @throws IOException if a remote or network exception occurs
*/
- public void modifyTable(final byte [] tableName, HTableDescriptor htd)
+ public void modifyTable(final byte [] tableName, HTableDescriptor htd, boolean instantModify)
throws IOException {
try {
- getMaster().modifyTable(tableName, htd);
+ getMaster().modifyTable(tableName, htd, instantModify);
} catch (RemoteException re) {
// Convert RE exceptions in here; client shouldn't have to deal with them,
// at least w/ the type of exceptions that come out of this method:
Index: src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
===================================================================
--- src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913)
+++ src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java (revision )
@@ -541,20 +541,20 @@
// modify table
htd.setMaxFileSize(512 * 1024 * 1024);
- admin.modifyTable(TEST_TABLE, htd);
+ admin.modifyTable(TEST_TABLE, htd, false);
// preModifyTable can't bypass default action.
assertTrue("Test table should have been modified",
cp.wasModifyTableCalled());
// add a column family
- admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
+ admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2), false);
assertTrue("New column family shouldn't have been added to test table",
cp.preAddColumnCalledOnly());
// modify a column family
HColumnDescriptor hcd1 = new HColumnDescriptor(TEST_FAMILY2);
hcd1.setMaxVersions(25);
- admin.modifyColumn(TEST_TABLE, hcd1);
+ admin.modifyColumn(TEST_TABLE, hcd1, false);
assertTrue("Second column family should be modified",
cp.preModifyColumnCalledOnly());
@@ -584,19 +584,19 @@
// modify table
htd.setMaxFileSize(512 * 1024 * 1024);
- admin.modifyTable(TEST_TABLE, htd);
+ admin.modifyTable(TEST_TABLE, htd, false);
assertTrue("Test table should have been modified",
cp.wasModifyTableCalled());
// add a column family
- admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
+ admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2), false);
assertTrue("New column family should have been added to test table",
cp.wasAddColumnCalled());
// modify a column family
HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
hcd.setMaxVersions(25);
- admin.modifyColumn(TEST_TABLE, hcd);
+ admin.modifyColumn(TEST_TABLE, hcd, false);
assertTrue("Second column family should be modified",
cp.wasModifyColumnCalled());
@@ -613,7 +613,7 @@
// delete column
assertFalse("No column family deleted yet", cp.wasDeleteColumnCalled());
- admin.deleteColumn(TEST_TABLE, TEST_FAMILY2);
+ admin.deleteColumn(TEST_TABLE, TEST_FAMILY2, false);
HTableDescriptor tableDesc = admin.getTableDescriptor(TEST_TABLE);
assertNull("'"+Bytes.toString(TEST_FAMILY2)+"' should have been removed",
tableDesc.getFamily(TEST_FAMILY2));
Index: src/main/java/org/apache/hadoop/hbase/executor/EventHandler.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/executor/EventHandler.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913)
+++ src/main/java/org/apache/hadoop/hbase/executor/EventHandler.java (revision )
@@ -140,14 +140,14 @@
* Constructor
*/
EventType(int value) {}
- public boolean isOnlineSchemaChangeSupported() {
+ public boolean isSchemaChangeEvent() {
return (
- this.equals(EventType.C_M_ADD_FAMILY) ||
- this.equals(EventType.C_M_DELETE_FAMILY) ||
- this.equals(EventType.C_M_MODIFY_FAMILY) ||
+ this.equals(EventType.C_M_ADD_FAMILY) ||
+ this.equals(EventType.C_M_DELETE_FAMILY) ||
+ this.equals(EventType.C_M_MODIFY_FAMILY) ||
- this.equals(EventType.C_M_MODIFY_TABLE)
- );
+ this.equals(EventType.C_M_MODIFY_TABLE));
}
+
}
/**
Index: src/main/java/org/apache/hadoop/hbase/regionserver/OnlineRegions.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/regionserver/OnlineRegions.java (revision 483a54d3d0a6c9a89205b0541303c1aabf512913)
+++ src/main/java/org/apache/hadoop/hbase/regionserver/OnlineRegions.java (revision )
@@ -21,6 +21,8 @@
import org.apache.hadoop.hbase.Server;
+import java.io.IOException;
+
/**
* Interface to Map of online regions. In the Map, the key is the region's
* encoded name and the value is an {@link HRegion} instance.
@@ -49,4 +51,11 @@
* null if named region is not member of the online regions.
*/
public HRegion getFromOnlineRegions(String encodedRegionName);
+
+ /**
+ * Refresh schema for online regions of a table.
+ * @param tableName
+ * @return
+ */
+ public void refreshSchema(byte[] tableName) throws IOException;
}
\ No newline at end of file
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 )
@@ -36,8 +36,10 @@
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.zookeeper.KeeperException;
+import org.apache.hadoop.hbase.zookeeper.MasterSchemaChangeTracker;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -52,8 +54,10 @@
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)
@@ -61,19 +65,18 @@
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);
}
+ public TableEventHandler(EventType eventType, byte [] tableName, Server server,
+ MasterServices masterServices, HMasterInterface masterInterface)
+ throws IOException {
+ this(eventType, tableName, server, masterServices);
+ this.instantAction = true;
+ this.master = masterInterface;
+ }
+
@Override
public void process() {
try {
@@ -83,23 +86,37 @@
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.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