Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1523883) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy) @@ -51,22 +51,21 @@ import org.apache.hadoop.hbase.Chore; import org.apache.hadoop.hbase.ClusterId; import org.apache.hadoop.hbase.ClusterStatus; -import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.HBaseIOException; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.constraint.ConstraintException; -import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.HealthCheckChore; import org.apache.hadoop.hbase.MasterNotRunningException; +import org.apache.hadoop.hbase.NamespaceDescriptor; +import org.apache.hadoop.hbase.NamespaceNotFoundException; import org.apache.hadoop.hbase.PleaseHoldException; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerLoad; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableDescriptors; +import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableNotDisabledException; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.UnknownRegionException; @@ -218,8 +217,11 @@ import org.apache.hadoop.net.DNS; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.Watcher; +import org.apache.hadoop.hbase.exceptions.DeserializationException; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.protobuf.Descriptors; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; @@ -366,7 +368,7 @@ /** The health check chore. */ private HealthCheckChore healthCheckChore; - + /** * is in distributedLogReplay mode. When true, SplitLogWorker directly replays WAL edits to newly * assigned region servers instead of creating recovered.edits files. @@ -489,7 +491,7 @@ } } - distributedLogReplay = this.conf.getBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, + distributedLogReplay = this.conf.getBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, HConstants.DEFAULT_DISTRIBUTED_LOG_REPLAY_CONFIG); } @@ -902,7 +904,7 @@ status.setStatus("Starting namespace manager"); initNamespace(); } - + if (this.cpHost != null) { try { this.cpHost.preMasterInitialization(); @@ -1361,6 +1363,7 @@ return !isStopped(); } + @Override public IsMasterRunningResponse isMasterRunning(RpcController c, IsMasterRunningRequest req) throws ServiceException { return IsMasterRunningResponse.newBuilder().setIsMasterRunning(isMasterRunning()).build(); @@ -1718,9 +1721,7 @@ } String namespace = hTableDescriptor.getTableName().getNamespaceAsString(); - if (getNamespaceDescriptor(namespace) == null) { - throw new ConstraintException("Namespace " + namespace + " does not exist"); - } + getNamespaceDescriptor(namespace); // ensure namespace exists HRegionInfo[] newRegions = getHRegionInfos(hTableDescriptor, splitKeys); checkInitialized(); @@ -2101,6 +2102,7 @@ } } Collections.sort(backupMasters, new Comparator() { + @Override public int compare(ServerName s1, ServerName s2) { return s1.getServerName().compareTo(s2.getServerName()); }}); @@ -2208,6 +2210,7 @@ this.zooKeeper.reconnectAfterExpiration(); Callable callable = new Callable () { + @Override public Boolean call() throws InterruptedException, IOException, KeeperException { MonitoredTask status = @@ -2383,6 +2386,7 @@ return this.stopped; } + @Override public boolean isAborted() { return this.abort; } @@ -2414,6 +2418,7 @@ * * @return true if master is ready to go, false if not. */ + @Override public boolean isInitialized() { return initialized; } @@ -2423,6 +2428,7 @@ * assignMeta to prevent processing of ServerShutdownHandler. * @return true if assignMeta has completed; */ + @Override public boolean isServerShutdownHandlerEnabled() { return this.serverShutdownHandlerEnabled; } @@ -2521,6 +2527,7 @@ * @return GetTableDescriptorsResponse * @throws ServiceException */ + @Override public GetTableDescriptorsResponse getTableDescriptors( RpcController controller, GetTableDescriptorsRequest req) throws ServiceException { List descriptors = new ArrayList(); @@ -2589,6 +2596,7 @@ * @return GetTableNamesResponse * @throws ServiceException */ + @Override public GetTableNamesResponse getTableNames( RpcController controller, GetTableNamesRequest req) throws ServiceException { try { @@ -3030,6 +3038,7 @@ return org.apache.commons.lang.StringUtils.isNotBlank(healthScriptLocation); } + @Override public void createNamespace(NamespaceDescriptor descriptor) throws IOException { TableName.isLegalNamespaceName(Bytes.toBytes(descriptor.getName())); if (cpHost != null) { @@ -3044,6 +3053,7 @@ } } + @Override public void modifyNamespace(NamespaceDescriptor descriptor) throws IOException { TableName.isLegalNamespaceName(Bytes.toBytes(descriptor.getName())); if (cpHost != null) { @@ -3058,6 +3068,7 @@ } } + @Override public void deleteNamespace(String name) throws IOException { if (cpHost != null) { if (cpHost.preDeleteNamespace(name)) { @@ -3071,19 +3082,29 @@ } } + @Override public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException { - return tableNamespaceManager.get(name); + NamespaceDescriptor nsd = tableNamespaceManager.get(name); + if (nsd == null) { + throw new NamespaceNotFoundException(name); + } + return nsd; } + @Override public List listNamespaceDescriptors() throws IOException { return Lists.newArrayList(tableNamespaceManager.list()); } + @Override public List listTableDescriptorsByNamespace(String name) throws IOException { + getNamespaceDescriptor(name); // check that namespace exists return Lists.newArrayList(tableDescriptors.getByNamespace(name).values()); } + @Override public List listTableNamesByNamespace(String name) throws IOException { + getNamespaceDescriptor(name); // check that namespace exists List tableNames = Lists.newArrayList(); for (HTableDescriptor descriptor: tableDescriptors.getByNamespace(name).values()) { tableNames.add(descriptor.getTableName()); Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java (revision 1523883) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java (working copy) @@ -33,6 +33,8 @@ import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.NamespaceDescriptor; +import org.apache.hadoop.hbase.NamespaceExistException; +import org.apache.hadoop.hbase.NamespaceNotFoundException; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ZKNamespaceManager; import org.apache.hadoop.hbase.catalog.MetaReader; @@ -113,14 +115,14 @@ nsTable = new HTable(conf, TableName.NAMESPACE_TABLE_NAME); zkNamespaceManager = new ZKNamespaceManager(masterServices.getZooKeeper()); zkNamespaceManager.start(); - + if (get(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE.getName()) == null) { create(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE); } if (get(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE.getName()) == null) { create(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE); } - + ResultScanner scanner = nsTable.getScanner(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES); try { for(Result result : scanner) { @@ -160,7 +162,7 @@ public synchronized void update(NamespaceDescriptor ns) throws IOException { HTable table = getNamespaceTable(); if (get(table, ns.getName()) == null) { - throw new ConstraintException("Namespace "+ns.getName()+" does not exist"); + throw new NamespaceNotFoundException(ns.getName()); } upsert(table, ns); } @@ -179,7 +181,7 @@ private void create(HTable table, NamespaceDescriptor ns) throws IOException { if (get(table, ns.getName()) != null) { - throw new ConstraintException("Namespace "+ns.getName()+" already exists"); + throw new NamespaceExistException(ns.getName()); } FileSystem fs = masterServices.getMasterFileSystem().getFileSystem(); fs.mkdirs(FSUtils.getNamespaceDir( @@ -203,6 +205,9 @@ } public synchronized void remove(String name) throws IOException { + if (get(name) == null) { + throw new NamespaceNotFoundException(name); + } if (NamespaceDescriptor.RESERVED_NAMESPACES.contains(name)) { throw new ConstraintException("Reserved namespace "+name+" cannot be removed."); } @@ -210,7 +215,7 @@ try { tableCount = masterServices.listTableDescriptorsByNamespace(name).size(); } catch (FileNotFoundException fnfe) { - throw new ConstraintException("namespace " + name + " does not exist"); + throw new NamespaceNotFoundException(name); } if (tableCount > 0) { throw new ConstraintException("Only empty namespaces can be removed. " + Index: hbase-server/src/test/java/org/apache/hadoop/hbase/TestNamespace.java =================================================================== --- hbase-server/src/test/java/org/apache/hadoop/hbase/TestNamespace.java (revision 1523883) +++ hbase-server/src/test/java/org/apache/hadoop/hbase/TestNamespace.java (working copy) @@ -18,7 +18,17 @@ */ package org.apache.hadoop.hbase; -import com.google.common.collect.Sets; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.Set; +import java.util.concurrent.Callable; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.fs.FileSystem; @@ -33,7 +43,9 @@ import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; +import com.google.common.collect.Sets; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; @@ -117,8 +129,8 @@ } //verify system tables aren't listed assertEquals(0, admin.listTables().length); - - //Try creating default and system namespaces. + + //Try creating default and system namespaces. boolean exceptionCaught = false; try { admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE); @@ -139,7 +151,7 @@ assertTrue(exceptionCaught); } } - + @Test public void testDeleteReservedNS() throws Exception { boolean exceptionCaught = false; @@ -192,7 +204,7 @@ LOG.info(testName); byte[] tableName = Bytes.toBytes("my_table"); - byte[] tableNameFoo = Bytes.toBytes(nsName+".my_table"); + byte[] tableNameFoo = Bytes.toBytes(nsName+":my_table"); //create namespace and verify admin.createNamespace(NamespaceDescriptor.create(nsName).build()); TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName)); @@ -219,8 +231,8 @@ desc.addFamily(colDesc); try { admin.createTable(desc); - fail("Expected no namespace constraint exception"); - } catch (ConstraintException ex) { + fail("Expected no namespace exists exception"); + } catch (NamespaceNotFoundException ex) { } //create table and in new namespace admin.createNamespace(NamespaceDescriptor.create(nsName).build()); @@ -262,7 +274,7 @@ HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); desc.addFamily(colDesc); admin.createTable(desc); - assertTrue(admin.listTables().length == 1); + assertTrue(admin.listTables().length == 1); admin.disableTable(desc.getTableName()); admin.deleteTable(desc.getTableName()); } @@ -307,4 +319,109 @@ ZooKeeperWatcher.namespaceZNode).size()); } + @Test(timeout = 60000) + public void testNamespaceOperations() throws IOException { + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()); + + // create namespace that already exists + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); + return null; + } + }, NamespaceExistException.class); + + // create a table in non-existing namespace + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("non_existing_namespace", "table1")); + htd.addFamily(new HColumnDescriptor("family1")); + admin.createTable(htd); + return null; + } + }, NamespaceNotFoundException.class); + + // get descriptor for existing namespace + admin.getNamespaceDescriptor(prefix + "ns1"); + + // get descriptor for non-existing namespace + runWithExpectedException(new Callable() { + @Override + public NamespaceDescriptor call() throws Exception { + return admin.getNamespaceDescriptor("non_existing_namespace"); + } + }, NamespaceNotFoundException.class); + + // delete descriptor for existing namespace + admin.deleteNamespace(prefix + "ns2"); + + // delete descriptor for non-existing namespace + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + admin.deleteNamespace("non_existing_namespace"); + return null; + } + }, NamespaceNotFoundException.class); + + // modify namespace descriptor for existing namespace + NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1"); + ns1.setConfiguration("foo", "bar"); + admin.modifyNamespace(ns1); + + // modify namespace descriptor for non-existing namespace + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()); + return null; + } + }, NamespaceNotFoundException.class); + + // get table descriptors for existing namespace + HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(prefix + "ns1", "table1")); + htd.addFamily(new HColumnDescriptor("family1")); + admin.createTable(htd); + HTableDescriptor[] htds = admin.listTableDescriptorsByNamespace(prefix + "ns1"); + assertNotNull("Should have not returned null", htds); + assertEquals("Should have returned non-empty array", 1, htds.length); + + // get table descriptors for non-existing namespace + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + admin.listTableDescriptorsByNamespace("non_existing_namespace"); + return null; + } + }, NamespaceNotFoundException.class); + + // get table names for existing namespace + TableName[] tableNames = admin.listTableNamesByNamespace(prefix + "ns1"); + assertNotNull("Should have not returned null", tableNames); + assertEquals("Should have returned non-empty array", 1, tableNames.length); + + // get table names for non-existing namespace + runWithExpectedException(new Callable() { + @Override + public Void call() throws Exception { + admin.listTableNamesByNamespace("non_existing_namespace"); + return null; + } + }, NamespaceNotFoundException.class); + + } + + private static void runWithExpectedException(Callable callable, Class exceptionClass) { + try { + callable.call(); + } catch(Exception ex) { + Assert.assertEquals(exceptionClass, ex.getClass()); + return; + } + fail("Should have thrown exception " + exceptionClass); + } + }