blob: d778fa9ce228664af3699f65a64705a909ca16d1 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase;
import static org.junit.Assert.assertEquals;
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;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.google.common.collect.Sets;
@Category({MiscTests.class, MediumTests.class})
public class TestNamespace {
private static final Log LOG = LogFactory.getLog(TestNamespace.class);
private static HMaster master;
protected final static int NUM_SLAVES_BASE = 4;
private static HBaseTestingUtility TEST_UTIL;
protected static Admin admin;
protected static HBaseCluster cluster;
private static ZKNamespaceManager zkNamespaceManager;
private String prefix = "TestNamespace";
@BeforeClass
public static void setUp() throws Exception {
TEST_UTIL = new HBaseTestingUtility();
TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE);
admin = TEST_UTIL.getHBaseAdmin();
cluster = TEST_UTIL.getHBaseCluster();
master = ((MiniHBaseCluster)cluster).getMaster();
zkNamespaceManager =
new ZKNamespaceManager(master.getZooKeeper());
zkNamespaceManager.start();
LOG.info("Done initializing cluster");
}
@AfterClass
public static void tearDown() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}
@Before
public void beforeMethod() throws IOException {
for (HTableDescriptor desc : admin.listTables(prefix+".*")) {
admin.disableTable(desc.getTableName());
admin.deleteTable(desc.getTableName());
}
for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) {
if (ns.getName().startsWith(prefix)) {
admin.deleteNamespace(ns.getName());
}
}
}
@Test
public void verifyReservedNS() throws IOException {
//verify existence of reserved namespaces
NamespaceDescriptor ns =
admin.getNamespaceDescriptor(NamespaceDescriptor.DEFAULT_NAMESPACE.getName());
assertNotNull(ns);
assertEquals(ns.getName(), NamespaceDescriptor.DEFAULT_NAMESPACE.getName());
assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR));
ns = admin.getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
assertNotNull(ns);
assertEquals(ns.getName(), NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR));
assertEquals(2, admin.listNamespaceDescriptors().length);
//verify existence of system tables
Set<TableName> systemTables = Sets.newHashSet(
TableName.META_TABLE_NAME,
TableName.NAMESPACE_TABLE_NAME);
HTableDescriptor[] descs =
admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
assertEquals(systemTables.size(), descs.length);
for (HTableDescriptor desc : descs) {
assertTrue(systemTables.contains(desc.getTableName()));
}
//verify system tables aren't listed
assertEquals(0, admin.listTables().length);
//Try creating default and system namespaces.
boolean exceptionCaught = false;
try {
admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE);
} catch (IOException exp) {
LOG.warn(exp);
exceptionCaught = true;
} finally {
assertTrue(exceptionCaught);
}
exceptionCaught = false;
try {
admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE);
} catch (IOException exp) {
LOG.warn(exp);
exceptionCaught = true;
} finally {
assertTrue(exceptionCaught);
}
}
@Test
public void testDeleteReservedNS() throws Exception {
boolean exceptionCaught = false;
try {
admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR);
} catch (IOException exp) {
LOG.warn(exp);
exceptionCaught = true;
} finally {
assertTrue(exceptionCaught);
}
try {
admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR);
} catch (IOException exp) {
LOG.warn(exp);
exceptionCaught = true;
} finally {
assertTrue(exceptionCaught);
}
}
@Test
public void createRemoveTest() throws Exception {
String testName = "createRemoveTest";
String nsName = prefix+"_"+testName;
LOG.info(testName);
//create namespace and verify
admin.createNamespace(NamespaceDescriptor.create(nsName).build());
assertEquals(3, admin.listNamespaceDescriptors().length);
TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() {
@Override
public boolean evaluate() throws Exception {
return zkNamespaceManager.list().size() == 3;
}
});
assertNotNull(zkNamespaceManager.get(nsName));
//remove namespace and verify
admin.deleteNamespace(nsName);
assertEquals(2, admin.listNamespaceDescriptors().length);
assertEquals(2, zkNamespaceManager.list().size());
assertNull(zkNamespaceManager.get(nsName));
}
@Test
public void createDoubleTest() throws IOException, InterruptedException {
String testName = "createDoubleTest";
String nsName = prefix+"_"+testName;
LOG.info(testName);
TableName tableName = TableName.valueOf("my_table");
TableName tableNameFoo = TableName.valueOf(nsName+":my_table");
//create namespace and verify
admin.createNamespace(NamespaceDescriptor.create(nsName).build());
TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName));
TEST_UTIL.createTable(tableNameFoo,Bytes.toBytes(nsName));
assertEquals(2, admin.listTables().length);
assertNotNull(admin
.getTableDescriptor(tableName));
assertNotNull(admin
.getTableDescriptor(tableNameFoo));
//remove namespace and verify
admin.disableTable(tableName);
admin.deleteTable(tableName);
assertEquals(1, admin.listTables().length);
}
@Test
public void createTableTest() throws IOException, InterruptedException {
String testName = "createTableTest";
String nsName = prefix+"_"+testName;
LOG.info(testName);
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(nsName+":my_table"));
HColumnDescriptor colDesc = new HColumnDescriptor("my_cf");
desc.addFamily(colDesc);
try {
admin.createTable(desc);
fail("Expected no namespace exists exception");
} catch (NamespaceNotFoundException ex) {
}
//create table and in new namespace
admin.createNamespace(NamespaceDescriptor.create(nsName).build());
admin.createTable(desc);
TEST_UTIL.waitTableAvailable(desc.getTableName().getName(), 10000);
FileSystem fs = FileSystem.get(TEST_UTIL.getConfiguration());
assertTrue(fs.exists(
new Path(master.getMasterFileSystem().getRootDir(),
new Path(HConstants.BASE_NAMESPACE_DIR,
new Path(nsName, desc.getTableName().getQualifierAsString())))));
assertEquals(1, admin.listTables().length);
//verify non-empty namespace can't be removed
try {
admin.deleteNamespace(nsName);
fail("Expected non-empty namespace constraint exception");
} catch (Exception ex) {
LOG.info("Caught expected exception: " + ex);
}
//sanity check try to write and read from table
Table table = TEST_UTIL.getConnection().getTable(desc.getTableName());
Put p = new Put(Bytes.toBytes("row1"));
p.addColumn(Bytes.toBytes("my_cf"), Bytes.toBytes("my_col"), Bytes.toBytes("value1"));
table.put(p);
//flush and read from disk to make sure directory changes are working
admin.flush(desc.getTableName());
Get g = new Get(Bytes.toBytes("row1"));
assertTrue(table.exists(g));
//normal case of removing namespace
TEST_UTIL.deleteTable(desc.getTableName());
admin.deleteNamespace(nsName);
}
@Test
public void createTableInDefaultNamespace() throws Exception {
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("default_table"));
HColumnDescriptor colDesc = new HColumnDescriptor("cf1");
desc.addFamily(colDesc);
admin.createTable(desc);
assertTrue(admin.listTables().length == 1);
admin.disableTable(desc.getTableName());
admin.deleteTable(desc.getTableName());
}
@Test
public void createTableInSystemNamespace() throws Exception {
TableName tableName = TableName.valueOf("hbase:createTableInSystemNamespace");
HTableDescriptor desc = new HTableDescriptor(tableName);
HColumnDescriptor colDesc = new HColumnDescriptor("cf1");
desc.addFamily(colDesc);
admin.createTable(desc);
assertEquals(0, admin.listTables().length);
assertTrue(admin.tableExists(tableName));
admin.disableTable(desc.getTableName());
admin.deleteTable(desc.getTableName());
}
@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_existant_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);
}
}