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 = new ZKNamespaceManager(master.getZooKeeper()); 080 zkNamespaceManager.start(); 081 LOG.info("Done initializing cluster"); 082 } 083 084 @AfterClass 085 public static void tearDown() throws Exception { 086 TEST_UTIL.shutdownMiniCluster(); 087 } 088 089 @Before 090 public void beforeMethod() throws IOException { 091 for (HTableDescriptor desc : admin.listTables(prefix + ".*")) { 092 admin.disableTable(desc.getTableName()); 093 admin.deleteTable(desc.getTableName()); 094 } 095 for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) { 096 if (ns.getName().startsWith(prefix)) { 097 admin.deleteNamespace(ns.getName()); 098 } 099 } 100 } 101 102 @Test 103 public void verifyReservedNS() throws IOException { 104 // verify existence of reserved namespaces 105 NamespaceDescriptor ns = 106 admin.getNamespaceDescriptor(NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 107 assertNotNull(ns); 108 assertEquals(ns.getName(), NamespaceDescriptor.DEFAULT_NAMESPACE.getName()); 109 assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR)); 110 111 ns = admin.getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 112 assertNotNull(ns); 113 assertEquals(ns.getName(), NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 114 assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR)); 115 116 assertEquals(2, admin.listNamespaces().length); 117 assertEquals(2, admin.listNamespaceDescriptors().length); 118 119 // verify existence of system tables 120 Set<TableName> systemTables = 121 Sets.newHashSet(TableName.META_TABLE_NAME, TableName.NAMESPACE_TABLE_NAME); 122 HTableDescriptor[] descs = 123 admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 124 assertEquals(systemTables.size(), descs.length); 125 for (HTableDescriptor desc : descs) { 126 assertTrue(systemTables.contains(desc.getTableName())); 127 } 128 // verify system tables aren't listed 129 assertEquals(0, admin.listTables().length); 130 131 // Try creating default and system namespaces. 132 boolean exceptionCaught = false; 133 try { 134 admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE); 135 } catch (IOException exp) { 136 LOG.warn(exp.toString(), exp); 137 exceptionCaught = true; 138 } finally { 139 assertTrue(exceptionCaught); 140 } 141 142 exceptionCaught = false; 143 try { 144 admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE); 145 } catch (IOException exp) { 146 LOG.warn(exp.toString(), exp); 147 exceptionCaught = true; 148 } finally { 149 assertTrue(exceptionCaught); 150 } 151 } 152 153 @Test 154 public void testDeleteReservedNS() throws Exception { 155 boolean exceptionCaught = false; 156 try { 157 admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR); 158 } catch (IOException exp) { 159 LOG.warn(exp.toString(), exp); 160 exceptionCaught = true; 161 } finally { 162 assertTrue(exceptionCaught); 163 } 164 165 try { 166 admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR); 167 } catch (IOException exp) { 168 LOG.warn(exp.toString(), exp); 169 exceptionCaught = true; 170 } finally { 171 assertTrue(exceptionCaught); 172 } 173 } 174 175 @Test 176 public void createRemoveTest() throws Exception { 177 String nsName = prefix + "_" + name.getMethodName(); 178 LOG.info(name.getMethodName()); 179 180 // create namespace and verify 181 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 182 assertEquals(3, admin.listNamespaces().length); 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.listNamespaces().length); 194 assertEquals(2, admin.listNamespaceDescriptors().length); 195 assertEquals(2, zkNamespaceManager.list().size()); 196 assertNull(zkNamespaceManager.get(nsName)); 197 } 198 199 @Test 200 public void createDoubleTest() throws IOException, InterruptedException { 201 String nsName = prefix + "_" + name.getMethodName(); 202 LOG.info(name.getMethodName()); 203 204 final TableName tableName = TableName.valueOf(name.getMethodName()); 205 final TableName tableNameFoo = TableName.valueOf(nsName + ":" + name.getMethodName()); 206 // create namespace and verify 207 admin.createNamespace(NamespaceDescriptor.create(nsName).build()); 208 TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName)); 209 TEST_UTIL.createTable(tableNameFoo, Bytes.toBytes(nsName)); 210 assertEquals(2, admin.listTables().length); 211 assertNotNull(admin.getTableDescriptor(tableName)); 212 assertNotNull(admin.getTableDescriptor(tableNameFoo)); 213 // remove namespace and verify 214 admin.disableTable(tableName); 215 admin.deleteTable(tableName); 216 assertEquals(1, admin.listTables().length); 217 } 218 219 @Test 220 public void createTableTest() throws IOException, InterruptedException { 221 String nsName = prefix + "_" + name.getMethodName(); 222 LOG.info(name.getMethodName()); 223 224 HTableDescriptor desc = 225 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(), new Path(HConstants.BASE_NAMESPACE_DIR, 240 new Path(nsName, desc.getTableName().getQualifierAsString()))))); 241 assertEquals(1, admin.listTables().length); 242 243 // verify non-empty namespace can't be removed 244 try { 245 admin.deleteNamespace(nsName); 246 fail("Expected non-empty namespace constraint exception"); 247 } catch (Exception ex) { 248 LOG.info("Caught expected exception: " + ex); 249 } 250 251 // sanity check try to write and read from table 252 Table table = TEST_UTIL.getConnection().getTable(desc.getTableName()); 253 Put p = new Put(Bytes.toBytes("row1")); 254 p.addColumn(Bytes.toBytes("my_cf"), Bytes.toBytes("my_col"), Bytes.toBytes("value1")); 255 table.put(p); 256 // flush and read from disk to make sure directory changes are working 257 admin.flush(desc.getTableName()); 258 Get g = new Get(Bytes.toBytes("row1")); 259 assertTrue(table.exists(g)); 260 261 // normal case of removing namespace 262 TEST_UTIL.deleteTable(desc.getTableName()); 263 admin.deleteNamespace(nsName); 264 } 265 266 @Test 267 public void createTableInDefaultNamespace() throws Exception { 268 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 269 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 270 desc.addFamily(colDesc); 271 admin.createTable(desc); 272 assertTrue(admin.listTables().length == 1); 273 admin.disableTable(desc.getTableName()); 274 admin.deleteTable(desc.getTableName()); 275 } 276 277 @Test 278 public void createTableInSystemNamespace() throws Exception { 279 final TableName tableName = TableName.valueOf("hbase:" + name.getMethodName()); 280 HTableDescriptor desc = new HTableDescriptor(tableName); 281 HColumnDescriptor colDesc = new HColumnDescriptor("cf1"); 282 desc.addFamily(colDesc); 283 admin.createTable(desc); 284 assertEquals(0, admin.listTables().length); 285 assertTrue(admin.tableExists(tableName)); 286 admin.disableTable(desc.getTableName()); 287 admin.deleteTable(desc.getTableName()); 288 } 289 290 @Test 291 public void testNamespaceOperations() throws IOException { 292 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 293 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()); 294 295 // create namespace that already exists 296 runWithExpectedException(new Callable<Void>() { 297 @Override 298 public Void call() throws Exception { 299 admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()); 300 return null; 301 } 302 }, NamespaceExistException.class); 303 304 // create a table in non-existing namespace 305 runWithExpectedException(new Callable<Void>() { 306 @Override 307 public Void call() throws Exception { 308 HTableDescriptor htd = 309 new HTableDescriptor(TableName.valueOf("non_existing_namespace", name.getMethodName())); 310 htd.addFamily(new HColumnDescriptor("family1")); 311 admin.createTable(htd); 312 return null; 313 } 314 }, NamespaceNotFoundException.class); 315 316 // get descriptor for existing namespace 317 admin.getNamespaceDescriptor(prefix + "ns1"); 318 319 // get descriptor for non-existing namespace 320 runWithExpectedException(new Callable<NamespaceDescriptor>() { 321 @Override 322 public NamespaceDescriptor call() throws Exception { 323 return admin.getNamespaceDescriptor("non_existing_namespace"); 324 } 325 }, NamespaceNotFoundException.class); 326 327 // delete descriptor for existing namespace 328 admin.deleteNamespace(prefix + "ns2"); 329 330 // delete descriptor for non-existing namespace 331 runWithExpectedException(new Callable<Void>() { 332 @Override 333 public Void call() throws Exception { 334 admin.deleteNamespace("non_existing_namespace"); 335 return null; 336 } 337 }, NamespaceNotFoundException.class); 338 339 // modify namespace descriptor for existing namespace 340 NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1"); 341 ns1.setConfiguration("foo", "bar"); 342 admin.modifyNamespace(ns1); 343 344 // modify namespace descriptor for non-existing namespace 345 runWithExpectedException(new Callable<Void>() { 346 @Override 347 public Void call() throws Exception { 348 admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()); 349 return null; 350 } 351 }, NamespaceNotFoundException.class); 352 353 // get table descriptors for existing namespace 354 HTableDescriptor htd = 355 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, 388 Class<E> exceptionClass) { 389 try { 390 callable.call(); 391 } catch (Exception ex) { 392 Assert.assertEquals(exceptionClass, ex.getClass()); 393 return; 394 } 395 fail("Should have thrown exception " + exceptionClass); 396 } 397}