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.listNamespaceDescriptors().length);
115 
116     //verify existence of system tables
117     Set<TableName> systemTables = Sets.newHashSet(
118         TableName.META_TABLE_NAME,
119         TableName.NAMESPACE_TABLE_NAME);
120     HTableDescriptor[] descs =
121         admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE.getName());
122     assertEquals(systemTables.size(), descs.length);
123     for (HTableDescriptor desc : descs) {
124       assertTrue(systemTables.contains(desc.getTableName()));
125     }
126     //verify system tables aren't listed
127     assertEquals(0, admin.listTables().length);
128 
129     //Try creating default and system namespaces.
130     boolean exceptionCaught = false;
131     try {
132       admin.createNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE);
133     } catch (IOException exp) {
134       LOG.warn(exp);
135       exceptionCaught = true;
136     } finally {
137       assertTrue(exceptionCaught);
138     }
139 
140     exceptionCaught = false;
141     try {
142       admin.createNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE);
143     } catch (IOException exp) {
144       LOG.warn(exp);
145       exceptionCaught = true;
146     } finally {
147       assertTrue(exceptionCaught);
148     }
149   }
150 
151   @Test
152   public void testDeleteReservedNS() throws Exception {
153     boolean exceptionCaught = false;
154     try {
155       admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR);
156     } catch (IOException exp) {
157       LOG.warn(exp);
158       exceptionCaught = true;
159     } finally {
160       assertTrue(exceptionCaught);
161     }
162 
163     try {
164       admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR);
165     } catch (IOException exp) {
166       LOG.warn(exp);
167       exceptionCaught = true;
168     } finally {
169       assertTrue(exceptionCaught);
170     }
171   }
172 
173   @Test
174   public void createRemoveTest() throws Exception {
175     String testName = "createRemoveTest";
176     String nsName = prefix+"_"+testName;
177     LOG.info(testName);
178 
179     //create namespace and verify
180     admin.createNamespace(NamespaceDescriptor.create(nsName).build());
181     assertEquals(3, admin.listNamespaceDescriptors().length);
182     TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() {
183       @Override
184       public boolean evaluate() throws Exception {
185         return zkNamespaceManager.list().size() == 3;
186       }
187     });
188     assertNotNull(zkNamespaceManager.get(nsName));
189     //remove namespace and verify
190     admin.deleteNamespace(nsName);
191     assertEquals(2, admin.listNamespaceDescriptors().length);
192     assertEquals(2, zkNamespaceManager.list().size());
193     assertNull(zkNamespaceManager.get(nsName));
194   }
195 
196   @Test
197   public void createDoubleTest() throws IOException, InterruptedException {
198     String testName = "createDoubleTest";
199     String nsName = prefix+"_"+testName;
200     LOG.info(testName);
201 
202     TableName tableName = TableName.valueOf("my_table");
203     TableName tableNameFoo = TableName.valueOf(nsName+":my_table");
204     //create namespace and verify
205     admin.createNamespace(NamespaceDescriptor.create(nsName).build());
206     TEST_UTIL.createTable(tableName, Bytes.toBytes(nsName));
207     TEST_UTIL.createTable(tableNameFoo,Bytes.toBytes(nsName));
208     assertEquals(2, admin.listTables().length);
209     assertNotNull(admin
210         .getTableDescriptor(tableName));
211     assertNotNull(admin
212         .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 testName = "createTableTest";
222     String nsName = prefix+"_"+testName;
223     LOG.info(testName);
224 
225     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(nsName+":my_table"));
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 = new HTable(TEST_UTIL.getConfiguration(), desc.getTableName());
254     Put p = new Put(Bytes.toBytes("row1"));
255     p.add(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("default_table"));
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     TableName tableName = TableName.valueOf("hbase:createTableInSystemNamespace");
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(timeout = 60000)
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 = new HTableDescriptor(TableName.valueOf("non_existing_namespace", "table1"));
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 = new HTableDescriptor(TableName.valueOf(prefix + "ns1", "table1"));
355     htd.addFamily(new HColumnDescriptor("family1"));
356     admin.createTable(htd);
357     HTableDescriptor[] htds = admin.listTableDescriptorsByNamespace(prefix + "ns1");
358     assertNotNull("Should have not returned null", htds);
359     assertEquals("Should have returned non-empty array", 1, htds.length);
360 
361     // get table descriptors for non-existing namespace
362     runWithExpectedException(new Callable<Void>() {
363       @Override
364       public Void call() throws Exception {
365         admin.listTableDescriptorsByNamespace("non_existing_namespace");
366         return null;
367       }
368     }, NamespaceNotFoundException.class);
369 
370     // get table names for existing namespace
371     TableName[] tableNames = admin.listTableNamesByNamespace(prefix + "ns1");
372     assertNotNull("Should have not returned null", tableNames);
373     assertEquals("Should have returned non-empty array", 1, tableNames.length);
374 
375     // get table names for non-existing namespace
376     runWithExpectedException(new Callable<Void>() {
377       @Override
378       public Void call() throws Exception {
379         admin.listTableNamesByNamespace("non_existing_namespace");
380         return null;
381       }
382     }, NamespaceNotFoundException.class);
383 
384   }
385 
386   private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) {
387     try {
388       callable.call();
389     } catch(Exception ex) {
390       Assert.assertEquals(exceptionClass, ex.getClass());
391       return;
392     }
393     fail("Should have thrown exception " + exceptionClass);
394   }
395 
396 }