001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertNotNull; 022import static org.junit.Assert.assertNull; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.IOException; 027import java.util.Set; 028import java.util.concurrent.Callable; 029import org.apache.hadoop.fs.FileSystem; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.client.Admin; 032import org.apache.hadoop.hbase.client.Get; 033import org.apache.hadoop.hbase.client.Put; 034import org.apache.hadoop.hbase.client.Table; 035import org.apache.hadoop.hbase.master.HMaster; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.testclassification.MiscTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.junit.AfterClass; 040import org.junit.Assert; 041import org.junit.Before; 042import org.junit.BeforeClass; 043import org.junit.ClassRule; 044import org.junit.Rule; 045import org.junit.Test; 046import org.junit.experimental.categories.Category; 047import org.junit.rules.TestName; 048import org.slf4j.Logger; 049import org.slf4j.LoggerFactory; 050 051import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 052 053@Category({MiscTests.class, MediumTests.class}) 054public class TestNamespace { 055 056 @ClassRule 057 public static final HBaseClassTestRule CLASS_RULE = 058 HBaseClassTestRule.forClass(TestNamespace.class); 059 060 private static final Logger LOG = LoggerFactory.getLogger(TestNamespace.class); 061 private static HMaster master; 062 protected final static int NUM_SLAVES_BASE = 4; 063 private static HBaseTestingUtility TEST_UTIL; 064 protected static Admin admin; 065 protected static HBaseCluster cluster; 066 private static ZKNamespaceManager zkNamespaceManager; 067 private String prefix = "TestNamespace"; 068 069 @Rule 070 public TestName name = new TestName(); 071 072 @BeforeClass 073 public static void setUp() throws Exception { 074 TEST_UTIL = new HBaseTestingUtility(); 075 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE); 076 admin = TEST_UTIL.getAdmin(); 077 cluster = TEST_UTIL.getHBaseCluster(); 078 master = ((MiniHBaseCluster)cluster).getMaster(); 079 zkNamespaceManager = 080 new ZKNamespaceManager(master.getZooKeeper()); 081 zkNamespaceManager.start(); 082 LOG.info("Done initializing cluster"); 083 } 084 085 @AfterClass 086 public static void tearDown() throws Exception { 087 TEST_UTIL.shutdownMiniCluster(); 088 } 089 090 @Before 091 public void beforeMethod() throws IOException { 092 for (HTableDescriptor desc : admin.listTables(prefix+".*")) { 093 admin.disableTable(desc.getTableName()); 094 admin.deleteTable(desc.getTableName()); 095 } 096 for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) { 097 if (ns.getName().startsWith(prefix)) { 098 admin.deleteNamespace(ns.getName()); 099 } 100 } 101 } 102 103 @Test 104 public void verifyReservedNS() throws IOException { 105 //verify existence of reserved namespaces 106 NamespaceDescriptor ns = 107 admin.getNamespaceDescriptor(NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 108 assertNotNull(ns); 109 assertEquals(ns.getName(), NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 110 assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR)); 111 112 ns = admin.getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 113 assertNotNull(ns); 114 assertEquals(ns.getName(), NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 115 assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR)); 116 117 assertEquals(2, admin.listNamespaces().length); 118 assertEquals(2, admin.listNamespaceDescriptors().length); 119 120 //verify existence of system tables 121 Set<TableName> systemTables = Sets.newHashSet( 122 TableName.META_TABLE_NAME, 123 TableName.NAMESPACE_TABLE_NAME); 124 HTableDescriptor[] descs = 125 admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 126 assertEquals(systemTables.size(), descs.length); 127 for (HTableDescriptor desc : descs) { 128 assertTrue(systemTables.contains(desc.getTableName())); 129 } 130 //verify system tables aren't listed 131 assertEquals(0, admin.listTables().length); 132 133 //Try creating default and system namespaces. 134 boolean exceptionCaught = false; 135 try { 136 admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE); 137 } catch (IOException exp) { 138 LOG.warn(exp.toString(), exp); 139 exceptionCaught = true; 140 } finally { 141 assertTrue(exceptionCaught); 142 } 143 144 exceptionCaught = false; 145 try { 146 admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE); 147 } catch (IOException exp) { 148 LOG.warn(exp.toString(), exp); 149 exceptionCaught = true; 150 } finally { 151 assertTrue(exceptionCaught); 152 } 153 } 154 155 @Test 156 public void testDeleteReservedNS() throws Exception { 157 boolean exceptionCaught = false; 158 try { 159 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR); 160 } catch (IOException exp) { 161 LOG.warn(exp.toString(), exp); 162 exceptionCaught = true; 163 } finally { 164 assertTrue(exceptionCaught); 165 } 166 167 try { 168 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR); 169 } catch (IOException exp) { 170 LOG.warn(exp.toString(), exp); 171 exceptionCaught = true; 172 } finally { 173 assertTrue(exceptionCaught); 174 } 175 } 176 177 @Test 178 public void createRemoveTest() throws Exception { 179 String nsName = prefix + "_" + name.getMethodName(); 180 LOG.info(name.getMethodName()); 181 182 //create namespace and verify 183 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 184 assertEquals(3, admin.listNamespaces().length); 185 assertEquals(3, admin.listNamespaceDescriptors().length); 186 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { 187 @Override 188 public boolean evaluate() throws Exception { 189 return zkNamespaceManager.list().size() == 3; 190 } 191 }); 192 assertNotNull(zkNamespaceManager.get(nsName)); 193 //remove namespace and verify 194 admin.deleteNamespace(nsName); 195 assertEquals(2, admin.listNamespaces().length); 196 assertEquals(2, admin.listNamespaceDescriptors().length); 197 assertEquals(2, zkNamespaceManager.list().size()); 198 assertNull(zkNamespaceManager.get(nsName)); 199 } 200 201 @Test 202 public void createDoubleTest() throws IOException, InterruptedException { 203 String nsName = prefix + "_" + name.getMethodName(); 204 LOG.info(name.getMethodName()); 205 206 final TableName tableName = TableName.valueOf(name.getMethodName()); 207 final TableName tableNameFoo = TableName.valueOf(nsName + ":" + name.getMethodName()); 208 //create namespace and verify 209 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 210 TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName)); 211 TEST_UTIL.createTable(tableNameFoo,Bytes.toBytes(nsName)); 212 assertEquals(2, admin.listTables().length); 213 assertNotNull(admin 214 .getTableDescriptor(tableName)); 215 assertNotNull(admin 216 .getTableDescriptor(tableNameFoo)); 217 //remove namespace and verify 218 admin.disableTable(tableName); 219 admin.deleteTable(tableName); 220 assertEquals(1, admin.listTables().length); 221 } 222 223 @Test 224 public void createTableTest() throws IOException, InterruptedException { 225 String nsName = prefix + "_" + name.getMethodName(); 226 LOG.info(name.getMethodName()); 227 228 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(nsName + ":" + name.getMethodName())); 229 HColumnDescriptor colDesc = new HColumnDescriptor("my_cf"); 230 desc.addFamily(colDesc); 231 try { 232 admin.createTable(desc); 233 fail("Expected no namespace exists exception"); 234 } catch (NamespaceNotFoundException ex) { 235 } 236 //create table and in new namespace 237 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 238 admin.createTable(desc); 239 TEST_UTIL.waitTableAvailable(desc.getTableName().getName(), 10000); 240 FileSystem fs = FileSystem.get(TEST_UTIL.getConfiguration()); 241 assertTrue(fs.exists( 242 new Path(master.getMasterFileSystem().getRootDir(), 243 new Path(HConstants.BASE_NAMESPACE_DIR, 244 new Path(nsName, desc.getTableName().getQualifierAsString()))))); 245 assertEquals(1, admin.listTables().length); 246 247 //verify non-empty namespace can't be removed 248 try { 249 admin.deleteNamespace(nsName); 250 fail("Expected non-empty namespace constraint exception"); 251 } catch (Exception ex) { 252 LOG.info("Caught expected exception: " + ex); 253 } 254 255 //sanity check try to write and read from table 256 Table table = TEST_UTIL.getConnection().getTable(desc.getTableName()); 257 Put p = new Put(Bytes.toBytes("row1")); 258 p.addColumn(Bytes.toBytes("my_cf"), Bytes.toBytes("my_col"), Bytes.toBytes("value1")); 259 table.put(p); 260 //flush and read from disk to make sure directory changes are working 261 admin.flush(desc.getTableName()); 262 Get g = new Get(Bytes.toBytes("row1")); 263 assertTrue(table.exists(g)); 264 265 //normal case of removing namespace 266 TEST_UTIL.deleteTable(desc.getTableName()); 267 admin.deleteNamespace(nsName); 268 } 269 270 @Test 271 public void createTableInDefaultNamespace() throws Exception { 272 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 273 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 274 desc.addFamily(colDesc); 275 admin.createTable(desc); 276 assertTrue(admin.listTables().length == 1); 277 admin.disableTable(desc.getTableName()); 278 admin.deleteTable(desc.getTableName()); 279 } 280 281 @Test 282 public void createTableInSystemNamespace() throws Exception { 283 final TableName tableName = TableName.valueOf("hbase:" + name.getMethodName()); 284 HTableDescriptor desc = new HTableDescriptor(tableName); 285 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 286 desc.addFamily(colDesc); 287 admin.createTable(desc); 288 assertEquals(0, admin.listTables().length); 289 assertTrue(admin.tableExists(tableName)); 290 admin.disableTable(desc.getTableName()); 291 admin.deleteTable(desc.getTableName()); 292 } 293 294 @Test 295 public void testNamespaceOperations() throws IOException { 296 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 297 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()); 298 299 // create namespace that already exists 300 runWithExpectedException(new Callable<Void>() { 301 @Override 302 public Void call() throws Exception { 303 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 304 return null; 305 } 306 }, NamespaceExistException.class); 307 308 // create a table in non-existing namespace 309 runWithExpectedException(new Callable<Void>() { 310 @Override 311 public Void call() throws Exception { 312 HTableDescriptor htd = 313 new HTableDescriptor(TableName.valueOf("non_existing_namespace", name.getMethodName())); 314 htd.addFamily(new HColumnDescriptor("family1")); 315 admin.createTable(htd); 316 return null; 317 } 318 }, NamespaceNotFoundException.class); 319 320 // get descriptor for existing namespace 321 admin.getNamespaceDescriptor(prefix + "ns1"); 322 323 // get descriptor for non-existing namespace 324 runWithExpectedException(new Callable<NamespaceDescriptor>() { 325 @Override 326 public NamespaceDescriptor call() throws Exception { 327 return admin.getNamespaceDescriptor("non_existing_namespace"); 328 } 329 }, NamespaceNotFoundException.class); 330 331 // delete descriptor for existing namespace 332 admin.deleteNamespace(prefix + "ns2"); 333 334 // delete descriptor for non-existing namespace 335 runWithExpectedException(new Callable<Void>() { 336 @Override 337 public Void call() throws Exception { 338 admin.deleteNamespace("non_existing_namespace"); 339 return null; 340 } 341 }, NamespaceNotFoundException.class); 342 343 // modify namespace descriptor for existing namespace 344 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1"); 345 ns1.setConfiguration("foo", "bar"); 346 admin.modifyNamespace(ns1); 347 348 // modify namespace descriptor for non-existing namespace 349 runWithExpectedException(new Callable<Void>() { 350 @Override 351 public Void call() throws Exception { 352 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()); 353 return null; 354 } 355 }, NamespaceNotFoundException.class); 356 357 // get table descriptors for existing namespace 358 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(prefix + "ns1", name.getMethodName())); 359 htd.addFamily(new HColumnDescriptor("family1")); 360 admin.createTable(htd); 361 HTableDescriptor[] htds = admin.listTableDescriptorsByNamespace(prefix + "ns1"); 362 assertNotNull("Should have not returned null", htds); 363 assertEquals("Should have returned non-empty array", 1, htds.length); 364 365 // get table descriptors for non-existing namespace 366 runWithExpectedException(new Callable<Void>() { 367 @Override 368 public Void call() throws Exception { 369 admin.listTableDescriptorsByNamespace("non_existant_namespace"); 370 return null; 371 } 372 }, NamespaceNotFoundException.class); 373 374 // get table names for existing namespace 375 TableName[] tableNames = admin.listTableNamesByNamespace(prefix + "ns1"); 376 assertNotNull("Should have not returned null", tableNames); 377 assertEquals("Should have returned non-empty array", 1, tableNames.length); 378 379 // get table names for non-existing namespace 380 runWithExpectedException(new Callable<Void>() { 381 @Override 382 public Void call() throws Exception { 383 admin.listTableNamesByNamespace("non_existing_namespace"); 384 return null; 385 } 386 }, NamespaceNotFoundException.class); 387 388 } 389 390 private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) { 391 try { 392 callable.call(); 393 } catch(Exception ex) { 394 Assert.assertEquals(exceptionClass, ex.getClass()); 395 return; 396 } 397 fail("Should have thrown exception " + exceptionClass); 398 } 399}