HBASE-9510 Namespace operations should throw clean exceptions
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1523902 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
866a2c6c42
commit
040b53e09a
|
@ -51,22 +51,21 @@ import org.apache.hadoop.hbase.Abortable;
|
|||
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.metrics.util.MBeanUtil;
|
|||
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 @@ MasterServices, Server {
|
|||
|
||||
/** 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 @@ MasterServices, Server {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ MasterServices, Server {
|
|||
status.setStatus("Starting namespace manager");
|
||||
initNamespace();
|
||||
}
|
||||
|
||||
|
||||
if (this.cpHost != null) {
|
||||
try {
|
||||
this.cpHost.preMasterInitialization();
|
||||
|
@ -1361,6 +1363,7 @@ MasterServices, Server {
|
|||
return !isStopped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsMasterRunningResponse isMasterRunning(RpcController c, IsMasterRunningRequest req)
|
||||
throws ServiceException {
|
||||
return IsMasterRunningResponse.newBuilder().setIsMasterRunning(isMasterRunning()).build();
|
||||
|
@ -1718,9 +1721,7 @@ MasterServices, Server {
|
|||
}
|
||||
|
||||
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 @@ MasterServices, Server {
|
|||
}
|
||||
}
|
||||
Collections.sort(backupMasters, new Comparator<ServerName>() {
|
||||
@Override
|
||||
public int compare(ServerName s1, ServerName s2) {
|
||||
return s1.getServerName().compareTo(s2.getServerName());
|
||||
}});
|
||||
|
@ -2208,6 +2210,7 @@ MasterServices, Server {
|
|||
this.zooKeeper.reconnectAfterExpiration();
|
||||
|
||||
Callable<Boolean> callable = new Callable<Boolean> () {
|
||||
@Override
|
||||
public Boolean call() throws InterruptedException,
|
||||
IOException, KeeperException {
|
||||
MonitoredTask status =
|
||||
|
@ -2383,6 +2386,7 @@ MasterServices, Server {
|
|||
return this.stopped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAborted() {
|
||||
return this.abort;
|
||||
}
|
||||
|
@ -2414,6 +2418,7 @@ MasterServices, Server {
|
|||
*
|
||||
* @return true if master is ready to go, false if not.
|
||||
*/
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
@ -2423,6 +2428,7 @@ MasterServices, Server {
|
|||
* assignMeta to prevent processing of ServerShutdownHandler.
|
||||
* @return true if assignMeta has completed;
|
||||
*/
|
||||
@Override
|
||||
public boolean isServerShutdownHandlerEnabled() {
|
||||
return this.serverShutdownHandlerEnabled;
|
||||
}
|
||||
|
@ -2521,6 +2527,7 @@ MasterServices, Server {
|
|||
* @return GetTableDescriptorsResponse
|
||||
* @throws ServiceException
|
||||
*/
|
||||
@Override
|
||||
public GetTableDescriptorsResponse getTableDescriptors(
|
||||
RpcController controller, GetTableDescriptorsRequest req) throws ServiceException {
|
||||
List<HTableDescriptor> descriptors = new ArrayList<HTableDescriptor>();
|
||||
|
@ -2589,6 +2596,7 @@ MasterServices, Server {
|
|||
* @return GetTableNamesResponse
|
||||
* @throws ServiceException
|
||||
*/
|
||||
@Override
|
||||
public GetTableNamesResponse getTableNames(
|
||||
RpcController controller, GetTableNamesRequest req) throws ServiceException {
|
||||
try {
|
||||
|
@ -3030,6 +3038,7 @@ MasterServices, Server {
|
|||
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 @@ MasterServices, Server {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyNamespace(NamespaceDescriptor descriptor) throws IOException {
|
||||
TableName.isLegalNamespaceName(Bytes.toBytes(descriptor.getName()));
|
||||
if (cpHost != null) {
|
||||
|
@ -3058,6 +3068,7 @@ MasterServices, Server {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteNamespace(String name) throws IOException {
|
||||
if (cpHost != null) {
|
||||
if (cpHost.preDeleteNamespace(name)) {
|
||||
|
@ -3071,19 +3082,29 @@ MasterServices, Server {
|
|||
}
|
||||
}
|
||||
|
||||
@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<NamespaceDescriptor> listNamespaceDescriptors() throws IOException {
|
||||
return Lists.newArrayList(tableNamespaceManager.list());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) throws IOException {
|
||||
getNamespaceDescriptor(name); // check that namespace exists
|
||||
return Lists.newArrayList(tableDescriptors.getByNamespace(name).values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableName> listTableNamesByNamespace(String name) throws IOException {
|
||||
getNamespaceDescriptor(name); // check that namespace exists
|
||||
List<TableName> tableNames = Lists.newArrayList();
|
||||
for (HTableDescriptor descriptor: tableDescriptors.getByNamespace(name).values()) {
|
||||
tableNames.add(descriptor.getTableName());
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.apache.hadoop.hbase.HConstants;
|
|||
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 @@ public class TableNamespaceManager {
|
|||
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 class TableNamespaceManager {
|
|||
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 @@ public class TableNamespaceManager {
|
|||
|
||||
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 class TableNamespaceManager {
|
|||
}
|
||||
|
||||
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 @@ public class TableNamespaceManager {
|
|||
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. " +
|
||||
|
|
|
@ -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.Bytes;
|
|||
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 @@ public class TestNamespace {
|
|||
}
|
||||
//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 @@ public class TestNamespace {
|
|||
assertTrue(exceptionCaught);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteReservedNS() throws Exception {
|
||||
boolean exceptionCaught = false;
|
||||
|
@ -192,7 +204,7 @@ public class TestNamespace {
|
|||
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 @@ public class TestNamespace {
|
|||
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 @@ public class TestNamespace {
|
|||
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 @@ public class TestNamespace {
|
|||
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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<NamespaceDescriptor>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
admin.listTableNamesByNamespace("non_existing_namespace");
|
||||
return null;
|
||||
}
|
||||
}, NamespaceNotFoundException.class);
|
||||
|
||||
}
|
||||
|
||||
private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) {
|
||||
try {
|
||||
callable.call();
|
||||
} catch(Exception ex) {
|
||||
Assert.assertEquals(exceptionClass, ex.getClass());
|
||||
return;
|
||||
}
|
||||
fail("Should have thrown exception " + exceptionClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue