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.client;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.IOException;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  import java.util.concurrent.atomic.AtomicBoolean;
34  import java.util.concurrent.atomic.AtomicInteger;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.hadoop.hbase.HBaseTestingUtility;
39  import org.apache.hadoop.hbase.HColumnDescriptor;
40  import org.apache.hadoop.hbase.HConstants;
41  import org.apache.hadoop.hbase.HRegionInfo;
42  import org.apache.hadoop.hbase.HTableDescriptor;
43  import org.apache.hadoop.hbase.InvalidFamilyOperationException;
44  import org.apache.hadoop.hbase.testclassification.LargeTests;
45  import org.apache.hadoop.hbase.ServerName;
46  import org.apache.hadoop.hbase.TableName;
47  import org.apache.hadoop.hbase.TableNotDisabledException;
48  import org.apache.hadoop.hbase.TableNotEnabledException;
49  import org.apache.hadoop.hbase.TableNotFoundException;
50  import org.apache.hadoop.hbase.executor.EventHandler;
51  import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
52  import org.apache.hadoop.hbase.util.Bytes;
53  import org.apache.hadoop.hbase.zookeeper.ZKTableStateClientSideReader;
54  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
55  import org.junit.After;
56  import org.junit.AfterClass;
57  import org.junit.Before;
58  import org.junit.BeforeClass;
59  import org.junit.Test;
60  import org.junit.experimental.categories.Category;
61  
62  /**
63   * Class to test HBaseAdmin.
64   * Spins up the minicluster once at test start and then takes it down afterward.
65   * Add any testing of HBaseAdmin functionality here.
66   */
67  @Category(LargeTests.class)
68  public class TestAdmin1 {
69    final Log LOG = LogFactory.getLog(getClass());
70    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
71    private Admin admin;
72  
73    @BeforeClass
74    public static void setUpBeforeClass() throws Exception {
75      TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
76      TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
77      TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
78      TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
79      TEST_UTIL.getConfiguration().setBoolean(
80          "hbase.master.enabletable.roundrobin", true);
81      TEST_UTIL.startMiniCluster(3);
82    }
83  
84    @AfterClass
85    public static void tearDownAfterClass() throws Exception {
86      TEST_UTIL.shutdownMiniCluster();
87    }
88  
89    @Before
90    public void setUp() throws Exception {
91      this.admin = TEST_UTIL.getHBaseAdmin();
92    }
93  
94    @After
95    public void tearDown() throws Exception {
96      for (HTableDescriptor htd : this.admin.listTables()) {
97        TEST_UTIL.deleteTable(htd.getName());
98      }
99    }
100 
101   @Test (timeout=300000)
102   public void testSplitFlushCompactUnknownTable() throws InterruptedException {
103     final TableName unknowntable = TableName.valueOf("fubar");
104     Exception exception = null;
105     try {
106       this.admin.compact(unknowntable);
107     } catch (IOException e) {
108       exception = e;
109     }
110     assertTrue(exception instanceof TableNotFoundException);
111 
112     exception = null;
113     try {
114       this.admin.flush(unknowntable);
115     } catch (IOException e) {
116       exception = e;
117     }
118     assertTrue(exception instanceof TableNotFoundException);
119 
120     exception = null;
121     try {
122       this.admin.split(unknowntable);
123     } catch (IOException e) {
124       exception = e;
125     }
126     assertTrue(exception instanceof TableNotFoundException);
127   }
128 
129   @Test (timeout=300000)
130   public void testDeleteEditUnknownColumnFamilyAndOrTable() throws IOException {
131     // Test we get exception if we try to
132     final TableName nonexistentTable = TableName.valueOf("nonexistent");
133     final byte[] nonexistentColumn = Bytes.toBytes("nonexistent");
134     HColumnDescriptor nonexistentHcd = new HColumnDescriptor(nonexistentColumn);
135     Exception exception = null;
136     try {
137       this.admin.addColumn(nonexistentTable, nonexistentHcd);
138     } catch (IOException e) {
139       exception = e;
140     }
141     assertTrue(exception instanceof TableNotFoundException);
142 
143     exception = null;
144     try {
145       this.admin.deleteTable(nonexistentTable);
146     } catch (IOException e) {
147       exception = e;
148     }
149     assertTrue(exception instanceof TableNotFoundException);
150 
151     exception = null;
152     try {
153       this.admin.deleteColumn(nonexistentTable, nonexistentColumn);
154     } catch (IOException e) {
155       exception = e;
156     }
157     assertTrue(exception instanceof TableNotFoundException);
158 
159     exception = null;
160     try {
161       this.admin.disableTable(nonexistentTable);
162     } catch (IOException e) {
163       exception = e;
164     }
165     assertTrue(exception instanceof TableNotFoundException);
166 
167     exception = null;
168     try {
169       this.admin.enableTable(nonexistentTable);
170     } catch (IOException e) {
171       exception = e;
172     }
173     assertTrue(exception instanceof TableNotFoundException);
174 
175     exception = null;
176     try {
177       this.admin.modifyColumn(nonexistentTable, nonexistentHcd);
178     } catch (IOException e) {
179       exception = e;
180     }
181     assertTrue(exception instanceof TableNotFoundException);
182 
183     exception = null;
184     try {
185       HTableDescriptor htd = new HTableDescriptor(nonexistentTable);
186       htd.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
187       this.admin.modifyTable(htd.getTableName(), htd);
188     } catch (IOException e) {
189       exception = e;
190     }
191     assertTrue(exception instanceof TableNotFoundException);
192 
193     // Now make it so at least the table exists and then do tests against a
194     // nonexistent column family -- see if we get right exceptions.
195     final TableName tableName =
196       TableName.valueOf("testDeleteEditUnknownColumnFamilyAndOrTable" + System.currentTimeMillis());
197     HTableDescriptor htd = new HTableDescriptor(tableName);
198     htd.addFamily(new HColumnDescriptor("cf"));
199     this.admin.createTable(htd);
200     try {
201       exception = null;
202       try {
203         this.admin.deleteColumn(htd.getTableName(), nonexistentHcd.getName());
204       } catch (IOException e) {
205         exception = e;
206       }
207       assertTrue("found=" + exception.getClass().getName(),
208           exception instanceof InvalidFamilyOperationException);
209 
210       exception = null;
211       try {
212         this.admin.modifyColumn(htd.getTableName(), nonexistentHcd);
213       } catch (IOException e) {
214         exception = e;
215       }
216       assertTrue("found=" + exception.getClass().getName(),
217           exception instanceof InvalidFamilyOperationException);
218     } finally {
219       this.admin.disableTable(tableName);
220       this.admin.deleteTable(tableName);
221     }
222   }
223 
224   @Test (timeout=300000)
225   public void testDisableAndEnableTable() throws IOException {
226     final byte [] row = Bytes.toBytes("row");
227     final byte [] qualifier = Bytes.toBytes("qualifier");
228     final byte [] value = Bytes.toBytes("value");
229     final TableName table = TableName.valueOf("testDisableAndEnableTable");
230     Table ht = TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
231     Put put = new Put(row);
232     put.add(HConstants.CATALOG_FAMILY, qualifier, value);
233     ht.put(put);
234     Get get = new Get(row);
235     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
236     ht.get(get);
237 
238     this.admin.disableTable(ht.getName());
239     assertTrue("Table must be disabled.", TEST_UTIL.getHBaseCluster()
240         .getMaster().getAssignmentManager().getTableStateManager().isTableState(
241         ht.getName(), ZooKeeperProtos.Table.State.DISABLED));
242 
243     // Test that table is disabled
244     get = new Get(row);
245     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
246     boolean ok = false;
247     try {
248       ht.get(get);
249     } catch (TableNotEnabledException e) {
250       ok = true;
251     }
252     ok = false;
253     // verify that scan encounters correct exception
254     Scan scan = new Scan();
255     try {
256       ResultScanner scanner = ht.getScanner(scan);
257       Result res = null;
258       do {
259         res = scanner.next();
260       } while (res != null);
261     } catch (TableNotEnabledException e) {
262       ok = true;
263     }
264     assertTrue(ok);
265     this.admin.enableTable(table);
266     assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
267         .getMaster().getAssignmentManager().getTableStateManager().isTableState(
268         ht.getName(), ZooKeeperProtos.Table.State.ENABLED));
269 
270     // Test that table is enabled
271     try {
272       ht.get(get);
273     } catch (RetriesExhaustedException e) {
274       ok = false;
275     }
276     assertTrue(ok);
277     ht.close();
278   }
279 
280   @Test (timeout=300000)
281   public void testDisableAndEnableTables() throws IOException {
282     final byte [] row = Bytes.toBytes("row");
283     final byte [] qualifier = Bytes.toBytes("qualifier");
284     final byte [] value = Bytes.toBytes("value");
285     final TableName table1 = TableName.valueOf("testDisableAndEnableTable1");
286     final TableName table2 = TableName.valueOf("testDisableAndEnableTable2");
287     Table ht1 = TEST_UTIL.createTable(table1, HConstants.CATALOG_FAMILY);
288     Table ht2 = TEST_UTIL.createTable(table2, HConstants.CATALOG_FAMILY);
289     Put put = new Put(row);
290     put.add(HConstants.CATALOG_FAMILY, qualifier, value);
291     ht1.put(put);
292     ht2.put(put);
293     Get get = new Get(row);
294     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
295     ht1.get(get);
296     ht2.get(get);
297 
298     this.admin.disableTables("testDisableAndEnableTable.*");
299 
300     // Test that tables are disabled
301     get = new Get(row);
302     get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
303     boolean ok = false;
304     try {
305       ht1.get(get);
306       ht2.get(get);
307     } catch (org.apache.hadoop.hbase.DoNotRetryIOException e) {
308       ok = true;
309     }
310 
311     assertTrue(ok);
312     this.admin.enableTables("testDisableAndEnableTable.*");
313 
314     // Test that tables are enabled
315     try {
316       ht1.get(get);
317     } catch (IOException e) {
318       ok = false;
319     }
320     try {
321       ht2.get(get);
322     } catch (IOException e) {
323       ok = false;
324     }
325     assertTrue(ok);
326 
327     ht1.close();
328     ht2.close();
329   }
330 
331   @Test (timeout=300000)
332   public void testCreateTable() throws IOException {
333     HTableDescriptor [] tables = admin.listTables();
334     int numTables = tables.length;
335     TEST_UTIL.createTable(TableName.valueOf("testCreateTable"), HConstants.CATALOG_FAMILY).close();
336     tables = this.admin.listTables();
337     assertEquals(numTables + 1, tables.length);
338     assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
339         .getMaster().getAssignmentManager().getTableStateManager().isTableState(
340         TableName.valueOf("testCreateTable"), ZooKeeperProtos.Table.State.ENABLED));
341   }
342 
343   @Test (timeout=300000)
344   public void testTruncateTable() throws IOException {
345     testTruncateTable(TableName.valueOf("testTruncateTable"), false);
346   }
347 
348   @Test (timeout=300000)
349   public void testTruncateTablePreservingSplits() throws IOException {
350     testTruncateTable(TableName.valueOf("testTruncateTablePreservingSplits"), true);
351   }
352 
353   private void testTruncateTable(final TableName tableName, boolean preserveSplits)
354       throws IOException {
355     byte[][] splitKeys = new byte[2][];
356     splitKeys[0] = Bytes.toBytes(4);
357     splitKeys[1] = Bytes.toBytes(8);
358 
359     // Create & Fill the table
360     HTable table = TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY, splitKeys);
361     try {
362       TEST_UTIL.loadNumericRows(table, HConstants.CATALOG_FAMILY, 0, 10);
363       assertEquals(10, TEST_UTIL.countRows(table));
364     } finally {
365       table.close();
366     }
367     assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
368 
369     // Truncate & Verify
370     this.admin.disableTable(tableName);
371     this.admin.truncateTable(tableName, preserveSplits);
372     table = new HTable(TEST_UTIL.getConfiguration(), tableName);
373     try {
374       assertEquals(0, TEST_UTIL.countRows(table));
375     } finally {
376       table.close();
377     }
378     if (preserveSplits) {
379       assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
380     } else {
381       assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
382     }
383   }
384 
385   @Test (timeout=300000)
386   public void testGetTableDescriptor() throws IOException {
387     HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
388     HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
389     HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
390     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("myTestTable"));
391     htd.addFamily(fam1);
392     htd.addFamily(fam2);
393     htd.addFamily(fam3);
394     this.admin.createTable(htd);
395     Table table = new HTable(TEST_UTIL.getConfiguration(), htd.getTableName());
396     HTableDescriptor confirmedHtd = table.getTableDescriptor();
397     assertEquals(htd.compareTo(confirmedHtd), 0);
398     table.close();
399   }
400 
401   @Test (timeout=300000)
402   public void testHColumnValidName() {
403        boolean exceptionThrown;
404        try {
405          new HColumnDescriptor("\\test\\abc");
406        } catch(IllegalArgumentException iae) {
407            exceptionThrown = true;
408            assertTrue(exceptionThrown);
409        }
410    }
411 
412   /**
413    * Verify schema modification takes.
414    * @throws IOException
415    * @throws InterruptedException
416    */
417   @Test (timeout=300000)
418   public void testOnlineChangeTableSchema() throws IOException, InterruptedException {
419     final TableName tableName =
420         TableName.valueOf("changeTableSchemaOnline");
421     TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
422         "hbase.online.schema.update.enable", true);
423     HTableDescriptor [] tables = admin.listTables();
424     int numTables = tables.length;
425     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
426     tables = this.admin.listTables();
427     assertEquals(numTables + 1, tables.length);
428 
429     // FIRST, do htabledescriptor changes.
430     HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
431     // Make a copy and assert copy is good.
432     HTableDescriptor copy = new HTableDescriptor(htd);
433     assertTrue(htd.equals(copy));
434     // Now amend the copy. Introduce differences.
435     long newFlushSize = htd.getMemStoreFlushSize() / 2;
436     if (newFlushSize <=0) {
437       newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
438     }
439     copy.setMemStoreFlushSize(newFlushSize);
440     final String key = "anyoldkey";
441     assertTrue(htd.getValue(key) == null);
442     copy.setValue(key, key);
443     boolean expectedException = false;
444     try {
445       admin.modifyTable(tableName, copy);
446     } catch (TableNotDisabledException re) {
447       expectedException = true;
448     }
449     assertFalse(expectedException);
450     HTableDescriptor modifiedHtd = this.admin.getTableDescriptor(tableName);
451     assertFalse(htd.equals(modifiedHtd));
452     assertTrue(copy.equals(modifiedHtd));
453     assertEquals(newFlushSize, modifiedHtd.getMemStoreFlushSize());
454     assertEquals(key, modifiedHtd.getValue(key));
455 
456     // Now work on column family changes.
457     int countOfFamilies = modifiedHtd.getFamilies().size();
458     assertTrue(countOfFamilies > 0);
459     HColumnDescriptor hcd = modifiedHtd.getFamilies().iterator().next();
460     int maxversions = hcd.getMaxVersions();
461     final int newMaxVersions = maxversions + 1;
462     hcd.setMaxVersions(newMaxVersions);
463     final byte [] hcdName = hcd.getName();
464     expectedException = false;
465     try {
466       this.admin.modifyColumn(tableName, hcd);
467     } catch (TableNotDisabledException re) {
468       expectedException = true;
469     }
470     assertFalse(expectedException);
471     modifiedHtd = this.admin.getTableDescriptor(tableName);
472     HColumnDescriptor modifiedHcd = modifiedHtd.getFamily(hcdName);
473     assertEquals(newMaxVersions, modifiedHcd.getMaxVersions());
474 
475     // Try adding a column
476     assertFalse(this.admin.isTableDisabled(tableName));
477     final String xtracolName = "xtracol";
478     HColumnDescriptor xtracol = new HColumnDescriptor(xtracolName);
479     xtracol.setValue(xtracolName, xtracolName);
480     expectedException = false;
481     try {
482       this.admin.addColumn(tableName, xtracol);
483     } catch (TableNotDisabledException re) {
484       expectedException = true;
485     }
486     // Add column should work even if the table is enabled
487     assertFalse(expectedException);
488     modifiedHtd = this.admin.getTableDescriptor(tableName);
489     hcd = modifiedHtd.getFamily(xtracol.getName());
490     assertTrue(hcd != null);
491     assertTrue(hcd.getValue(xtracolName).equals(xtracolName));
492 
493     // Delete the just-added column.
494     this.admin.deleteColumn(tableName, xtracol.getName());
495     modifiedHtd = this.admin.getTableDescriptor(tableName);
496     hcd = modifiedHtd.getFamily(xtracol.getName());
497     assertTrue(hcd == null);
498 
499     // Delete the table
500     this.admin.disableTable(tableName);
501     this.admin.deleteTable(tableName);
502     this.admin.listTables();
503     assertFalse(this.admin.tableExists(tableName));
504   }
505 
506   @Test (timeout=300000)
507   public void testShouldFailOnlineSchemaUpdateIfOnlineSchemaIsNotEnabled()
508       throws Exception {
509     final TableName tableName = TableName.valueOf("changeTableSchemaOnlineFailure");
510     TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
511         "hbase.online.schema.update.enable", false);
512     HTableDescriptor[] tables = admin.listTables();
513     int numTables = tables.length;
514     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
515     tables = this.admin.listTables();
516     assertEquals(numTables + 1, tables.length);
517 
518     // FIRST, do htabledescriptor changes.
519     HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
520     // Make a copy and assert copy is good.
521     HTableDescriptor copy = new HTableDescriptor(htd);
522     assertTrue(htd.equals(copy));
523     // Now amend the copy. Introduce differences.
524     long newFlushSize = htd.getMemStoreFlushSize() / 2;
525     if (newFlushSize <=0) {
526       newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
527     }
528     copy.setMemStoreFlushSize(newFlushSize);
529     final String key = "anyoldkey";
530     assertTrue(htd.getValue(key) == null);
531     copy.setValue(key, key);
532     boolean expectedException = false;
533     try {
534       admin.modifyTable(tableName, copy);
535     } catch (TableNotDisabledException re) {
536       expectedException = true;
537     }
538     assertTrue("Online schema update should not happen.", expectedException);
539 
540     // Reset the value for the other tests
541     TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
542         "hbase.online.schema.update.enable", true);
543   }
544 
545   /**
546    * Listens for when an event is done in Master.
547    */
548   static class DoneListener implements EventHandler.EventHandlerListener {
549     private final AtomicBoolean done;
550 
551     DoneListener(final AtomicBoolean done) {
552       super();
553       this.done = done;
554     }
555 
556     @Override
557     public void afterProcess(EventHandler event) {
558       this.done.set(true);
559       synchronized (this.done) {
560         // Wake anyone waiting on this value to change.
561         this.done.notifyAll();
562       }
563     }
564 
565     @Override
566     public void beforeProcess(EventHandler event) {
567       // continue
568     }
569   }
570 
571   @SuppressWarnings("deprecation")
572   protected void verifyRoundRobinDistribution(HTable ht, int expectedRegions) throws IOException {
573     int numRS = ht.getConnection().getCurrentNrHRS();
574     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
575     Map<ServerName, List<HRegionInfo>> server2Regions = new HashMap<ServerName, List<HRegionInfo>>();
576     for (Map.Entry<HRegionInfo, ServerName> entry : regions.entrySet()) {
577       ServerName server = entry.getValue();
578       List<HRegionInfo> regs = server2Regions.get(server);
579       if (regs == null) {
580         regs = new ArrayList<HRegionInfo>();
581         server2Regions.put(server, regs);
582       }
583       regs.add(entry.getKey());
584     }
585     float average = (float) expectedRegions/numRS;
586     int min = (int)Math.floor(average);
587     int max = (int)Math.ceil(average);
588     for (List<HRegionInfo> regionList : server2Regions.values()) {
589       assertTrue(regionList.size() == min || regionList.size() == max);
590     }
591   }
592 
593   @Test (timeout=300000)
594   public void testCreateTableNumberOfRegions() throws IOException, InterruptedException {
595     TableName tableName = TableName.valueOf("testCreateTableNumberOfRegions");
596     HTableDescriptor desc = new HTableDescriptor(tableName);
597     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
598     admin.createTable(desc);
599     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
600     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
601     assertEquals("Table should have only 1 region", 1, regions.size());
602     ht.close();
603 
604     TableName TABLE_2 = TableName.valueOf(tableName.getNameAsString() + "_2");
605     desc = new HTableDescriptor(TABLE_2);
606     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
607     admin.createTable(desc, new byte[][]{new byte[]{42}});
608     HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
609     regions = ht2.getRegionLocations();
610     assertEquals("Table should have only 2 region", 2, regions.size());
611     ht2.close();
612 
613     TableName TABLE_3 = TableName.valueOf(tableName.getNameAsString() + "_3");
614     desc = new HTableDescriptor(TABLE_3);
615     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
616     admin.createTable(desc, "a".getBytes(), "z".getBytes(), 3);
617     HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
618     regions = ht3.getRegionLocations();
619     assertEquals("Table should have only 3 region", 3, regions.size());
620     ht3.close();
621 
622     TableName TABLE_4 = TableName.valueOf(tableName.getNameAsString() + "_4");
623     desc = new HTableDescriptor(TABLE_4);
624     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
625     try {
626       admin.createTable(desc, "a".getBytes(), "z".getBytes(), 2);
627       fail("Should not be able to create a table with only 2 regions using this API.");
628     } catch (IllegalArgumentException eae) {
629     // Expected
630     }
631 
632     TableName TABLE_5 = TableName.valueOf(tableName.getNameAsString() + "_5");
633     desc = new HTableDescriptor(TABLE_5);
634     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
635     admin.createTable(desc, new byte[] {1}, new byte[] {127}, 16);
636     HTable ht5 = new HTable(TEST_UTIL.getConfiguration(), TABLE_5);
637     regions = ht5.getRegionLocations();
638     assertEquals("Table should have 16 region", 16, regions.size());
639     ht5.close();
640   }
641 
642   @Test (timeout=300000)
643   public void testCreateTableWithRegions() throws IOException, InterruptedException {
644 
645     TableName tableName = TableName.valueOf("testCreateTableWithRegions");
646 
647     byte [][] splitKeys = {
648         new byte [] { 1, 1, 1 },
649         new byte [] { 2, 2, 2 },
650         new byte [] { 3, 3, 3 },
651         new byte [] { 4, 4, 4 },
652         new byte [] { 5, 5, 5 },
653         new byte [] { 6, 6, 6 },
654         new byte [] { 7, 7, 7 },
655         new byte [] { 8, 8, 8 },
656         new byte [] { 9, 9, 9 },
657     };
658     int expectedRegions = splitKeys.length + 1;
659 
660     HTableDescriptor desc = new HTableDescriptor(tableName);
661     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
662     admin.createTable(desc, splitKeys);
663 
664     boolean tableAvailable = admin.isTableAvailable(tableName, splitKeys);
665     assertTrue("Table should be created with splitKyes + 1 rows in META", tableAvailable);
666 
667     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
668     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
669     assertEquals("Tried to create " + expectedRegions + " regions " +
670         "but only found " + regions.size(),
671         expectedRegions, regions.size());
672     System.err.println("Found " + regions.size() + " regions");
673 
674     Iterator<HRegionInfo> hris = regions.keySet().iterator();
675     HRegionInfo hri = hris.next();
676     assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
677     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
678     hri = hris.next();
679     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
680     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
681     hri = hris.next();
682     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
683     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
684     hri = hris.next();
685     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
686     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
687     hri = hris.next();
688     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
689     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
690     hri = hris.next();
691     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
692     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
693     hri = hris.next();
694     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
695     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
696     hri = hris.next();
697     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
698     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
699     hri = hris.next();
700     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
701     assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
702     hri = hris.next();
703     assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
704     assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
705 
706     verifyRoundRobinDistribution(ht, expectedRegions);
707     ht.close();
708 
709     // Now test using start/end with a number of regions
710 
711     // Use 80 bit numbers to make sure we aren't limited
712     byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
713     byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
714 
715     // Splitting into 10 regions, we expect (null,1) ... (9, null)
716     // with (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) in the middle
717 
718     expectedRegions = 10;
719 
720     TableName TABLE_2 = TableName.valueOf(tableName.getNameAsString() + "_2");
721 
722     desc = new HTableDescriptor(TABLE_2);
723     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
724     admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
725     admin.createTable(desc, startKey, endKey, expectedRegions);
726 
727     HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
728     regions = ht2.getRegionLocations();
729     assertEquals("Tried to create " + expectedRegions + " regions " +
730         "but only found " + regions.size(),
731         expectedRegions, regions.size());
732     System.err.println("Found " + regions.size() + " regions");
733 
734     hris = regions.keySet().iterator();
735     hri = hris.next();
736     assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
737     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
738     hri = hris.next();
739     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
740     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
741     hri = hris.next();
742     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
743     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
744     hri = hris.next();
745     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
746     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
747     hri = hris.next();
748     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
749     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
750     hri = hris.next();
751     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
752     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
753     hri = hris.next();
754     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
755     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
756     hri = hris.next();
757     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
758     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
759     hri = hris.next();
760     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
761     assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
762     hri = hris.next();
763     assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
764     assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
765 
766     verifyRoundRobinDistribution(ht2, expectedRegions);
767     ht2.close();
768 
769     // Try once more with something that divides into something infinite
770 
771     startKey = new byte [] { 0, 0, 0, 0, 0, 0 };
772     endKey = new byte [] { 1, 0, 0, 0, 0, 0 };
773 
774     expectedRegions = 5;
775 
776     TableName TABLE_3 = TableName.valueOf(tableName.getNameAsString() + "_3");
777 
778     desc = new HTableDescriptor(TABLE_3);
779     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
780     admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
781     admin.createTable(desc, startKey, endKey, expectedRegions);
782 
783 
784     HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
785     regions = ht3.getRegionLocations();
786     assertEquals("Tried to create " + expectedRegions + " regions " +
787         "but only found " + regions.size(),
788         expectedRegions, regions.size());
789     System.err.println("Found " + regions.size() + " regions");
790 
791     verifyRoundRobinDistribution(ht3, expectedRegions);
792     ht3.close();
793 
794 
795     // Try an invalid case where there are duplicate split keys
796     splitKeys = new byte [][] {
797         new byte [] { 1, 1, 1 },
798         new byte [] { 2, 2, 2 },
799         new byte [] { 3, 3, 3 },
800         new byte [] { 2, 2, 2 }
801     };
802 
803     TableName TABLE_4 = TableName.valueOf(tableName.getNameAsString() + "_4");
804     desc = new HTableDescriptor(TABLE_4);
805     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
806     Admin ladmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
807     try {
808       ladmin.createTable(desc, splitKeys);
809       assertTrue("Should not be able to create this table because of " +
810           "duplicate split keys", false);
811     } catch(IllegalArgumentException iae) {
812       // Expected
813     }
814     ladmin.close();
815   }
816 
817   @Test (timeout=300000)
818   public void testTableAvailableWithRandomSplitKeys() throws Exception {
819     TableName tableName = TableName.valueOf("testTableAvailableWithRandomSplitKeys");
820     HTableDescriptor desc = new HTableDescriptor(tableName);
821     desc.addFamily(new HColumnDescriptor("col"));
822     byte[][] splitKeys = new byte[1][];
823     splitKeys = new byte [][] {
824         new byte [] { 1, 1, 1 },
825         new byte [] { 2, 2, 2 }
826     };
827     admin.createTable(desc);
828     boolean tableAvailable = admin.isTableAvailable(tableName, splitKeys);
829     assertFalse("Table should be created with 1 row in META", tableAvailable);
830   }
831 
832   @Test (timeout=300000)
833   public void testCreateTableWithOnlyEmptyStartRow() throws IOException {
834     byte[] tableName = Bytes.toBytes("testCreateTableWithOnlyEmptyStartRow");
835     byte[][] splitKeys = new byte[1][];
836     splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
837     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
838     desc.addFamily(new HColumnDescriptor("col"));
839     try {
840       admin.createTable(desc, splitKeys);
841       fail("Test case should fail as empty split key is passed.");
842     } catch (IllegalArgumentException e) {
843     }
844   }
845 
846   @Test (timeout=300000)
847   public void testCreateTableWithEmptyRowInTheSplitKeys() throws IOException{
848     byte[] tableName = Bytes.toBytes("testCreateTableWithEmptyRowInTheSplitKeys");
849     byte[][] splitKeys = new byte[3][];
850     splitKeys[0] = "region1".getBytes();
851     splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY;
852     splitKeys[2] = "region2".getBytes();
853     HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
854     desc.addFamily(new HColumnDescriptor("col"));
855     try {
856       admin.createTable(desc, splitKeys);
857       fail("Test case should fail as empty split key is passed.");
858     } catch (IllegalArgumentException e) {
859       LOG.info("Expected ", e);
860     }
861   }
862 
863   @Test (timeout=120000)
864   public void testTableExist() throws IOException {
865     final TableName table = TableName.valueOf("testTableExist");
866     boolean exist;
867     exist = this.admin.tableExists(table);
868     assertEquals(false, exist);
869     TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
870     exist = this.admin.tableExists(table);
871     assertEquals(true, exist);
872   }
873 
874   /**
875    * Tests forcing split from client and having scanners successfully ride over split.
876    * @throws Exception
877    * @throws IOException
878    */
879   @Test (timeout=400000)
880   public void testForceSplit() throws Exception {
881     byte[][] familyNames = new byte[][] { Bytes.toBytes("cf") };
882     int[] rowCounts = new int[] { 6000 };
883     int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
884     int blockSize = 256;
885     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
886 
887     byte[] splitKey = Bytes.toBytes(3500);
888     splitTest(splitKey, familyNames, rowCounts, numVersions, blockSize);
889   }
890 
891   /**
892    * Test retain assignment on enableTable.
893    *
894    * @throws IOException
895    */
896   @Test (timeout=300000)
897   public void testEnableTableRetainAssignment() throws IOException {
898     final TableName tableName = TableName.valueOf("testEnableTableAssignment");
899     byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 },
900         new byte[] { 3, 3, 3 }, new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 },
901         new byte[] { 6, 6, 6 }, new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 },
902         new byte[] { 9, 9, 9 } };
903     int expectedRegions = splitKeys.length + 1;
904     HTableDescriptor desc = new HTableDescriptor(tableName);
905     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
906     admin.createTable(desc, splitKeys);
907     HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
908     Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
909     assertEquals("Tried to create " + expectedRegions + " regions "
910         + "but only found " + regions.size(), expectedRegions, regions.size());
911     // Disable table.
912     admin.disableTable(tableName);
913     // Enable table, use retain assignment to assign regions.
914     admin.enableTable(tableName);
915     Map<HRegionInfo, ServerName> regions2 = ht.getRegionLocations();
916 
917     // Check the assignment.
918     assertEquals(regions.size(), regions2.size());
919     for (Map.Entry<HRegionInfo, ServerName> entry : regions.entrySet()) {
920       assertEquals(regions2.get(entry.getKey()), entry.getValue());
921     }
922   }
923 
924   /**
925    * Multi-family scenario. Tests forcing split from client and
926    * having scanners successfully ride over split.
927    * @throws Exception
928    * @throws IOException
929    */
930   @Test (timeout=800000)
931   public void testForceSplitMultiFamily() throws Exception {
932     int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
933 
934     // use small HFile block size so that we can have lots of blocks in HFile
935     // Otherwise, if there is only one block,
936     // HFileBlockIndex.midKey()'s value == startKey
937     int blockSize = 256;
938     byte[][] familyNames = new byte[][] { Bytes.toBytes("cf1"),
939       Bytes.toBytes("cf2") };
940 
941     // one of the column families isn't splittable
942     int[] rowCounts = new int[] { 6000, 1 };
943     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
944 
945     rowCounts = new int[] { 1, 6000 };
946     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
947 
948     // one column family has much smaller data than the other
949     // the split key should be based on the largest column family
950     rowCounts = new int[] { 6000, 300 };
951     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
952 
953     rowCounts = new int[] { 300, 6000 };
954     splitTest(null, familyNames, rowCounts, numVersions, blockSize);
955 
956   }
957 
958   void splitTest(byte[] splitPoint, byte[][] familyNames, int[] rowCounts,
959     int numVersions, int blockSize) throws Exception {
960     TableName tableName = TableName.valueOf("testForceSplit");
961     StringBuilder sb = new StringBuilder();
962     // Add tail to String so can see better in logs where a test is running.
963     for (int i = 0; i < rowCounts.length; i++) {
964       sb.append("_").append(Integer.toString(rowCounts[i]));
965     }
966     assertFalse(admin.tableExists(tableName));
967     final HTable table = TEST_UTIL.createTable(tableName, familyNames,
968       numVersions, blockSize);
969 
970     int rowCount = 0;
971     byte[] q = new byte[0];
972 
973     // insert rows into column families. The number of rows that have values
974     // in a specific column family is decided by rowCounts[familyIndex]
975     for (int index = 0; index < familyNames.length; index++) {
976       ArrayList<Put> puts = new ArrayList<Put>(rowCounts[index]);
977       for (int i = 0; i < rowCounts[index]; i++) {
978         byte[] k = Bytes.toBytes(i);
979         Put put = new Put(k);
980         put.add(familyNames[index], q, k);
981         puts.add(put);
982       }
983       table.put(puts);
984 
985       if ( rowCount < rowCounts[index] ) {
986         rowCount = rowCounts[index];
987       }
988     }
989 
990     // get the initial layout (should just be one region)
991     Map<HRegionInfo, ServerName> m = table.getRegionLocations();
992     LOG.info("Initial regions (" + m.size() + "): " + m);
993     assertTrue(m.size() == 1);
994 
995     // Verify row count
996     Scan scan = new Scan();
997     ResultScanner scanner = table.getScanner(scan);
998     int rows = 0;
999     for(@SuppressWarnings("unused") Result result : scanner) {
1000       rows++;
1001     }
1002     scanner.close();
1003     assertEquals(rowCount, rows);
1004 
1005     // Have an outstanding scan going on to make sure we can scan over splits.
1006     scan = new Scan();
1007     scanner = table.getScanner(scan);
1008     // Scan first row so we are into first region before split happens.
1009     scanner.next();
1010 
1011     // Split the table
1012     this.admin.split(tableName, splitPoint);
1013 
1014     final AtomicInteger count = new AtomicInteger(0);
1015     Thread t = new Thread("CheckForSplit") {
1016       @Override
1017       public void run() {
1018         for (int i = 0; i < 45; i++) {
1019           try {
1020             sleep(1000);
1021           } catch (InterruptedException e) {
1022             continue;
1023           }
1024           // check again    table = new HTable(conf, tableName);
1025           Map<HRegionInfo, ServerName> regions = null;
1026           try {
1027             regions = table.getRegionLocations();
1028           } catch (IOException e) {
1029             e.printStackTrace();
1030           }
1031           if (regions == null) continue;
1032           count.set(regions.size());
1033           if (count.get() >= 2) {
1034             LOG.info("Found: " + regions);
1035             break;
1036           }
1037           LOG.debug("Cycle waiting on split");
1038         }
1039         LOG.debug("CheckForSplit thread exited, current region count: " + count.get());
1040       }
1041     };
1042     t.setPriority(Thread.NORM_PRIORITY - 2);
1043     t.start();
1044     t.join();
1045 
1046     // Verify row count
1047     rows = 1; // We counted one row above.
1048     for (@SuppressWarnings("unused") Result result : scanner) {
1049       rows++;
1050       if (rows > rowCount) {
1051         scanner.close();
1052         assertTrue("Scanned more than expected (" + rowCount + ")", false);
1053       }
1054     }
1055     scanner.close();
1056     assertEquals(rowCount, rows);
1057 
1058     Map<HRegionInfo, ServerName> regions = null;
1059     try {
1060       regions = table.getRegionLocations();
1061     } catch (IOException e) {
1062       e.printStackTrace();
1063     }
1064     assertEquals(2, regions.size());
1065     Set<HRegionInfo> hRegionInfos = regions.keySet();
1066     HRegionInfo[] r = hRegionInfos.toArray(new HRegionInfo[hRegionInfos.size()]);
1067     if (splitPoint != null) {
1068       // make sure the split point matches our explicit configuration
1069       assertEquals(Bytes.toString(splitPoint),
1070           Bytes.toString(r[0].getEndKey()));
1071       assertEquals(Bytes.toString(splitPoint),
1072           Bytes.toString(r[1].getStartKey()));
1073       LOG.debug("Properly split on " + Bytes.toString(splitPoint));
1074     } else {
1075       if (familyNames.length > 1) {
1076         int splitKey = Bytes.toInt(r[0].getEndKey());
1077         // check if splitKey is based on the largest column family
1078         // in terms of it store size
1079         int deltaForLargestFamily = Math.abs(rowCount/2 - splitKey);
1080         LOG.debug("SplitKey=" + splitKey + "&deltaForLargestFamily=" + deltaForLargestFamily +
1081           ", r=" + r[0]);
1082         for (int index = 0; index < familyNames.length; index++) {
1083           int delta = Math.abs(rowCounts[index]/2 - splitKey);
1084           if (delta < deltaForLargestFamily) {
1085             assertTrue("Delta " + delta + " for family " + index
1086               + " should be at least deltaForLargestFamily " + deltaForLargestFamily,
1087               false);
1088           }
1089         }
1090       }
1091     }
1092     TEST_UTIL.deleteTable(tableName);
1093     table.close();
1094   }
1095 
1096   /**
1097    * HADOOP-2156
1098    * @throws IOException
1099    */
1100   @SuppressWarnings("deprecation")
1101   @Test (expected=IllegalArgumentException.class, timeout=300000)
1102   public void testEmptyHTableDescriptor() throws IOException {
1103     this.admin.createTable(new HTableDescriptor());
1104   }
1105 
1106   @Test (expected=IllegalArgumentException.class, timeout=300000)
1107   public void testInvalidHColumnDescriptor() throws IOException {
1108      new HColumnDescriptor("/cfamily/name");
1109   }
1110 
1111   @Test (timeout=300000)
1112   public void testEnableDisableAddColumnDeleteColumn() throws Exception {
1113     ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(TEST_UTIL);
1114     TableName tableName = TableName.valueOf("testMasterAdmin");
1115     TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
1116     while (!ZKTableStateClientSideReader.isEnabledTable(zkw,
1117       TableName.valueOf("testMasterAdmin"))) {
1118       Thread.sleep(10);
1119     }
1120     this.admin.disableTable(tableName);
1121     try {
1122       new HTable(TEST_UTIL.getConfiguration(), tableName);
1123     } catch (org.apache.hadoop.hbase.DoNotRetryIOException e) {
1124       //expected
1125     }
1126 
1127     this.admin.addColumn(tableName, new HColumnDescriptor("col2"));
1128     this.admin.enableTable(tableName);
1129     try {
1130       this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
1131     } catch (TableNotDisabledException e) {
1132       LOG.info(e);
1133     }
1134     this.admin.disableTable(tableName);
1135     this.admin.deleteTable(tableName);
1136   }
1137 }