1   /**
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.client;
21  
22  
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  import org.apache.zookeeper.KeeperException;
28  
29  import java.io.IOException;
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.concurrent.atomic.AtomicBoolean;
36  import java.util.concurrent.atomic.AtomicInteger;
37  import java.util.concurrent.atomic.AtomicReference;
38  
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  import org.apache.hadoop.conf.Configuration;
42  import org.apache.hadoop.hbase.DoNotRetryIOException;
43  import org.apache.hadoop.hbase.HBaseTestingUtility;
44  import org.apache.hadoop.hbase.HColumnDescriptor;
45  import org.apache.hadoop.hbase.HConstants;
46  import org.apache.hadoop.hbase.HRegionInfo;
47  import org.apache.hadoop.hbase.HRegionLocation;
48  import org.apache.hadoop.hbase.HServerAddress;
49  import org.apache.hadoop.hbase.HTableDescriptor;
50  import org.apache.hadoop.hbase.InvalidFamilyOperationException;
51  import org.apache.hadoop.hbase.LargeTests;
52  import org.apache.hadoop.hbase.ServerName;
53  import org.apache.hadoop.hbase.TableExistsException;
54  import org.apache.hadoop.hbase.TableNotDisabledException;
55  import org.apache.hadoop.hbase.TableNotEnabledException;
56  import org.apache.hadoop.hbase.TableNotFoundException;
57  import org.apache.hadoop.hbase.catalog.CatalogTracker;
58  import org.apache.hadoop.hbase.executor.EventHandler;
59  import org.apache.hadoop.hbase.executor.EventHandler.EventType;
60  import org.apache.hadoop.hbase.executor.ExecutorService;
61  import org.apache.hadoop.hbase.master.MasterServices;
62  import org.apache.hadoop.hbase.regionserver.HRegion;
63  import org.apache.hadoop.hbase.regionserver.HRegionServer;
64  import org.apache.hadoop.hbase.regionserver.wal.HLogUtilsForTests;
65  import org.apache.hadoop.hbase.util.Bytes;
66  import org.apache.hadoop.hbase.util.Pair;
67  import org.apache.hadoop.hbase.zookeeper.ZKTableReadOnly;
68  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
69  import org.junit.After;
70  import org.junit.AfterClass;
71  import org.junit.Assert;
72  import org.junit.Before;
73  import org.junit.BeforeClass;
74  import org.junit.Test;
75  import org.junit.experimental.categories.Category;
76  
77  
78  /**
79   * Class to test HBaseAdmin.
80   * Spins up the minicluster once at test start and then takes it down afterward.
81   * Add any testing of HBaseAdmin functionality here.
82   */
83  @Category(LargeTests.class)
84  public class TestAdmin {
85    final Log LOG = LogFactory.getLog(getClass());
86    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
87    private HBaseAdmin admin;
88  
89    @BeforeClass
90    public static void setUpBeforeClass() throws Exception {
91      TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
92      TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
93      TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
94      TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
95      TEST_UTIL.getConfiguration().setBoolean(
96          "hbase.master.enabletable.roundrobin", true);
97      TEST_UTIL.startMiniCluster(3);
98    }
99  
100   @AfterClass
101   public static void tearDownAfterClass() throws Exception {
102     TEST_UTIL.shutdownMiniCluster();
103   }
104 
105   @Before
106   public void setUp() throws Exception {
107     this.admin = TEST_UTIL.getHBaseAdmin();
108   }
109 
110   @After
111   public void tearDown() throws Exception {
112   }
113 
114   @Test (timeout=300000)
115   public void testFailedCatalogTrackerGetCleansUpProperly()
116   throws IOException {
117     // An HBaseAdmin that we can make fail when it goes to get catalogtracker.
118     final AtomicBoolean fail = new AtomicBoolean(false);
119     final AtomicReference<CatalogTracker> internalCt = new AtomicReference<CatalogTracker>();
120     HBaseAdmin doctoredAdmin = new HBaseAdmin(this.admin.getConfiguration()) {
121       @Override
122       protected CatalogTracker startCatalogTracker(CatalogTracker ct)
123       throws IOException, InterruptedException {
124         internalCt.set(ct);
125         super.startCatalogTracker(ct);
126         if (fail.get()) {
127           throw new IOException("Intentional test fail",
128             new KeeperException.ConnectionLossException());
129         }
130         return ct;
131       }
132     };
133     try {
134       CatalogTracker ct = doctoredAdmin.getCatalogTracker();
135       assertFalse(ct.isStopped());
136       doctoredAdmin.cleanupCatalogTracker(ct);
137       assertTrue(ct.isStopped());
138       // Now have mess with our doctored admin and make the start of catalog tracker 'fail'.
139       fail.set(true);
140       boolean expectedException = false;
141       try {
142         doctoredAdmin.getCatalogTracker();
143       } catch (IOException ioe) {
144         assertTrue(ioe.getCause() instanceof KeeperException.ConnectionLossException);
145         expectedException = true;
146       }
147       if (!expectedException) fail("Didn't get expected exception!");
148       // Assert that the internally made ct was properly shutdown.
149       assertTrue("Internal CatalogTracker not closed down", internalCt.get().isStopped());
150     } finally {
151       doctoredAdmin.close();
152     }
153   }
154 
155   @Test
156   public void testSplitFlushCompactUnknownTable() throws InterruptedException {
157     final String unknowntable = "fubar";
158     Exception exception = null;
159     try {
160       this.admin.compact(unknowntable);
161     } catch (IOException e) {
162       exception = e;
163     }
164     assertTrue(exception instanceof TableNotFoundException);
165 
166     exception = null;
167     try {
168       this.admin.flush(unknowntable);
169     } catch (IOException e) {
170       exception = e;
171     }
172     assertTrue(exception instanceof TableNotFoundException);
173 
174     exception = null;
175     try {
176       this.admin.split(unknowntable);
177     } catch (IOException e) {
178       exception = e;
179     }
180     assertTrue(exception instanceof TableNotFoundException);
181   }
182 
183   @Test
184   public void testDeleteEditUnknownColumnFamilyAndOrTable() throws IOException {
185     // Test we get exception if we try to
186     final String nonexistent = "nonexistent";
187     HColumnDescriptor nonexistentHcd = new HColumnDescriptor(nonexistent);
188     Exception exception = null;
189     try {
190       this.admin.addColumn(nonexistent, nonexistentHcd);
191     } catch (IOException e) {
192       exception = e;
193     }
194     assertTrue(exception instanceof TableNotFoundException);
195 
196     exception = null;
197     try {
198       this.admin.deleteTable(nonexistent);
199     } catch (IOException e) {
200       exception = e;
201     }
202     assertTrue(exception instanceof TableNotFoundException);
203 
204     exception = null;
205     try {
206       this.admin.deleteColumn(nonexistent, nonexistent);
207     } catch (IOException e) {
208       exception = e;
209     }
210     assertTrue(exception instanceof TableNotFoundException);
211 
212     exception = null;
213     try {
214       this.admin.disableTable(nonexistent);
215     } catch (IOException e) {
216       exception = e;
217     }
218     assertTrue(exception instanceof TableNotFoundException);
219 
220     exception = null;
221     try {
222       this.admin.enableTable(nonexistent);
223     } catch (IOException e) {
224       exception = e;
225     }
226     assertTrue(exception instanceof TableNotFoundException);
227 
228     exception = null;
229     try {
230       this.admin.modifyColumn(nonexistent, nonexistentHcd);
231     } catch (IOException e) {
232       exception = e;
233     }
234     assertTrue(exception instanceof TableNotFoundException);
235 
236     exception = null;
237     try {
238       HTableDescriptor htd = new HTableDescriptor(nonexistent);
239       this.admin.modifyTable(htd.getName(), htd);
240     } catch (IOException e) {
241       exception = e;
242     }
243     assertTrue(exception instanceof TableNotFoundException);
244 
245     // Now make it so at least the table exists and then do tests against a
246     // nonexistent column family -- see if we get right exceptions.
247     final String tableName = "t";
248     HTableDescriptor htd = new HTableDescriptor(tableName);
249     htd.addFamily(new HColumnDescriptor("cf"));
250     this.admin.createTable(htd);
251     try {
252       exception = null;
253       try {
254         this.admin.deleteColumn(htd.getName(), nonexistentHcd.getName());
255       } catch (IOException e) {
256         exception = e;
257       }
258       assertTrue(exception instanceof InvalidFamilyOperationException);
259 
260       exception = null;
261       try {
262         this.admin.modifyColumn(htd.getName(), nonexistentHcd);
263       } catch (IOException e) {
264         exception = e;
265       }
266       assertTrue(exception instanceof InvalidFamilyOperationException);
267     } finally {
268       this.admin.disableTable(tableName);
269       this.admin.deleteTable(tableName);
270     }
271   }
272 
273   @Test
274   public void testDisableAndEnableTable() throws IOException {
275     final byte [] row = Bytes.toBytes("row");
276     final byte [] qualifier = Bytes.toBytes("qualifier");
277     final byte [] value = Bytes.toBytes("value");
278     final byte [] table = Bytes.toBytes("testDisableAndEnableTable");
279     HTable ht = TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
280     Put put = new Put(row);
281     put.add(HConstants.CATALOG_FAMILY, qualifier, value);
282     ht.put(put);
283     Get get = new Get(row);
284     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
285     ht.get(get);
286 
287     this.admin.disableTable(table);
288     assertTrue("Table must be disabled.", TEST_UTIL.getHBaseCluster()
289         .getMaster().getAssignmentManager().getZKTable().isDisabledTable(
290             Bytes.toString(table)));
291 
292     // Test that table is disabled
293     get = new Get(row);
294     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
295     boolean ok = false;
296     try {
297       ht.get(get);
298     } catch (DoNotRetryIOException e) {
299       ok = true;
300     }
301     assertTrue(ok);
302     this.admin.enableTable(table);
303     assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
304         .getMaster().getAssignmentManager().getZKTable().isEnabledTable(
305             Bytes.toString(table)));
306 
307     // Test that table is enabled
308     try {
309       ht.get(get);
310     } catch (RetriesExhaustedException e) {
311       ok = false;
312     }
313     assertTrue(ok);
314     ht.close();
315   }
316 
317   @Test
318   public void testIsEnabledOnUnknownTable() throws Exception {
319     try {
320       admin.isTableEnabled(Bytes.toBytes("unkownTable"));
321       fail("Test should fail if isTableEnabled called on unknown table.");
322     } catch (IOException e) {
323     }
324   }
325 
326   @Test
327   public void testDisableAndEnableTables() throws IOException {
328     final byte [] row = Bytes.toBytes("row");
329     final byte [] qualifier = Bytes.toBytes("qualifier");
330     final byte [] value = Bytes.toBytes("value");
331     final byte [] table1 = Bytes.toBytes("testDisableAndEnableTable1");
332     final byte [] table2 = Bytes.toBytes("testDisableAndEnableTable2");
333     HTable ht1 = TEST_UTIL.createTable(table1, HConstants.CATALOG_FAMILY);
334     HTable ht2 = TEST_UTIL.createTable(table2, HConstants.CATALOG_FAMILY);
335     Put put = new Put(row);
336     put.add(HConstants.CATALOG_FAMILY, qualifier, value);
337     ht1.put(put);
338     ht2.put(put);
339     Get get = new Get(row);
340     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
341     ht1.get(get);
342     ht2.get(get);
343 
344     this.admin.disableTables("testDisableAndEnableTable.*");
345 
346     // Test that tables are disabled
347     get = new Get(row);
348     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
349     boolean ok = false;
350     try {
351       ht1.get(get);
352       ht2.get(get);
353     } catch (DoNotRetryIOException e) {
354       ok = true;
355     }
356 
357     assertTrue(ok);
358     this.admin.enableTables("testDisableAndEnableTable.*");
359 
360     // Test that tables are enabled
361     try {
362       ht1.get(get);
363     } catch (IOException e) {
364       ok = false;
365     }
366     try {
367       ht2.get(get);
368     } catch (IOException e) {
369       ok = false;
370     }
371     assertTrue(ok);
372 
373     ht1.close();
374     ht2.close();
375   }
376 
377   @Test
378   public void testCreateTable() throws IOException {
379     HTableDescriptor [] tables = admin.listTables();
380     int numTables = tables.length;
381     TEST_UTIL.createTable(Bytes.toBytes("testCreateTable"),
382       HConstants.CATALOG_FAMILY).close();
383     tables = this.admin.listTables();
384     assertEquals(numTables + 1, tables.length);
385     assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
386         .getMaster().getAssignmentManager().getZKTable().isEnabledTable(
387             "testCreateTable"));
388   }
389 
390   @Test
391   public void testGetTableDescriptor() throws IOException {
392     HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
393     HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
394     HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
395     HTableDescriptor htd = new HTableDescriptor("myTestTable");
396     htd.addFamily(fam1);
397     htd.addFamily(fam2);
398     htd.addFamily(fam3);
399     this.admin.createTable(htd);
400     HTable table = new HTable(TEST_UTIL.getConfiguration(), "myTestTable");
401     HTableDescriptor confirmedHtd = table.getTableDescriptor();
402     assertEquals(htd.compareTo(confirmedHtd), 0);
403     table.close();
404   }
405 
406   @Test
407   public void testHColumnValidName() {
408        boolean exceptionThrown = false;
409        try {
410        HColumnDescriptor fam1 = new HColumnDescriptor("\\test\\abc");
411        } catch(IllegalArgumentException iae) {
412            exceptionThrown = true;
413            assertTrue(exceptionThrown);
414        }
415    }
416   /**
417    * Verify schema modification takes.
418    * @throws IOException
419    * @throws InterruptedException
420    */
421   @Test
422   public void testOnlineChangeTableSchema() throws IOException, InterruptedException {
423     final byte [] tableName = Bytes.toBytes("changeTableSchemaOnline");
424     HTableDescriptor [] tables = admin.listTables();
425     int numTables = tables.length;
426     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
427     tables = this.admin.listTables();
428     assertEquals(numTables + 1, tables.length);
429 
430     // FIRST, do htabledescriptor changes.
431     HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
432     // Make a copy and assert copy is good.
433     HTableDescriptor copy = new HTableDescriptor(htd);
434     assertTrue(htd.equals(copy));
435     // Now amend the copy. Introduce differences.
436     long newFlushSize = htd.getMemStoreFlushSize() / 2;
437     if (newFlushSize <=0) {
438       newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
439     }
440     copy.setMemStoreFlushSize(newFlushSize);
441     final String key = "anyoldkey";
442     assertTrue(htd.getValue(key) == null);
443     copy.setValue(key, key);
444     boolean expectedException = false;
445     try {
446       modifyTable(tableName, copy);
447     } catch (TableNotDisabledException re) {
448       expectedException = true;
449     }
450     assertFalse(expectedException);
451     HTableDescriptor modifiedHtd = this.admin.getTableDescriptor(tableName);
452     assertFalse(htd.equals(modifiedHtd));
453     assertTrue(copy.equals(modifiedHtd));
454     assertEquals(newFlushSize, modifiedHtd.getMemStoreFlushSize());
455     assertEquals(key, modifiedHtd.getValue(key));
456 
457     // Now work on column family changes.
458     htd = this.admin.getTableDescriptor(tableName);
459     int countOfFamilies = modifiedHtd.getFamilies().size();
460     assertTrue(countOfFamilies > 0);
461     HColumnDescriptor hcd = modifiedHtd.getFamilies().iterator().next();
462     int maxversions = hcd.getMaxVersions();
463     final int newMaxVersions = maxversions + 1;
464     hcd.setMaxVersions(newMaxVersions);
465     final byte [] hcdName = hcd.getName();
466     expectedException = false;
467     try {
468       this.admin.modifyColumn(tableName, hcd);
469     } catch (TableNotDisabledException re) {
470       expectedException = true;
471     }
472     assertFalse(expectedException);
473     modifiedHtd = this.admin.getTableDescriptor(tableName);
474     HColumnDescriptor modifiedHcd = modifiedHtd.getFamily(hcdName);
475     assertEquals(newMaxVersions, modifiedHcd.getMaxVersions());
476 
477     // Try adding a column
478     assertFalse(this.admin.isTableDisabled(tableName));
479     final String xtracolName = "xtracol";
480     htd = this.admin.getTableDescriptor(tableName);
481     HColumnDescriptor xtracol = new HColumnDescriptor(xtracolName);
482     xtracol.setValue(xtracolName, xtracolName);
483     expectedException = false;
484     try {
485       this.admin.addColumn(tableName, xtracol);
486     } catch (TableNotDisabledException re) {
487       expectedException = true;
488     }
489     // Add column should work even if the table is enabled
490     assertFalse(expectedException);
491     modifiedHtd = this.admin.getTableDescriptor(tableName);
492     hcd = modifiedHtd.getFamily(xtracol.getName());
493     assertTrue(hcd != null);
494     assertTrue(hcd.getValue(xtracolName).equals(xtracolName));
495 
496     // Delete the just-added column.
497     this.admin.deleteColumn(tableName, xtracol.getName());
498     modifiedHtd = this.admin.getTableDescriptor(tableName);
499     hcd = modifiedHtd.getFamily(xtracol.getName());
500     assertTrue(hcd == null);
501 
502     // Delete the table
503     this.admin.disableTable(tableName);
504     this.admin.deleteTable(tableName);
505     this.admin.listTables();
506     assertFalse(this.admin.tableExists(tableName));
507   }
508 
509   @Test
510   public void testShouldFailOnlineSchemaUpdateIfOnlineSchemaIsNotEnabled()
511       throws Exception {
512     final byte[] tableName = Bytes.toBytes("changeTableSchemaOnlineFailure");
513     TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
514         "hbase.online.schema.update.enable", false);
515     HTableDescriptor[] tables = admin.listTables();
516     int numTables = tables.length;
517     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
518     tables = this.admin.listTables();
519     assertEquals(numTables + 1, tables.length);
520 
521     // FIRST, do htabledescriptor changes.
522     HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
523     // Make a copy and assert copy is good.
524     HTableDescriptor copy = new HTableDescriptor(htd);
525     assertTrue(htd.equals(copy));
526     // Now amend the copy. Introduce differences.
527     long newFlushSize = htd.getMemStoreFlushSize() / 2;
528     if (newFlushSize <=0) {
529       newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
530     }
531     copy.setMemStoreFlushSize(newFlushSize);
532     final String key = "anyoldkey";
533     assertTrue(htd.getValue(key) == null);
534     copy.setValue(key, key);
535     boolean expectedException = false;
536     try {
537       modifyTable(tableName, copy);
538     } catch (TableNotDisabledException re) {
539       expectedException = true;
540     }
541     assertTrue("Online schema update should not happen.", expectedException);
542     TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
543         "hbase.online.schema.update.enable", true);
544   }
545 
546   /**
547    * Modify table is async so wait on completion of the table operation in master.
548    * @param tableName
549    * @param htd
550    * @throws IOException
551    */
552   private void modifyTable(final byte [] tableName, final HTableDescriptor htd)
553   throws IOException {
554     MasterServices services = TEST_UTIL.getMiniHBaseCluster().getMaster();
555     ExecutorService executor = services.getExecutorService();
556     AtomicBoolean done = new AtomicBoolean(false);
557     executor.registerListener(EventType.C_M_MODIFY_TABLE, new DoneListener(done));
558     this.admin.modifyTable(tableName, htd);
559     while (!done.get()) {
560       synchronized (done) {
561         try {
562           done.wait(100);
563         } catch (InterruptedException e) {
564           e.printStackTrace();
565         }
566       }
567     }
568     executor.unregisterListener(EventType.C_M_MODIFY_TABLE);
569   }
570 
571   /**
572    * Listens for when an event is done in Master.
573    */
574   static class DoneListener implements EventHandler.EventHandlerListener {
575     private final AtomicBoolean done;
576 
577     DoneListener(final AtomicBoolean done) {
578       super();
579       this.done = done;
580     }
581 
582     @Override
583     public void afterProcess(EventHandler event) {
584       this.done.set(true);
585       synchronized (this.done) {
586         // Wake anyone waiting on this value to change.
587         this.done.notifyAll();
588       }
589     }
590 
591     @Override
592     public void beforeProcess(EventHandler event) {
593       // continue
594     }
595   }
596 
597   protected void verifyRoundRobinDistribution(HTable ht, int expectedRegions) throws IOException {
598     int numRS = ht.getConnection().getCurrentNrHRS();
599     Map<HRegionInfo,HServerAddress> regions = ht.getRegionsInfo();
600     Map<HServerAddress, List<HRegionInfo>> server2Regions = new HashMap<HServerAddress, List<HRegionInfo>>();
601     for (Map.Entry<HRegionInfo,HServerAddress> entry : regions.entrySet()) {
602       HServerAddress server = entry.getValue();
603       List<HRegionInfo> regs = server2Regions.get(server);
604       if (regs == null) {
605         regs = new ArrayList<HRegionInfo>();
606         server2Regions.put(server, regs);
607       }
608       regs.add(entry.getKey());
609     }
610     float average = (float) expectedRegions/numRS;
611     int min = (int)Math.floor(average);
612     int max = (int)Math.ceil(average);
613     for (List<HRegionInfo> regionList : server2Regions.values()) {
614       assertTrue(regionList.size() == min || regionList.size() == max);
615     }
616   }
617 
618   @Test
619   public void testCreateTableNumberOfRegions() throws IOException, InterruptedException {
620     byte[] tableName = Bytes.toBytes("testCreateTableNumberOfRegions");
621     HTableDescriptor desc = new HTableDescriptor(tableName);
622     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
623     admin.createTable(desc);
624     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
625     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
626     assertEquals("Table should have only 1 region", 1, regions.size());
627     ht.close();
628 
629     byte[] TABLE_2 = Bytes.add(tableName, Bytes.toBytes("_2"));
630     desc = new HTableDescriptor(TABLE_2);
631     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
632     admin.createTable(desc, new byte[][] { new byte[] { 42 } });
633     HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
634     regions = ht2.getRegionLocations();
635     assertEquals("Table should have only 2 region", 2, regions.size());
636     ht2.close();
637 
638     byte[] TABLE_3 = Bytes.add(tableName, Bytes.toBytes("_3"));
639     desc = new HTableDescriptor(TABLE_3);
640     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
641     admin.createTable(desc, "a".getBytes(), "z".getBytes(), 3);
642     HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
643     regions = ht3.getRegionLocations();
644     assertEquals("Table should have only 3 region", 3, regions.size());
645     ht3.close();
646 
647     byte[] TABLE_4 = Bytes.add(tableName, Bytes.toBytes("_4"));
648     desc = new HTableDescriptor(TABLE_4);
649     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
650     try {
651       admin.createTable(desc, "a".getBytes(), "z".getBytes(), 2);
652       fail("Should not be able to create a table with only 2 regions using this API.");
653     } catch (IllegalArgumentException eae) {
654       // Expected
655     }
656 
657     byte[] TABLE_5 = Bytes.add(tableName, Bytes.toBytes("_5"));
658     desc = new HTableDescriptor(TABLE_5);
659     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
660     admin.createTable(desc, new byte[] { 1 }, new byte[] { 127 }, 16);
661     HTable ht5 = new HTable(TEST_UTIL.getConfiguration(), TABLE_5);
662     regions = ht5.getRegionLocations();
663     assertEquals("Table should have 16 region", 16, regions.size());
664     ht5.close();
665   }
666 
667   @Test
668   public void testCreateTableWithRegions() throws IOException, InterruptedException {
669 
670     byte[] tableName = Bytes.toBytes("testCreateTableWithRegions");
671 
672     byte [][] splitKeys = {
673         new byte [] { 1, 1, 1 },
674         new byte [] { 2, 2, 2 },
675         new byte [] { 3, 3, 3 },
676         new byte [] { 4, 4, 4 },
677         new byte [] { 5, 5, 5 },
678         new byte [] { 6, 6, 6 },
679         new byte [] { 7, 7, 7 },
680         new byte [] { 8, 8, 8 },
681         new byte [] { 9, 9, 9 },
682     };
683     int expectedRegions = splitKeys.length + 1;
684 
685     HTableDescriptor desc = new HTableDescriptor(tableName);
686     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
687     admin.createTable(desc, splitKeys);
688 
689     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
690     Map<HRegionInfo,HServerAddress> regions = ht.getRegionsInfo();
691     assertEquals("Tried to create " + expectedRegions + " regions " +
692         "but only found " + regions.size(),
693         expectedRegions, regions.size());
694     System.err.println("Found " + regions.size() + " regions");
695 
696     Iterator<HRegionInfo> hris = regions.keySet().iterator();
697     HRegionInfo hri = hris.next();
698     assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
699     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
700     hri = hris.next();
701     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
702     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
703     hri = hris.next();
704     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
705     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
706     hri = hris.next();
707     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
708     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
709     hri = hris.next();
710     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
711     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
712     hri = hris.next();
713     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
714     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
715     hri = hris.next();
716     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
717     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
718     hri = hris.next();
719     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
720     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
721     hri = hris.next();
722     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
723     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
724     hri = hris.next();
725     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
726     assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
727 
728     verifyRoundRobinDistribution(ht, expectedRegions);
729     ht.close();
730 
731     // Now test using start/end with a number of regions
732 
733     // Use 80 bit numbers to make sure we aren't limited
734     byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
735     byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
736 
737     // Splitting into 10 regions, we expect (null,1) ... (9, null)
738     // with (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) in the middle
739 
740     expectedRegions = 10;
741 
742     byte [] TABLE_2 = Bytes.add(tableName, Bytes.toBytes("_2"));
743 
744     desc = new HTableDescriptor(TABLE_2);
745     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
746     admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
747     admin.createTable(desc, startKey, endKey, expectedRegions);
748 
749     HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
750     regions = ht2.getRegionsInfo();
751     assertEquals("Tried to create " + expectedRegions + " regions " +
752         "but only found " + regions.size(),
753         expectedRegions, regions.size());
754     System.err.println("Found " + regions.size() + " regions");
755 
756     hris = regions.keySet().iterator();
757     hri = hris.next();
758     assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
759     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
760     hri = hris.next();
761     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
762     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
763     hri = hris.next();
764     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
765     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
766     hri = hris.next();
767     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
768     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
769     hri = hris.next();
770     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
771     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
772     hri = hris.next();
773     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
774     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
775     hri = hris.next();
776     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
777     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
778     hri = hris.next();
779     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
780     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
781     hri = hris.next();
782     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
783     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
784     hri = hris.next();
785     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
786     assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
787 
788     verifyRoundRobinDistribution(ht2, expectedRegions);
789     ht2.close();
790 
791     // Try once more with something that divides into something infinite
792 
793     startKey = new byte [] { 0, 0, 0, 0, 0, 0 };
794     endKey = new byte [] { 1, 0, 0, 0, 0, 0 };
795 
796     expectedRegions = 5;
797 
798     byte [] TABLE_3 = Bytes.add(tableName, Bytes.toBytes("_3"));
799 
800     desc = new HTableDescriptor(TABLE_3);
801     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
802     admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
803     admin.createTable(desc, startKey, endKey, expectedRegions);
804 
805 
806     HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
807     regions = ht3.getRegionsInfo();
808     assertEquals("Tried to create " + expectedRegions + " regions " +
809         "but only found " + regions.size(),
810         expectedRegions, regions.size());
811     System.err.println("Found " + regions.size() + " regions");
812 
813     verifyRoundRobinDistribution(ht3, expectedRegions);
814     ht3.close();
815 
816 
817     // Try an invalid case where there are duplicate split keys
818     splitKeys = new byte [][] {
819         new byte [] { 1, 1, 1 },
820         new byte [] { 2, 2, 2 },
821         new byte [] { 3, 3, 3 },
822         new byte [] { 2, 2, 2 }
823     };
824 
825     byte [] TABLE_4 = Bytes.add(tableName, Bytes.toBytes("_4"));
826     desc = new HTableDescriptor(TABLE_4);
827     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
828     HBaseAdmin ladmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
829     try {
830       ladmin.createTable(desc, splitKeys);
831       assertTrue("Should not be able to create this table because of " +
832           "duplicate split keys", false);
833     } catch(IllegalArgumentException iae) {
834       // Expected
835     }
836     ladmin.close();
837   }
838 
839 
840   @Test
841   public void testCreateTableWithOnlyEmptyStartRow() throws IOException {
842     byte[] tableName = Bytes.toBytes("testCreateTableWithOnlyEmptyStartRow");
843     byte[][] splitKeys = new byte[1][];
844     splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
845     HTableDescriptor desc = new HTableDescriptor(tableName);
846     desc.addFamily(new HColumnDescriptor("col"));
847     try {
848       admin.createTable(desc, splitKeys);
849       fail("Test case should fail as empty split key is passed.");
850     } catch (IllegalArgumentException e) {
851     }
852   }
853 
854   @Test
855   public void testCreateTableWithEmptyRowInTheSplitKeys() throws IOException {
856     byte[] tableName = Bytes
857         .toBytes("testCreateTableWithEmptyRowInTheSplitKeys");
858     byte[][] splitKeys = new byte[3][];
859     splitKeys[0] = "region1".getBytes();
860     splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY;
861     splitKeys[2] = "region2".getBytes();
862     HTableDescriptor desc = new HTableDescriptor(tableName);
863     desc.addFamily(new HColumnDescriptor("col"));
864     try {
865       admin.createTable(desc, splitKeys);
866       fail("Test case should fail as empty split key is passed.");
867     } catch (IllegalArgumentException e) {
868     }
869   }
870 
871   @Test
872   public void testTableExist() throws IOException {
873     final byte [] table = Bytes.toBytes("testTableExist");
874     boolean exist = false;
875     exist = this.admin.tableExists(table);
876     assertEquals(false, exist);
877     TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
878     exist = this.admin.tableExists(table);
879     assertEquals(true, exist);
880   }
881 
882   /**
883    * Tests forcing split from client and having scanners successfully ride over split.
884    * @throws Exception
885    * @throws IOException
886    */
887   @Test
888   public void testForceSplit() throws Exception {
889     byte[][] familyNames = new byte[][] { Bytes.toBytes("cf") };
890     int[] rowCounts = new int[] { 6000 };
891     int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
892     int blockSize = 256;
893     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
894 
895     byte[] splitKey = Bytes.toBytes(3500);
896     splitTest(splitKey, familyNames, rowCounts, numVersions, blockSize);
897   }
898 
899   /**
900    * Test retain assignment on enableTable.
901    *
902    * @throws IOException
903    */
904   @Test
905   public void testEnableTableRetainAssignment() throws IOException, InterruptedException {
906     byte[] tableName = Bytes.toBytes("testEnableTableAssignment");
907     byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 },
908         new byte[] { 3, 3, 3 }, new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 },
909         new byte[] { 6, 6, 6 }, new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 },
910         new byte[] { 9, 9, 9 } };
911     int expectedRegions = splitKeys.length + 1;
912     HTableDescriptor desc = new HTableDescriptor(tableName);
913     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
914     admin.createTable(desc, splitKeys);
915     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
916     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
917     assertEquals("Tried to create " + expectedRegions + " regions "
918         + "but only found " + regions.size(), expectedRegions, regions.size());
919     // Disable table.
920     admin.disableTable(tableName);
921     // Enable table, use retain assignment to assign regions.
922     admin.enableTable(tableName);
923     Map<HRegionInfo, ServerName> regions2 = ht.getRegionLocations();
924 
925     // Check the assignment.
926     assertEquals(regions.size(), regions2.size());
927     for (Map.Entry<HRegionInfo, ServerName> entry : regions.entrySet()) {
928       ServerName sn1 = regions2.get(entry.getKey());
929       ServerName sn2 = entry.getValue();
930       assertEquals(sn1, sn2);
931     }
932   }
933 
934   /**
935    * Multi-family scenario. Tests forcing split from client and
936    * having scanners successfully ride over split.
937    * @throws Exception
938    * @throws IOException
939    */
940   @Test
941   public void testForceSplitMultiFamily() throws Exception {
942     int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
943 
944     // use small HFile block size so that we can have lots of blocks in HFile
945     // Otherwise, if there is only one block,
946     // HFileBlockIndex.midKey()'s value == startKey
947     int blockSize = 256;
948     byte[][] familyNames = new byte[][] { Bytes.toBytes("cf1"),
949       Bytes.toBytes("cf2") };
950 
951     // one of the column families isn't splittable
952     int[] rowCounts = new int[] { 6000, 1 };
953     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
954 
955     rowCounts = new int[] { 1, 6000 };
956     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
957 
958     // one column family has much smaller data than the other
959     // the split key should be based on the largest column family
960     rowCounts = new int[] { 6000, 300 };
961     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
962 
963     rowCounts = new int[] { 300, 6000 };
964     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
965 
966   }
967 
968   void splitTest(byte[] splitPoint, byte[][] familyNames, int[] rowCounts,
969     int numVersions, int blockSize) throws Exception {
970     byte [] tableName = Bytes.toBytes("testForceSplit");
971     assertFalse(admin.tableExists(tableName));
972     final HTable table = TEST_UTIL.createTable(tableName, familyNames,
973       numVersions, blockSize);
974     int rowCount = 0;
975     byte[] q = new byte[0];
976 
977     // insert rows into column families. The number of rows that have values
978     // in a specific column family is decided by rowCounts[familyIndex]
979     for (int index = 0; index < familyNames.length; index++) {
980       ArrayList<Put> puts = new ArrayList<Put>(rowCounts[index]);
981       for (int i = 0; i < rowCounts[index]; i++) {
982         byte[] k = Bytes.toBytes(i);
983         Put put = new Put(k);
984         put.add(familyNames[index], q, k);
985         puts.add(put);
986       }
987       table.put(puts);
988 
989       if ( rowCount < rowCounts[index] ) {
990         rowCount = rowCounts[index];
991       }
992     }
993 
994     // get the initial layout (should just be one region)
995     Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
996     System.out.println("Initial regions (" + m.size() + "): " + m);
997     assertTrue(m.size() == 1);
998 
999     // Verify row count
1000     Scan scan = new Scan();
1001     ResultScanner scanner = table.getScanner(scan);
1002     int rows = 0;
1003     for(@SuppressWarnings("unused") Result result : scanner) {
1004       rows++;
1005     }
1006     scanner.close();
1007     assertEquals(rowCount, rows);
1008 
1009     // Have an outstanding scan going on to make sure we can scan over splits.
1010     scan = new Scan();
1011     scanner = table.getScanner(scan);
1012     // Scan first row so we are into first region before split happens.
1013     scanner.next();
1014 
1015     final AtomicInteger count = new AtomicInteger(0);
1016     Thread t = new Thread("CheckForSplit") {
1017       public void run() {
1018         for (int i = 0; i < 20; i++) {
1019           try {
1020             sleep(1000);
1021           } catch (InterruptedException e) {
1022             continue;
1023           }
1024           // check again    table = new HTable(conf, tableName);
1025           Map<HRegionInfo, HServerAddress> regions = null;
1026           try {
1027             regions = table.getRegionsInfo();
1028           } catch (IOException e) {
1029             e.printStackTrace();
1030           }
1031           if (regions == null) continue;
1032           count.set(regions.size());
1033           if (count.get() >= 2) break;
1034           LOG.debug("Cycle waiting on split");
1035         }
1036       }
1037     };
1038     t.start();
1039     // Split the table
1040     this.admin.split(tableName, splitPoint);
1041     t.join();
1042 
1043     // Verify row count
1044     rows = 1; // We counted one row above.
1045     for (@SuppressWarnings("unused") Result result : scanner) {
1046       rows++;
1047       if (rows > rowCount) {
1048         scanner.close();
1049         assertTrue("Scanned more than expected (" + rowCount + ")", false);
1050       }
1051     }
1052     scanner.close();
1053     assertEquals(rowCount, rows);
1054 
1055     Map<HRegionInfo, HServerAddress> regions = null;
1056     try {
1057       regions = table.getRegionsInfo();
1058     } catch (IOException e) {
1059       e.printStackTrace();
1060     }
1061     assertEquals(2, regions.size());
1062     HRegionInfo[] r = regions.keySet().toArray(new HRegionInfo[0]);
1063     if (splitPoint != null) {
1064       // make sure the split point matches our explicit configuration
1065       assertEquals(Bytes.toString(splitPoint),
1066           Bytes.toString(r[0].getEndKey()));
1067       assertEquals(Bytes.toString(splitPoint),
1068           Bytes.toString(r[1].getStartKey()));
1069       LOG.debug("Properly split on " + Bytes.toString(splitPoint));
1070     } else {
1071       if (familyNames.length > 1) {
1072         int splitKey = Bytes.toInt(r[0].getEndKey());
1073         // check if splitKey is based on the largest column family
1074         // in terms of it store size
1075         int deltaForLargestFamily = Math.abs(rowCount/2 - splitKey);
1076         for (int index = 0; index < familyNames.length; index++) {
1077           int delta = Math.abs(rowCounts[index]/2 - splitKey);
1078           assertTrue(delta >= deltaForLargestFamily);
1079         }
1080       }
1081     }
1082     TEST_UTIL.deleteTable(tableName);
1083     table.close();
1084   }
1085 
1086   /**
1087    * HADOOP-2156
1088    * @throws IOException
1089    */
1090   @Test (expected=IllegalArgumentException.class)
1091   public void testEmptyHHTableDescriptor() throws IOException {
1092     this.admin.createTable(new HTableDescriptor());
1093   }
1094 
1095   @Test (expected=IllegalArgumentException.class)
1096   public void testInvalidHColumnDescriptor() throws IOException {
1097      new HColumnDescriptor("/cfamily/name");
1098   }
1099 
1100   @Test(timeout=300000)
1101   public void testEnableDisableAddColumnDeleteColumn() throws Exception {
1102     ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(TEST_UTIL);
1103     byte [] tableName = Bytes.toBytes("testMasterAdmin");
1104     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
1105     while (!ZKTableReadOnly.isEnabledTable(zkw, "testMasterAdmin")) {
1106       Thread.sleep(10);
1107     }
1108     this.admin.disableTable(tableName);
1109     try {
1110       new HTable(TEST_UTIL.getConfiguration(), tableName);
1111     } catch (DoNotRetryIOException e) {
1112       //expected
1113     }
1114 
1115     this.admin.addColumn(tableName, new HColumnDescriptor("col2"));
1116     this.admin.enableTable(tableName);
1117     try {
1118       this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
1119     } catch (TableNotDisabledException e) {
1120       LOG.info(e);
1121     }
1122     this.admin.disableTable(tableName);
1123     this.admin.deleteTable(tableName);
1124   }
1125 
1126   @Test
1127   public void testCreateBadTables() throws IOException {
1128     String msg = null;
1129     try {
1130       this.admin.createTable(HTableDescriptor.ROOT_TABLEDESC);
1131     } catch (IllegalArgumentException e) {
1132       msg = e.toString();
1133     }
1134     assertTrue("Unexcepted exception message " + msg, msg != null &&
1135       msg.startsWith(IllegalArgumentException.class.getName()) &&
1136       msg.contains(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()));
1137     msg = null;
1138     try {
1139       this.admin.createTable(HTableDescriptor.META_TABLEDESC);
1140     } catch(IllegalArgumentException e) {
1141       msg = e.toString();
1142     }
1143     assertTrue("Unexcepted exception message " + msg, msg != null &&
1144       msg.startsWith(IllegalArgumentException.class.getName()) &&
1145       msg.contains(HTableDescriptor.META_TABLEDESC.getNameAsString()));
1146 
1147     // Now try and do concurrent creation with a bunch of threads.
1148     final HTableDescriptor threadDesc =
1149       new HTableDescriptor("threaded_testCreateBadTables");
1150     threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
1151     int count = 10;
1152     Thread [] threads = new Thread [count];
1153     final AtomicInteger successes = new AtomicInteger(0);
1154     final AtomicInteger failures = new AtomicInteger(0);
1155     final HBaseAdmin localAdmin = this.admin;
1156     for (int i = 0; i < count; i++) {
1157       threads[i] = new Thread(Integer.toString(i)) {
1158         @Override
1159         public void run() {
1160           try {
1161             localAdmin.createTable(threadDesc);
1162             successes.incrementAndGet();
1163           } catch (TableExistsException e) {
1164             failures.incrementAndGet();
1165           } catch (IOException e) {
1166             throw new RuntimeException("Failed threaded create" + getName(), e);
1167           }
1168         }
1169       };
1170     }
1171     for (int i = 0; i < count; i++) {
1172       threads[i].start();
1173     }
1174     for (int i = 0; i < count; i++) {
1175       while(threads[i].isAlive()) {
1176         try {
1177           Thread.sleep(100);
1178         } catch (InterruptedException e) {
1179           // continue
1180         }
1181       }
1182     }
1183     // All threads are now dead.  Count up how many tables were created and
1184     // how many failed w/ appropriate exception.
1185     assertEquals(1, successes.get());
1186     assertEquals(count - 1, failures.get());
1187   }
1188 
1189   /**
1190    * Test for hadoop-1581 'HBASE: Unopenable tablename bug'.
1191    * @throws Exception
1192    */
1193   @Test
1194   public void testTableNameClash() throws Exception {
1195     String name = "testTableNameClash";
1196     admin.createTable(new HTableDescriptor(name + "SOMEUPPERCASE"));
1197     admin.createTable(new HTableDescriptor(name));
1198     // Before fix, below would fail throwing a NoServerForRegionException.
1199     new HTable(TEST_UTIL.getConfiguration(), name).close();
1200   }
1201 
1202   /***
1203    * HMaster.createTable used to be kind of synchronous call
1204    * Thus creating of table with lots of regions can cause RPC timeout
1205    * After the fix to make createTable truly async, RPC timeout shouldn't be an
1206    * issue anymore
1207    * @throws Exception
1208    */
1209   @Test
1210   public void testCreateTableRPCTimeOut() throws Exception {
1211     String name = "testCreateTableRPCTimeOut";
1212     int oldTimeout = TEST_UTIL.getConfiguration().
1213       getInt(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT);
1214     TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500);
1215     try {
1216       int expectedRegions = 100;
1217       // Use 80 bit numbers to make sure we aren't limited
1218       byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
1219       byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
1220       HBaseAdmin hbaseadmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
1221       hbaseadmin.createTable(new HTableDescriptor(name), startKey, endKey,
1222         expectedRegions);
1223       hbaseadmin.close();
1224     } finally {
1225       TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, oldTimeout);
1226     }
1227   }
1228 
1229   /**
1230    * Test read only tables
1231    * @throws Exception
1232    */
1233   @Test
1234   public void testReadOnlyTable() throws Exception {
1235     byte [] name = Bytes.toBytes("testReadOnlyTable");
1236     HTable table = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
1237     byte[] value = Bytes.toBytes("somedata");
1238     // This used to use an empty row... That must have been a bug
1239     Put put = new Put(value);
1240     put.add(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY, value);
1241     table.put(put);
1242     table.close();
1243   }
1244 
1245   /**
1246    * Test that user table names can contain '-' and '.' so long as they do not
1247    * start with same. HBASE-771
1248    * @throws IOException
1249    */
1250   @Test
1251   public void testTableNames() throws IOException {
1252     byte[][] illegalNames = new byte[][] {
1253         Bytes.toBytes("-bad"),
1254         Bytes.toBytes(".bad"),
1255         HConstants.ROOT_TABLE_NAME,
1256         HConstants.META_TABLE_NAME
1257     };
1258     for (int i = 0; i < illegalNames.length; i++) {
1259       try {
1260         new HTableDescriptor(illegalNames[i]);
1261         throw new IOException("Did not detect '" +
1262           Bytes.toString(illegalNames[i]) + "' as an illegal user table name");
1263       } catch (IllegalArgumentException e) {
1264         // expected
1265       }
1266     }
1267     byte[] legalName = Bytes.toBytes("g-oo.d");
1268     try {
1269       new HTableDescriptor(legalName);
1270     } catch (IllegalArgumentException e) {
1271       throw new IOException("Legal user table name: '" +
1272         Bytes.toString(legalName) + "' caused IllegalArgumentException: " +
1273         e.getMessage());
1274     }
1275   }
1276 
1277   /**
1278    * For HADOOP-2579
1279    * @throws IOException
1280    */
1281   @Test (expected=TableExistsException.class)
1282   public void testTableExistsExceptionWithATable() throws IOException {
1283     final byte [] name = Bytes.toBytes("testTableExistsExceptionWithATable");
1284     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close();
1285     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
1286   }
1287 
1288   /**
1289    * Can't disable a table if the table isn't in enabled state
1290    * @throws IOException
1291    */
1292   @Test (expected=TableNotEnabledException.class)
1293   public void testTableNotEnabledExceptionWithATable() throws IOException {
1294     final byte [] name = Bytes.toBytes(
1295       "testTableNotEnabledExceptionWithATable");
1296     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close();
1297     this.admin.disableTable(name);
1298     this.admin.disableTable(name);
1299   }
1300 
1301   /**
1302    * Can't enable a table if the table isn't in disabled state
1303    * @throws IOException
1304    */
1305   @Test (expected=TableNotDisabledException.class)
1306   public void testTableNotDisabledExceptionWithATable() throws IOException {
1307     final byte [] name = Bytes.toBytes(
1308       "testTableNotDisabledExceptionWithATable");
1309     HTable t = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
1310     try {
1311     this.admin.enableTable(name);
1312     }finally {
1313        t.close();
1314     }
1315   }
1316 
1317   /**
1318    * For HADOOP-2579
1319    * @throws IOException
1320    */
1321   @Test (expected=TableNotFoundException.class)
1322   public void testTableNotFoundExceptionWithoutAnyTables() throws IOException {
1323     new HTable(TEST_UTIL.getConfiguration(),
1324         "testTableNotFoundExceptionWithoutAnyTables");
1325   }
1326   @Test
1327   public void testShouldCloseTheRegionBasedOnTheEncodedRegionName()
1328       throws Exception {
1329     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion");
1330     createTableWithDefaultConf(TABLENAME);
1331 
1332     HRegionInfo info = null;
1333     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1334     List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1335     for (HRegionInfo regionInfo : onlineRegions) {
1336       if (!regionInfo.isMetaTable()) {
1337         info = regionInfo;
1338         admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), rs
1339             .getServerName().getServerName());
1340       }
1341     }
1342     boolean isInList = rs.getOnlineRegions().contains(info);
1343     long timeout = System.currentTimeMillis() + 10000;
1344     while ((System.currentTimeMillis() < timeout) && (isInList)) {
1345       Thread.sleep(100);
1346       isInList = rs.getOnlineRegions().contains(info);
1347     }
1348     assertFalse("The region should not be present in online regions list.",
1349         isInList);
1350   }
1351 
1352   @Test
1353   public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception {
1354     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion1");
1355     createTableWithDefaultConf(TABLENAME);
1356 
1357     HRegionInfo info = null;
1358     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1359     List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1360     for (HRegionInfo regionInfo : onlineRegions) {
1361       if (!regionInfo.isMetaTable()) {
1362         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion1")) {
1363           info = regionInfo;
1364           admin.closeRegionWithEncodedRegionName("sample", rs.getServerName()
1365               .getServerName());
1366         }
1367       }
1368     }
1369     onlineRegions = rs.getOnlineRegions();
1370     assertTrue("The region should be present in online regions list.",
1371         onlineRegions.contains(info));
1372   }
1373 
1374   @Test
1375   public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception {
1376     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion2");
1377     createTableWithDefaultConf(TABLENAME);
1378 
1379     HRegionInfo info = null;
1380     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1381     List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1382     for (HRegionInfo regionInfo : onlineRegions) {
1383       if (!regionInfo.isMetaTable()) {
1384 
1385         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion2")) {
1386           info = regionInfo;
1387           admin.closeRegion(regionInfo.getRegionNameAsString(), rs
1388               .getServerName().getServerName());
1389         }
1390       }
1391     }
1392 
1393     boolean isInList = rs.getOnlineRegions().contains(info);
1394     long timeout = System.currentTimeMillis() + 10000;
1395     while ((System.currentTimeMillis() < timeout) && (isInList)) {
1396       Thread.sleep(100);
1397       isInList = rs.getOnlineRegions().contains(info);
1398     }
1399 
1400     assertFalse("The region should not be present in online regions list.",
1401       isInList);
1402   }
1403 
1404   @Test
1405   public void testCloseRegionWhenServerNameIsNull() throws Exception {
1406     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion3");
1407     createTableWithDefaultConf(TABLENAME);
1408 
1409     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1410 
1411     try {
1412       List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1413       for (HRegionInfo regionInfo : onlineRegions) {
1414         if (!regionInfo.isMetaTable()) {
1415           if (regionInfo.getRegionNameAsString()
1416               .contains("TestHBACloseRegion3")) {
1417             admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
1418                 null);
1419           }
1420         }
1421       }
1422       fail("The test should throw exception if the servername passed is null.");
1423     } catch (IllegalArgumentException e) {
1424     }
1425   }
1426 
1427 
1428   @Test
1429   public void testCloseRegionWhenServerNameIsEmpty() throws Exception {
1430     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegionWhenServerNameIsEmpty");
1431     createTableWithDefaultConf(TABLENAME);
1432 
1433     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1434 
1435     try {
1436       List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1437       for (HRegionInfo regionInfo : onlineRegions) {
1438         if (!regionInfo.isMetaTable()) {
1439           if (regionInfo.getRegionNameAsString()
1440               .contains("TestHBACloseRegionWhenServerNameIsEmpty")) {
1441             admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
1442                 " ");
1443           }
1444         }
1445       }
1446       fail("The test should throw exception if the servername passed is empty.");
1447     } catch (IllegalArgumentException e) {
1448     }
1449   }
1450 
1451   @Test
1452   public void testCloseRegionWhenEncodedRegionNameIsNotGiven() throws Exception {
1453     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion4");
1454     createTableWithDefaultConf(TABLENAME);
1455 
1456     HRegionInfo info = null;
1457     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
1458 
1459     List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
1460     for (HRegionInfo regionInfo : onlineRegions) {
1461       if (!regionInfo.isMetaTable()) {
1462         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion4")) {
1463           info = regionInfo;
1464           admin.closeRegionWithEncodedRegionName(regionInfo
1465               .getRegionNameAsString(), rs.getServerName().getServerName());
1466         }
1467       }
1468     }
1469     onlineRegions = rs.getOnlineRegions();
1470     assertTrue("The region should be present in online regions list.",
1471         onlineRegions.contains(info));
1472   }
1473 
1474   private HBaseAdmin createTable(byte[] TABLENAME) throws IOException {
1475 
1476     Configuration config = TEST_UTIL.getConfiguration();
1477     HBaseAdmin admin = new HBaseAdmin(config);
1478 
1479     HTableDescriptor htd = new HTableDescriptor(TABLENAME);
1480     HColumnDescriptor hcd = new HColumnDescriptor("value");
1481 
1482     htd.addFamily(hcd);
1483     admin.createTable(htd, null);
1484     return admin;
1485   }
1486 
1487   private void createTableWithDefaultConf(byte[] TABLENAME) throws IOException {
1488     HTableDescriptor htd = new HTableDescriptor(TABLENAME);
1489     HColumnDescriptor hcd = new HColumnDescriptor("value");
1490     htd.addFamily(hcd);
1491 
1492     admin.createTable(htd, null);
1493   }
1494 
1495   /**
1496    * For HBASE-2556
1497    * @throws IOException
1498    */
1499   @Test
1500   public void testGetTableRegions() throws IOException {
1501 
1502     byte[] tableName = Bytes.toBytes("testGetTableRegions");
1503 
1504     int expectedRegions = 10;
1505 
1506     // Use 80 bit numbers to make sure we aren't limited
1507     byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
1508     byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
1509 
1510 
1511     HTableDescriptor desc = new HTableDescriptor(tableName);
1512     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
1513     admin.createTable(desc, startKey, endKey, expectedRegions);
1514 
1515     List<HRegionInfo> RegionInfos = admin.getTableRegions(tableName);
1516 
1517     assertEquals("Tried to create " + expectedRegions + " regions " +
1518         "but only found " + RegionInfos.size(),
1519         expectedRegions, RegionInfos.size());
1520 
1521  }
1522 
1523   @Test
1524   public void testHLogRollWriting() throws Exception {
1525     setUpforLogRolling();
1526     String className = this.getClass().getName();
1527     StringBuilder v = new StringBuilder(className);
1528     while (v.length() < 1000) {
1529       v.append(className);
1530     }
1531     byte[] value = Bytes.toBytes(v.toString());
1532     HRegionServer regionServer = startAndWriteData("TestLogRolling", value);
1533     LOG.info("after writing there are "
1534         + HLogUtilsForTests.getNumLogFiles(regionServer.getWAL()) + " log files");
1535 
1536     // flush all regions
1537 
1538     List<HRegion> regions = new ArrayList<HRegion>(regionServer
1539         .getOnlineRegionsLocalContext());
1540     for (HRegion r : regions) {
1541       r.flushcache();
1542     }
1543     admin.rollHLogWriter(regionServer.getServerName().getServerName());
1544     int count = HLogUtilsForTests.getNumLogFiles(regionServer.getWAL());
1545     LOG.info("after flushing all regions and rolling logs there are " +
1546         count + " log files");
1547     assertTrue(("actual count: " + count), count <= 3);
1548   }
1549 
1550   private void setUpforLogRolling() {
1551     // Force a region split after every 768KB
1552     TEST_UTIL.getConfiguration().setLong(HConstants.HREGION_MAX_FILESIZE,
1553         768L * 1024L);
1554 
1555     // We roll the log after every 32 writes
1556     TEST_UTIL.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32);
1557 
1558     TEST_UTIL.getConfiguration().setInt(
1559         "hbase.regionserver.logroll.errors.tolerated", 2);
1560     TEST_UTIL.getConfiguration().setInt("ipc.ping.interval", 10 * 1000);
1561     TEST_UTIL.getConfiguration().setInt("ipc.socket.timeout", 10 * 1000);
1562     TEST_UTIL.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000);
1563 
1564     // For less frequently updated regions flush after every 2 flushes
1565     TEST_UTIL.getConfiguration().setInt(
1566         "hbase.hregion.memstore.optionalflushcount", 2);
1567 
1568     // We flush the cache after every 8192 bytes
1569     TEST_UTIL.getConfiguration().setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
1570         8192);
1571 
1572     // Increase the amount of time between client retries
1573     TEST_UTIL.getConfiguration().setLong("hbase.client.pause", 10 * 1000);
1574 
1575     // Reduce thread wake frequency so that other threads can get
1576     // a chance to run.
1577     TEST_UTIL.getConfiguration().setInt(HConstants.THREAD_WAKE_FREQUENCY,
1578         2 * 1000);
1579 
1580     /**** configuration for testLogRollOnDatanodeDeath ****/
1581     // make sure log.hflush() calls syncFs() to open a pipeline
1582     TEST_UTIL.getConfiguration().setBoolean("dfs.support.append", true);
1583     // lower the namenode & datanode heartbeat so the namenode
1584     // quickly detects datanode failures
1585     TEST_UTIL.getConfiguration().setInt("heartbeat.recheck.interval", 5000);
1586     TEST_UTIL.getConfiguration().setInt("dfs.heartbeat.interval", 1);
1587     // the namenode might still try to choose the recently-dead datanode
1588     // for a pipeline, so try to a new pipeline multiple times
1589     TEST_UTIL.getConfiguration().setInt("dfs.client.block.write.retries", 30);
1590     TEST_UTIL.getConfiguration().setInt(
1591         "hbase.regionserver.hlog.tolerable.lowreplication", 2);
1592     TEST_UTIL.getConfiguration().setInt(
1593         "hbase.regionserver.hlog.lowreplication.rolllimit", 3);
1594   }
1595 
1596   private HRegionServer startAndWriteData(String tableName, byte[] value)
1597       throws IOException {
1598     // When the META table can be opened, the region servers are running
1599     new HTable(
1600       TEST_UTIL.getConfiguration(), HConstants.META_TABLE_NAME).close();
1601     HRegionServer regionServer = TEST_UTIL.getHBaseCluster()
1602         .getRegionServerThreads().get(0).getRegionServer();
1603 
1604     // Create the test table and open it
1605     HTableDescriptor desc = new HTableDescriptor(tableName);
1606     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
1607     admin.createTable(desc);
1608     HTable table = new HTable(TEST_UTIL.getConfiguration(), tableName);
1609 
1610     regionServer = TEST_UTIL.getRSForFirstRegionInTable(Bytes
1611         .toBytes(tableName));
1612     for (int i = 1; i <= 256; i++) { // 256 writes should cause 8 log rolls
1613       Put put = new Put(Bytes.toBytes("row" + String.format("%1$04d", i)));
1614       put.add(HConstants.CATALOG_FAMILY, null, value);
1615       table.put(put);
1616       if (i % 32 == 0) {
1617         // After every 32 writes sleep to let the log roller run
1618         try {
1619           Thread.sleep(2000);
1620         } catch (InterruptedException e) {
1621           // continue
1622         }
1623       }
1624     }
1625 
1626     table.close();
1627     return regionServer;
1628   }
1629 
1630   /**
1631    * HBASE-4417 checkHBaseAvailable() doesn't close zk connections
1632    */
1633   @Test
1634   public void testCheckHBaseAvailableClosesConnection() throws Exception {
1635     Configuration conf = TEST_UTIL.getConfiguration();
1636 
1637     int initialCount = HConnectionTestingUtility.getConnectionCount();
1638     HBaseAdmin.checkHBaseAvailable(conf);
1639     int finalCount = HConnectionTestingUtility.getConnectionCount();
1640 
1641     Assert.assertEquals(initialCount, finalCount) ;
1642   }
1643 
1644   @Test
1645   public void testDisableCatalogTable() throws Exception {
1646     try {
1647       this.admin.disableTable(".META.");
1648       fail("Expected to throw IllegalArgumentException");
1649     } catch (IllegalArgumentException e) {
1650     }
1651     // Before the fix for HBASE-6146, the below table creation was failing as the META table
1652     // actually getting disabled by the disableTable() call.
1653     HTableDescriptor htd = new HTableDescriptor("testDisableCatalogTable".getBytes());
1654     HColumnDescriptor hcd = new HColumnDescriptor("cf1".getBytes());
1655     htd.addFamily(hcd);
1656     TEST_UTIL.getHBaseAdmin().createTable(htd);
1657   }
1658 
1659   @Test
1660   public void testGetRegion() throws Exception {
1661     final String name = "testGetRegion";
1662     LOG.info("Started " + name);
1663     final byte [] nameBytes = Bytes.toBytes(name);
1664     HTable t = TEST_UTIL.createTable(nameBytes, HConstants.CATALOG_FAMILY);
1665     TEST_UTIL.createMultiRegions(t, HConstants.CATALOG_FAMILY);
1666     CatalogTracker ct = new CatalogTracker(TEST_UTIL.getConfiguration());
1667     ct.start();
1668     try {
1669       HRegionLocation regionLocation = t.getRegionLocation("mmm");
1670       HRegionInfo region = regionLocation.getRegionInfo();
1671       byte[] regionName = region.getRegionName();
1672       Pair<HRegionInfo, ServerName> pair = admin.getRegion(regionName, ct);
1673       assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName()));
1674       pair = admin.getRegion(region.getEncodedNameAsBytes(), ct);
1675       assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName()));
1676     } finally {
1677       ct.stop();
1678     }
1679   }
1680 
1681   @Test
1682   public void testRootTableSplit() throws Exception {
1683     Scan s = new Scan();
1684     HTable rootTable = new HTable(TEST_UTIL.getConfiguration(), HConstants.ROOT_TABLE_NAME);
1685     ResultScanner scanner = rootTable.getScanner(s);
1686     Result metaEntry = scanner.next();
1687     this.admin.split(HConstants.ROOT_TABLE_NAME, metaEntry.getRow());
1688     Thread.sleep(1000);
1689     List<HRegion> regions = TEST_UTIL.getMiniHBaseCluster().getRegions(HConstants.ROOT_TABLE_NAME);
1690     assertEquals("ROOT region should not be splitted.",1, regions.size());
1691   }
1692 
1693   @Test
1694   public void testIsEnabledOrDisabledOnUnknownTable() throws Exception {
1695     try {
1696       admin.isTableEnabled(Bytes.toBytes("unkownTable"));
1697       fail("Test should fail if isTableEnabled called on unknown table.");
1698     } catch (IOException e) {
1699     }
1700 
1701     try {
1702       admin.isTableDisabled(Bytes.toBytes("unkownTable"));
1703       fail("Test should fail if isTableDisabled called on unknown table.");
1704     } catch (IOException e) {
1705     }
1706   }
1707 
1708   @org.junit.Rule
1709   public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
1710     new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
1711 }