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.listNamespaceDescriptors().length); 118 119 //verify existence of system tables 120 Set<TableName> systemTables = Sets.newHashSet( 121 TableName.META_TABLE_NAME, 122 TableName.NAMESPACE_TABLE_NAME); 123 HTableDescriptor[] descs = 124 admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 125 assertEquals(systemTables.size(), descs.length); 126 for (HTableDescriptor desc : descs) { 127 assertTrue(systemTables.contains(desc.getTableName())); 128 } 129 //verify system tables aren't listed 130 assertEquals(0, admin.listTables().length); 131 132 //Try creating default and system namespaces. 133 boolean exceptionCaught = false; 134 try { 135 admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE); 136 } catch (IOException exp) { 137 LOG.warn(exp.toString(), exp); 138 exceptionCaught = true; 139 } finally { 140 assertTrue(exceptionCaught); 141 } 142 143 exceptionCaught = false; 144 try { 145 admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE); 146 } catch (IOException exp) { 147 LOG.warn(exp.toString(), exp); 148 exceptionCaught = true; 149 } finally { 150 assertTrue(exceptionCaught); 151 } 152 } 153 154 @Test 155 public void testDeleteReservedNS() throws Exception { 156 boolean exceptionCaught = false; 157 try { 158 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR); 159 } catch (IOException exp) { 160 LOG.warn(exp.toString(), exp); 161 exceptionCaught = true; 162 } finally { 163 assertTrue(exceptionCaught); 164 } 165 166 try { 167 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR); 168 } catch (IOException exp) { 169 LOG.warn(exp.toString(), exp); 170 exceptionCaught = true; 171 } finally { 172 assertTrue(exceptionCaught); 173 } 174 } 175 176 @Test 177 public void createRemoveTest() throws Exception { 178 String nsName = prefix + "_" + name.getMethodName(); 179 LOG.info(name.getMethodName()); 180 181 //create namespace and verify 182 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 183 assertEquals(3, admin.listNamespaceDescriptors().length); 184 TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { 185 @Override 186 public boolean evaluate() throws Exception { 187 return zkNamespaceManager.list().size() == 3; 188 } 189 }); 190 assertNotNull(zkNamespaceManager.get(nsName)); 191 //remove namespace and verify 192 admin.deleteNamespace(nsName); 193 assertEquals(2, admin.listNamespaceDescriptors().length); 194 assertEquals(2, zkNamespaceManager.list().size()); 195 assertNull(zkNamespaceManager.get(nsName)); 196 } 197 198 @Test 199 public void createDoubleTest() throws IOException, InterruptedException { 200 String nsName = prefix + "_" + name.getMethodName(); 201 LOG.info(name.getMethodName()); 202 203 final TableName tableName = TableName.valueOf(name.getMethodName()); 204 final TableName tableNameFoo = TableName.valueOf(nsName + ":" + name.getMethodName()); 205 //create namespace and verify 206 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 207 TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName)); 208 TEST_UTIL.createTable(tableNameFoo,Bytes.toBytes(nsName)); 209 assertEquals(2, admin.listTables().length); 210 assertNotNull(admin 211 .getTableDescriptor(tableName)); 212 assertNotNull(admin 213 .getTableDescriptor(tableNameFoo)); 214 //remove namespace and verify 215 admin.disableTable(tableName); 216 admin.deleteTable(tableName); 217 assertEquals(1, admin.listTables().length); 218 } 219 220 @Test 221 public void createTableTest() throws IOException, InterruptedException { 222 String nsName = prefix + "_" + name.getMethodName(); 223 LOG.info(name.getMethodName()); 224 225 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(nsName + ":" + name.getMethodName())); 226 HColumnDescriptor colDesc = new HColumnDescriptor("my_cf"); 227 desc.addFamily(colDesc); 228 try { 229 admin.createTable(desc); 230 fail("Expected no namespace exists exception"); 231 } catch (NamespaceNotFoundException ex) { 232 } 233 //create table and in new namespace 234 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 235 admin.createTable(desc); 236 TEST_UTIL.waitTableAvailable(desc.getTableName().getName(), 10000); 237 FileSystem fs = FileSystem.get(TEST_UTIL.getConfiguration()); 238 assertTrue(fs.exists( 239 new Path(master.getMasterFileSystem().getRootDir(), 240 new Path(HConstants.BASE_NAMESPACE_DIR, 241 new Path(nsName, desc.getTableName().getQualifierAsString()))))); 242 assertEquals(1, admin.listTables().length); 243 244 //verify non-empty namespace can't be removed 245 try { 246 admin.deleteNamespace(nsName); 247 fail("Expected non-empty namespace constraint exception"); 248 } catch (Exception ex) { 249 LOG.info("Caught expected exception: " + ex); 250 } 251 252 //sanity check try to write and read from table 253 Table table = TEST_UTIL.getConnection().getTable(desc.getTableName()); 254 Put p = new Put(Bytes.toBytes("row1")); 255 p.addColumn(Bytes.toBytes("my_cf"), Bytes.toBytes("my_col"), Bytes.toBytes("value1")); 256 table.put(p); 257 //flush and read from disk to make sure directory changes are working 258 admin.flush(desc.getTableName()); 259 Get g = new Get(Bytes.toBytes("row1")); 260 assertTrue(table.exists(g)); 261 262 //normal case of removing namespace 263 TEST_UTIL.deleteTable(desc.getTableName()); 264 admin.deleteNamespace(nsName); 265 } 266 267 @Test 268 public void createTableInDefaultNamespace() throws Exception { 269 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 270 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 271 desc.addFamily(colDesc); 272 admin.createTable(desc); 273 assertTrue(admin.listTables().length == 1); 274 admin.disableTable(desc.getTableName()); 275 admin.deleteTable(desc.getTableName()); 276 } 277 278 @Test 279 public void createTableInSystemNamespace() throws Exception { 280 final TableName tableName = TableName.valueOf("hbase:" + name.getMethodName()); 281 HTableDescriptor desc = new HTableDescriptor(tableName); 282 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 283 desc.addFamily(colDesc); 284 admin.createTable(desc); 285 assertEquals(0, admin.listTables().length); 286 assertTrue(admin.tableExists(tableName)); 287 admin.disableTable(desc.getTableName()); 288 admin.deleteTable(desc.getTableName()); 289 } 290 291 @Test 292 public void testNamespaceOperations() throws IOException { 293 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 294 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()); 295 296 // create namespace that already exists 297 runWithExpectedException(new Callable<Void>() { 298 @Override 299 public Void call() throws Exception { 300 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 301 return null; 302 } 303 }, NamespaceExistException.class); 304 305 // create a table in non-existing namespace 306 runWithExpectedException(new Callable<Void>() { 307 @Override 308 public Void call() throws Exception { 309 HTableDescriptor htd = 310 new HTableDescriptor(TableName.valueOf("non_existing_namespace", name.getMethodName())); 311 htd.addFamily(new HColumnDescriptor("family1")); 312 admin.createTable(htd); 313 return null; 314 } 315 }, NamespaceNotFoundException.class); 316 317 // get descriptor for existing namespace 318 admin.getNamespaceDescriptor(prefix + "ns1"); 319 320 // get descriptor for non-existing namespace 321 runWithExpectedException(new Callable<NamespaceDescriptor>() { 322 @Override 323 public NamespaceDescriptor call() throws Exception { 324 return admin.getNamespaceDescriptor("non_existing_namespace"); 325 } 326 }, NamespaceNotFoundException.class); 327 328 // delete descriptor for existing namespace 329 admin.deleteNamespace(prefix + "ns2"); 330 331 // delete descriptor for non-existing namespace 332 runWithExpectedException(new Callable<Void>() { 333 @Override 334 public Void call() throws Exception { 335 admin.deleteNamespace("non_existing_namespace"); 336 return null; 337 } 338 }, NamespaceNotFoundException.class); 339 340 // modify namespace descriptor for existing namespace 341 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1"); 342 ns1.setConfiguration("foo", "bar"); 343 admin.modifyNamespace(ns1); 344 345 // modify namespace descriptor for non-existing namespace 346 runWithExpectedException(new Callable<Void>() { 347 @Override 348 public Void call() throws Exception { 349 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()); 350 return null; 351 } 352 }, NamespaceNotFoundException.class); 353 354 // get table descriptors for existing namespace 355 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(prefix + "ns1", name.getMethodName())); 356 htd.addFamily(new HColumnDescriptor("family1")); 357 admin.createTable(htd); 358 HTableDescriptor[] htds = admin.listTableDescriptorsByNamespace(prefix + "ns1"); 359 assertNotNull("Should have not returned null", htds); 360 assertEquals("Should have returned non-empty array", 1, htds.length); 361 362 // get table descriptors for non-existing namespace 363 runWithExpectedException(new Callable<Void>() { 364 @Override 365 public Void call() throws Exception { 366 admin.listTableDescriptorsByNamespace("non_existant_namespace"); 367 return null; 368 } 369 }, NamespaceNotFoundException.class); 370 371 // get table names for existing namespace 372 TableName[] tableNames = admin.listTableNamesByNamespace(prefix + "ns1"); 373 assertNotNull("Should have not returned null", tableNames); 374 assertEquals("Should have returned non-empty array", 1, tableNames.length); 375 376 // get table names for non-existing namespace 377 runWithExpectedException(new Callable<Void>() { 378 @Override 379 public Void call() throws Exception { 380 admin.listTableNamesByNamespace("non_existing_namespace"); 381 return null; 382 } 383 }, NamespaceNotFoundException.class); 384 385 } 386 387 private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) { 388 try { 389 callable.call(); 390 } catch(Exception ex) { 391 Assert.assertEquals(exceptionClass, ex.getClass()); 392 return; 393 } 394 fail("Should have thrown exception " + exceptionClass); 395 } 396}