View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertNull;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.io.IOException;
29  import java.util.Set;
30  import java.util.concurrent.Callable;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.fs.FileSystem;
35  import org.apache.hadoop.fs.Path;
36  import org.apache.hadoop.hbase.client.Admin;
37  import org.apache.hadoop.hbase.client.Get;
38  import org.apache.hadoop.hbase.client.HTable;
39  import org.apache.hadoop.hbase.client.Put;
40  import org.apache.hadoop.hbase.client.Table;
41  import org.apache.hadoop.hbase.master.HMaster;
42  import org.apache.hadoop.hbase.testclassification.MediumTests;
43  import org.apache.hadoop.hbase.util.Bytes;
44  import org.apache.hadoop.hbase.util.FSUtils;
45  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
46  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
47  import org.junit.AfterClass;
48  import org.junit.Assert;
49  import org.junit.Before;
50  import org.junit.BeforeClass;
51  import org.junit.Ignore;
52  import org.junit.Test;
53  import org.junit.experimental.categories.Category;
54  
55  import com.google.common.collect.Sets;
56  
57  @Category(MediumTests.class)
58  public class TestNamespace {
59    private static final Log LOG = LogFactory.getLog(TestNamespace.class);
60    private static HMaster master;
61    protected final static int NUM_SLAVES_BASE = 4;
62    private static HBaseTestingUtility TEST_UTIL;
63    protected static Admin admin;
64    protected static HBaseCluster cluster;
65    private static ZKNamespaceManager zkNamespaceManager;
66    private String prefix = "TestNamespace";
67  
68  
69    @BeforeClass
70    public static void setUp() throws Exception {
71      TEST_UTIL = new HBaseTestingUtility();
72      TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE);
73      admin = TEST_UTIL.getHBaseAdmin();
74      cluster = TEST_UTIL.getHBaseCluster();
75      master = ((MiniHBaseCluster)cluster).getMaster();
76      zkNamespaceManager =
77          new ZKNamespaceManager(master.getZooKeeper());
78      zkNamespaceManager.start();
79      LOG.info("Done initializing cluster");
80    }
81  
82    @AfterClass
83    public static void tearDown() throws Exception {
84      TEST_UTIL.shutdownMiniCluster();
85    }
86  
87    @Before
88    public void beforeMethod() throws IOException {
89      for (HTableDescriptor desc : admin.listTables(prefix+".*")) {
90        admin.disableTable(desc.getTableName());
91        admin.deleteTable(desc.getTableName());
92      }
93      for (NamespaceDescriptor ns : admin.listNamespaceDescriptors()) {
94        if (ns.getName().startsWith(prefix)) {
95          admin.deleteNamespace(ns.getName());
96        }
97      }
98    }
99  
100   @Test
101   public void verifyReservedNS() throws IOException {
102     //verify existence of reserved namespaces
103     NamespaceDescriptor ns =
104         admin.getNamespaceDescriptor(NamespaceDescriptor.DEFAULT_NAMESPACE.getName());
105     assertNotNull(ns);
106     assertEquals(ns.getName(), NamespaceDescriptor.DEFAULT_NAMESPACE.getName());
107     assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR));
108 
109     ns = admin.getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
110     assertNotNull(ns);
111     assertEquals(ns.getName(), NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
112     assertNotNull(zkNamespaceManager.get(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR));
113 
114     assertEquals(2, admin.listNamespaces().length);
115     assertEquals(2, admin.listNamespaceDescriptors().length);
116 
117     //verify existence of system tables
118     Set<TableName> systemTables = Sets.newHashSet(
119         TableName.META_TABLE_NAME,
120         TableName.NAMESPACE_TABLE_NAME);
121     HTableDescriptor[] descs =
122         admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
123     assertEquals(systemTables.size(), descs.length);
124     for (HTableDescriptor desc : descs) {
125       assertTrue(systemTables.contains(desc.getTableName()));
126     }
127     //verify system tables aren't listed
128     assertEquals(0, admin.listTables().length);
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);
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);
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);
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);
168       exceptionCaught = true;
169     } finally {
170       assertTrue(exceptionCaught);
171     }
172   }
173 
174   @Test
175   public void createRemoveTest() throws Exception {
176     String testName = "createRemoveTest";
177     String nsName = prefix+"_"+testName;
178     LOG.info(testName);
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 testName = "createDoubleTest";
202     String nsName = prefix+"_"+testName;
203     LOG.info(testName);
204 
205     TableName tableName = TableName.valueOf("my_table");
206     TableName tableNameFoo = TableName.valueOf(nsName+":my_table");
207     //create namespace and verify
208     admin.createNamespace(NamespaceDescriptor.create(nsName).build());
209     TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName));
210     TEST_UTIL.createTable(tableNameFoo,Bytes.toBytes(nsName));
211     assertEquals(2, admin.listTables().length);
212     assertNotNull(admin
213         .getTableDescriptor(tableName));
214     assertNotNull(admin
215         .getTableDescriptor(tableNameFoo));
216     //remove namespace and verify
217     admin.disableTable(tableName);
218     admin.deleteTable(tableName);
219     assertEquals(1, admin.listTables().length);
220   }
221 
222   @Test
223   public void createTableTest() throws IOException, InterruptedException {
224     String testName = "createTableTest";
225     String nsName = prefix+"_"+testName;
226     LOG.info(testName);
227 
228     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(nsName+":my_table"));
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 = new HTable(TEST_UTIL.getConfiguration(), desc.getTableName());
257     Put p = new Put(Bytes.toBytes("row1"));
258     p.add(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("default_table"));
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     TableName tableName = TableName.valueOf("hbase:createTableInSystemNamespace");
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(timeout = 60000)
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 = new HTableDescriptor(TableName.valueOf("non_existing_namespace", "table1"));
313         htd.addFamily(new HColumnDescriptor("family1"));
314         admin.createTable(htd);
315         return null;
316       }
317     }, NamespaceNotFoundException.class);
318 
319     // get descriptor for existing namespace
320     admin.getNamespaceDescriptor(prefix + "ns1");
321 
322     // get descriptor for non-existing namespace
323     runWithExpectedException(new Callable<NamespaceDescriptor>() {
324       @Override
325       public NamespaceDescriptor call() throws Exception {
326         return admin.getNamespaceDescriptor("non_existing_namespace");
327       }
328     }, NamespaceNotFoundException.class);
329 
330     // delete descriptor for existing namespace
331     admin.deleteNamespace(prefix + "ns2");
332 
333     // delete descriptor for non-existing namespace
334     runWithExpectedException(new Callable<Void>() {
335       @Override
336       public Void call() throws Exception {
337         admin.deleteNamespace("non_existing_namespace");
338         return null;
339       }
340     }, NamespaceNotFoundException.class);
341 
342     // modify namespace descriptor for existing namespace
343     NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1");
344     ns1.setConfiguration("foo", "bar");
345     admin.modifyNamespace(ns1);
346 
347     // modify namespace descriptor for non-existing namespace
348     runWithExpectedException(new Callable<Void>() {
349       @Override
350       public Void call() throws Exception {
351         admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build());
352         return null;
353       }
354     }, NamespaceNotFoundException.class);
355 
356     // get table descriptors for existing namespace
357     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(prefix + "ns1", "table1"));
358     htd.addFamily(new HColumnDescriptor("family1"));
359     admin.createTable(htd);
360     HTableDescriptor[] htds = admin.listTableDescriptorsByNamespace(prefix + "ns1");
361     assertNotNull("Should have not returned null", htds);
362     assertEquals("Should have returned non-empty array", 1, htds.length);
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("non_existing_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, Class<E> exceptionClass) {
390     try {
391       callable.call();
392     } catch(Exception ex) {
393       Assert.assertEquals(exceptionClass, ex.getClass());
394       return;
395     }
396     fail("Should have thrown exception " + exceptionClass);
397   }
398 
399   @Test
400   public void testValueOfNamespaceAndQualifier() {
401     TableName name0 = TableName.valueOf("table");
402     TableName name1 = TableName.valueOf("table", "table");
403     assertEquals(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR, name0.getNamespaceAsString());
404     assertEquals("table", name0.getQualifierAsString());
405     assertEquals("table", name0.getNameAsString());
406     assertEquals("table", name1.getNamespaceAsString());
407     assertEquals("table", name1.getQualifierAsString());
408     assertEquals("table:table", name1.getNameAsString());
409   }
410 
411 }