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