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.List;
28  import java.util.Random;
29  import java.util.concurrent.atomic.AtomicInteger;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.conf.Configuration;
34  import org.apache.hadoop.hbase.HBaseTestingUtility;
35  import org.apache.hadoop.hbase.HColumnDescriptor;
36  import org.apache.hadoop.hbase.HConstants;
37  import org.apache.hadoop.hbase.HRegionInfo;
38  import org.apache.hadoop.hbase.HRegionLocation;
39  import org.apache.hadoop.hbase.HTableDescriptor;
40  import org.apache.hadoop.hbase.testclassification.LargeTests;
41  import org.apache.hadoop.hbase.MasterNotRunningException;
42  import org.apache.hadoop.hbase.MiniHBaseCluster;
43  import org.apache.hadoop.hbase.NotServingRegionException;
44  import org.apache.hadoop.hbase.ProcedureInfo;
45  import org.apache.hadoop.hbase.ServerName;
46  import org.apache.hadoop.hbase.TableExistsException;
47  import org.apache.hadoop.hbase.TableName;
48  import org.apache.hadoop.hbase.TableNotDisabledException;
49  import org.apache.hadoop.hbase.TableNotEnabledException;
50  import org.apache.hadoop.hbase.TableNotFoundException;
51  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
52  import org.apache.hadoop.hbase.constraint.ConstraintException;
53  import org.apache.hadoop.hbase.master.AssignmentManager;
54  import org.apache.hadoop.hbase.master.HMaster;
55  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
56  import org.apache.hadoop.hbase.regionserver.HRegionServer;
57  import org.apache.hadoop.hbase.regionserver.Region;
58  import org.apache.hadoop.hbase.util.Bytes;
59  import org.apache.hadoop.hbase.util.Pair;
60  import org.apache.hadoop.hbase.wal.DefaultWALProvider;
61  import org.junit.After;
62  import org.junit.AfterClass;
63  import org.junit.Assert;
64  import org.junit.Before;
65  import org.junit.BeforeClass;
66  import org.junit.Test;
67  import org.junit.experimental.categories.Category;
68  
69  import com.google.protobuf.ServiceException;
70  
71  /**
72   * Class to test HBaseAdmin.
73   * Spins up the minicluster once at test start and then takes it down afterward.
74   * Add any testing of HBaseAdmin functionality here.
75   */
76  @Category(LargeTests.class)
77  public class TestAdmin2 {
78    final Log LOG = LogFactory.getLog(getClass());
79    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
80    private Admin admin;
81  
82    @BeforeClass
83    public static void setUpBeforeClass() throws Exception {
84      TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
85      TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
86      TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
87      TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
88      TEST_UTIL.getConfiguration().setInt("hbase.regionserver.metahandler.count", 30);
89      TEST_UTIL.getConfiguration().setBoolean(
90          "hbase.master.enabletable.roundrobin", true);
91      TEST_UTIL.startMiniCluster(3);
92    }
93  
94    @AfterClass
95    public static void tearDownAfterClass() throws Exception {
96      TEST_UTIL.shutdownMiniCluster();
97    }
98  
99    @Before
100   public void setUp() throws Exception {
101     this.admin = TEST_UTIL.getHBaseAdmin();
102   }
103 
104   @After
105   public void tearDown() throws Exception {
106     for (HTableDescriptor htd : this.admin.listTables()) {
107       TEST_UTIL.deleteTable(htd.getName());
108     }
109   }
110 
111   @Test (timeout=300000)
112   public void testCreateBadTables() throws IOException {
113     String msg = null;
114     try {
115       this.admin.createTable(new HTableDescriptor(TableName.META_TABLE_NAME));
116     } catch(TableExistsException e) {
117       msg = e.toString();
118     }
119     assertTrue("Unexcepted exception message " + msg, msg != null &&
120       msg.startsWith(TableExistsException.class.getName()) &&
121       msg.contains(TableName.META_TABLE_NAME.getNameAsString()));
122 
123     // Now try and do concurrent creation with a bunch of threads.
124     final HTableDescriptor threadDesc =
125       new HTableDescriptor(TableName.valueOf("threaded_testCreateBadTables"));
126     threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
127     int count = 10;
128     Thread [] threads = new Thread [count];
129     final AtomicInteger successes = new AtomicInteger(0);
130     final AtomicInteger failures = new AtomicInteger(0);
131     final Admin localAdmin = this.admin;
132     for (int i = 0; i < count; i++) {
133       threads[i] = new Thread(Integer.toString(i)) {
134         @Override
135         public void run() {
136           try {
137             localAdmin.createTable(threadDesc);
138             successes.incrementAndGet();
139           } catch (TableExistsException e) {
140             failures.incrementAndGet();
141           } catch (IOException e) {
142             throw new RuntimeException("Failed threaded create" + getName(), e);
143           }
144         }
145       };
146     }
147     for (int i = 0; i < count; i++) {
148       threads[i].start();
149     }
150     for (int i = 0; i < count; i++) {
151       while(threads[i].isAlive()) {
152         try {
153           Thread.sleep(100);
154         } catch (InterruptedException e) {
155           // continue
156         }
157       }
158     }
159     // All threads are now dead.  Count up how many tables were created and
160     // how many failed w/ appropriate exception.
161     assertEquals(1, successes.get());
162     assertEquals(count - 1, failures.get());
163   }
164 
165   /**
166    * Test for hadoop-1581 'HBASE: Unopenable tablename bug'.
167    * @throws Exception
168    */
169   @Test (timeout=300000)
170   public void testTableNameClash() throws Exception {
171     String name = "testTableNameClash";
172     HTableDescriptor htd1 = new HTableDescriptor(TableName.valueOf(name + "SOMEUPPERCASE"));
173     HTableDescriptor htd2 = new HTableDescriptor(TableName.valueOf(name));
174     htd1.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
175     htd2.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
176     admin.createTable(htd1);
177     admin.createTable(htd2);
178     // Before fix, below would fail throwing a NoServerForRegionException.
179     new HTable(TEST_UTIL.getConfiguration(), htd2.getTableName()).close();
180   }
181 
182   /***
183    * HMaster.createTable used to be kind of synchronous call
184    * Thus creating of table with lots of regions can cause RPC timeout
185    * After the fix to make createTable truly async, RPC timeout shouldn't be an
186    * issue anymore
187    * @throws Exception
188    */
189   @Test (timeout=300000)
190   public void testCreateTableRPCTimeOut() throws Exception {
191     String name = "testCreateTableRPCTimeOut";
192     int oldTimeout = TEST_UTIL.getConfiguration().
193       getInt(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT);
194     TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500);
195     try {
196       int expectedRegions = 100;
197       // Use 80 bit numbers to make sure we aren't limited
198       byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
199       byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
200       Admin hbaseadmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
201       HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name));
202       htd.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
203       hbaseadmin.createTable(htd, startKey, endKey, expectedRegions);
204       hbaseadmin.close();
205     } finally {
206       TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, oldTimeout);
207     }
208   }
209 
210   /**
211    * Test read only tables
212    * @throws Exception
213    */
214   @Test (timeout=300000)
215   public void testReadOnlyTable() throws Exception {
216     TableName name = TableName.valueOf("testReadOnlyTable");
217     Table table = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
218     byte[] value = Bytes.toBytes("somedata");
219     // This used to use an empty row... That must have been a bug
220     Put put = new Put(value);
221     put.add(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY, value);
222     table.put(put);
223     table.close();
224   }
225 
226   /**
227    * Test that user table names can contain '-' and '.' so long as they do not
228    * start with same. HBASE-771
229    * @throws IOException
230    */
231   @Test (timeout=300000)
232   public void testTableNames() throws IOException {
233     byte[][] illegalNames = new byte[][] {
234         Bytes.toBytes("-bad"),
235         Bytes.toBytes(".bad")
236     };
237     for (byte[] illegalName : illegalNames) {
238       try {
239         new HTableDescriptor(TableName.valueOf(illegalName));
240         throw new IOException("Did not detect '" +
241             Bytes.toString(illegalName) + "' as an illegal user table name");
242       } catch (IllegalArgumentException e) {
243         // expected
244       }
245     }
246     byte[] legalName = Bytes.toBytes("g-oo.d");
247     try {
248       new HTableDescriptor(TableName.valueOf(legalName));
249     } catch (IllegalArgumentException e) {
250       throw new IOException("Legal user table name: '" +
251         Bytes.toString(legalName) + "' caused IllegalArgumentException: " +
252         e.getMessage());
253     }
254   }
255 
256   /**
257    * For HADOOP-2579
258    * @throws IOException
259    */
260   @Test (expected=TableExistsException.class, timeout=300000)
261   public void testTableExistsExceptionWithATable() throws IOException {
262     final TableName name = TableName.valueOf("testTableExistsExceptionWithATable");
263     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close();
264     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
265   }
266 
267   /**
268    * Can't disable a table if the table isn't in enabled state
269    * @throws IOException
270    */
271   @Test (expected=TableNotEnabledException.class, timeout=300000)
272   public void testTableNotEnabledExceptionWithATable() throws IOException {
273     final TableName name = TableName.valueOf("testTableNotEnabledExceptionWithATable");
274     TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close();
275     this.admin.disableTable(name);
276     this.admin.disableTable(name);
277   }
278 
279   /**
280    * Can't enable a table if the table isn't in disabled state
281    * @throws IOException
282    */
283   @Test (expected=TableNotDisabledException.class, timeout=300000)
284   public void testTableNotDisabledExceptionWithATable() throws IOException {
285     final TableName name = TableName.valueOf("testTableNotDisabledExceptionWithATable");
286     Table t = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
287     try {
288     this.admin.enableTable(name);
289     }finally {
290        t.close();
291     }
292   }
293 
294   /**
295    * For HADOOP-2579
296    * @throws IOException
297    */
298   @Test (expected=TableNotFoundException.class, timeout=300000)
299   public void testTableNotFoundExceptionWithoutAnyTables() throws IOException {
300     TableName tableName = TableName
301         .valueOf("testTableNotFoundExceptionWithoutAnyTables");
302     Table ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
303     ht.get(new Get("e".getBytes()));
304   }
305 
306 
307   @Test (timeout=300000)
308   public void testShouldCloseTheRegionBasedOnTheEncodedRegionName()
309       throws Exception {
310     TableName TABLENAME =
311         TableName.valueOf("TestHBACloseRegion");
312     createTableWithDefaultConf(TABLENAME);
313 
314     HRegionInfo info = null;
315     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
316     List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
317     for (HRegionInfo regionInfo : onlineRegions) {
318       if (!regionInfo.getTable().isSystemTable()) {
319         info = regionInfo;
320         admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), rs
321             .getServerName().getServerName());
322       }
323     }
324     boolean isInList = ProtobufUtil.getOnlineRegions(
325       rs.getRSRpcServices()).contains(info);
326     long timeout = System.currentTimeMillis() + 10000;
327     while ((System.currentTimeMillis() < timeout) && (isInList)) {
328       Thread.sleep(100);
329       isInList = ProtobufUtil.getOnlineRegions(
330         rs.getRSRpcServices()).contains(info);
331     }
332 
333     assertFalse("The region should not be present in online regions list.",
334       isInList);
335   }
336 
337   @Test (timeout=300000)
338   public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception {
339     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion1");
340     createTableWithDefaultConf(TABLENAME);
341 
342     HRegionInfo info = null;
343     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME));
344     List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
345     for (HRegionInfo regionInfo : onlineRegions) {
346       if (!regionInfo.isMetaTable()) {
347         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion1")) {
348           info = regionInfo;
349           try {
350             admin.closeRegionWithEncodedRegionName("sample", rs.getServerName()
351               .getServerName());
352           } catch (NotServingRegionException nsre) {
353             // expected, ignore it
354           }
355         }
356       }
357     }
358     onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
359     assertTrue("The region should be present in online regions list.",
360         onlineRegions.contains(info));
361   }
362 
363   @Test (timeout=300000)
364   public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception {
365     TableName TABLENAME =
366         TableName.valueOf("TestHBACloseRegion2");
367     createTableWithDefaultConf(TABLENAME);
368 
369     HRegionInfo info = null;
370     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
371     List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
372     for (HRegionInfo regionInfo : onlineRegions) {
373       if (!regionInfo.isMetaTable()) {
374 
375         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion2")) {
376           info = regionInfo;
377           admin.closeRegion(regionInfo.getRegionNameAsString(), rs
378               .getServerName().getServerName());
379         }
380       }
381     }
382 
383     boolean isInList = ProtobufUtil.getOnlineRegions(
384       rs.getRSRpcServices()).contains(info);
385     long timeout = System.currentTimeMillis() + 10000;
386     while ((System.currentTimeMillis() < timeout) && (isInList)) {
387       Thread.sleep(100);
388       isInList = ProtobufUtil.getOnlineRegions(
389         rs.getRSRpcServices()).contains(info);
390     }
391 
392     assertFalse("The region should not be present in online regions list.",
393       isInList);
394   }
395 
396   @Test (timeout=300000)
397   public void testCloseRegionWhenServerNameIsNull() throws Exception {
398     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion3");
399     createTableWithDefaultConf(TABLENAME);
400 
401     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME));
402 
403     try {
404       List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
405       for (HRegionInfo regionInfo : onlineRegions) {
406         if (!regionInfo.isMetaTable()) {
407           if (regionInfo.getRegionNameAsString()
408               .contains("TestHBACloseRegion3")) {
409             admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
410                 null);
411           }
412         }
413       }
414       fail("The test should throw exception if the servername passed is null.");
415     } catch (IllegalArgumentException e) {
416     }
417   }
418 
419 
420   @Test (timeout=300000)
421   public void testCloseRegionWhenServerNameIsEmpty() throws Exception {
422     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegionWhenServerNameIsEmpty");
423     createTableWithDefaultConf(TABLENAME);
424 
425     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME));
426 
427     try {
428       List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
429       for (HRegionInfo regionInfo : onlineRegions) {
430         if (!regionInfo.isMetaTable()) {
431           if (regionInfo.getRegionNameAsString()
432               .contains("TestHBACloseRegionWhenServerNameIsEmpty")) {
433             admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
434                 " ");
435           }
436         }
437       }
438       fail("The test should throw exception if the servername passed is empty.");
439     } catch (IllegalArgumentException e) {
440     }
441   }
442 
443   @Test (timeout=300000)
444   public void testCloseRegionWhenEncodedRegionNameIsNotGiven() throws Exception {
445     byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion4");
446     createTableWithDefaultConf(TABLENAME);
447 
448     HRegionInfo info = null;
449     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME));
450 
451     List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
452     for (HRegionInfo regionInfo : onlineRegions) {
453       if (!regionInfo.isMetaTable()) {
454         if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion4")) {
455           info = regionInfo;
456           try {
457             admin.closeRegionWithEncodedRegionName(regionInfo
458               .getRegionNameAsString(), rs.getServerName().getServerName());
459           } catch (NotServingRegionException nsre) {
460             // expected, ignore it.
461           }
462         }
463       }
464     }
465     onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
466     assertTrue("The region should be present in online regions list.",
467         onlineRegions.contains(info));
468   }
469 
470   private HBaseAdmin createTable(byte[] TABLENAME) throws IOException {
471 
472     Configuration config = TEST_UTIL.getConfiguration();
473     HBaseAdmin admin = new HBaseAdmin(config);
474 
475     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLENAME));
476     HColumnDescriptor hcd = new HColumnDescriptor("value");
477 
478     htd.addFamily(hcd);
479     admin.createTable(htd, null);
480     return admin;
481   }
482 
483   private void createTableWithDefaultConf(byte[] TABLENAME) throws IOException {
484     createTableWithDefaultConf(TableName.valueOf(TABLENAME));
485   }
486 
487   private void createTableWithDefaultConf(TableName TABLENAME) throws IOException {
488     HTableDescriptor htd = new HTableDescriptor(TABLENAME);
489     HColumnDescriptor hcd = new HColumnDescriptor("value");
490     htd.addFamily(hcd);
491 
492     admin.createTable(htd, null);
493   }
494 
495   /**
496    * For HBASE-2556
497    * @throws IOException
498    */
499   @Test (timeout=300000)
500   public void testGetTableRegions() throws IOException {
501 
502     final TableName tableName = TableName.valueOf("testGetTableRegions");
503 
504     int expectedRegions = 10;
505 
506     // Use 80 bit numbers to make sure we aren't limited
507     byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
508     byte [] endKey =   { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
509 
510 
511     HTableDescriptor desc = new HTableDescriptor(tableName);
512     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
513     admin.createTable(desc, startKey, endKey, expectedRegions);
514 
515     List<HRegionInfo> RegionInfos = admin.getTableRegions(tableName);
516 
517     assertEquals("Tried to create " + expectedRegions + " regions " +
518         "but only found " + RegionInfos.size(),
519         expectedRegions, RegionInfos.size());
520 
521  }
522 
523   @Test (timeout=300000)
524   public void testWALRollWriting() throws Exception {
525     setUpforLogRolling();
526     String className = this.getClass().getName();
527     StringBuilder v = new StringBuilder(className);
528     while (v.length() < 1000) {
529       v.append(className);
530     }
531     byte[] value = Bytes.toBytes(v.toString());
532     HRegionServer regionServer = startAndWriteData(TableName.valueOf("TestLogRolling"), value);
533     LOG.info("after writing there are "
534         + DefaultWALProvider.getNumRolledLogFiles(regionServer.getWAL(null)) + " log files");
535 
536     // flush all regions
537     for (Region r : regionServer.getOnlineRegionsLocalContext()) {
538       r.flush(true);
539     }
540     admin.rollWALWriter(regionServer.getServerName());
541     int count = DefaultWALProvider.getNumRolledLogFiles(regionServer.getWAL(null));
542     LOG.info("after flushing all regions and rolling logs there are " +
543         count + " log files");
544     assertTrue(("actual count: " + count), count <= 2);
545   }
546 
547   @Test (timeout=300000)
548   public void testMoveToPreviouslyAssignedRS() throws IOException, InterruptedException {
549     byte[] tableName = Bytes.toBytes("testMoveToPreviouslyAssignedRS");
550     MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
551     HMaster master = cluster.getMaster();
552     HBaseAdmin localAdmin = createTable(tableName);
553     List<HRegionInfo> tableRegions = localAdmin.getTableRegions(tableName);
554     HRegionInfo hri = tableRegions.get(0);
555     AssignmentManager am = master.getAssignmentManager();
556     assertTrue("Region " + hri.getRegionNameAsString()
557       + " should be assigned properly", am.waitForAssignment(hri));
558     ServerName server = am.getRegionStates().getRegionServerOfRegion(hri);
559     localAdmin.move(hri.getEncodedNameAsBytes(), Bytes.toBytes(server.getServerName()));
560     assertEquals("Current region server and region server before move should be same.", server,
561       am.getRegionStates().getRegionServerOfRegion(hri));
562   }
563 
564 
565   private void setUpforLogRolling() {
566     // Force a region split after every 768KB
567     TEST_UTIL.getConfiguration().setLong(HConstants.HREGION_MAX_FILESIZE,
568         768L * 1024L);
569 
570     // We roll the log after every 32 writes
571     TEST_UTIL.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32);
572 
573     TEST_UTIL.getConfiguration().setInt(
574         "hbase.regionserver.logroll.errors.tolerated", 2);
575     TEST_UTIL.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000);
576 
577     // For less frequently updated regions flush after every 2 flushes
578     TEST_UTIL.getConfiguration().setInt(
579         "hbase.hregion.memstore.optionalflushcount", 2);
580 
581     // We flush the cache after every 8192 bytes
582     TEST_UTIL.getConfiguration().setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
583         8192);
584 
585     // Increase the amount of time between client retries
586     TEST_UTIL.getConfiguration().setLong("hbase.client.pause", 10 * 1000);
587 
588     // Reduce thread wake frequency so that other threads can get
589     // a chance to run.
590     TEST_UTIL.getConfiguration().setInt(HConstants.THREAD_WAKE_FREQUENCY,
591         2 * 1000);
592 
593     /**** configuration for testLogRollOnDatanodeDeath ****/
594     // make sure log.hflush() calls syncFs() to open a pipeline
595     TEST_UTIL.getConfiguration().setBoolean("dfs.support.append", true);
596     // lower the namenode & datanode heartbeat so the namenode
597     // quickly detects datanode failures
598     TEST_UTIL.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
599     TEST_UTIL.getConfiguration().setInt("dfs.heartbeat.interval", 1);
600     // the namenode might still try to choose the recently-dead datanode
601     // for a pipeline, so try to a new pipeline multiple times
602     TEST_UTIL.getConfiguration().setInt("dfs.client.block.write.retries", 30);
603     TEST_UTIL.getConfiguration().setInt(
604         "hbase.regionserver.hlog.tolerable.lowreplication", 2);
605     TEST_UTIL.getConfiguration().setInt(
606         "hbase.regionserver.hlog.lowreplication.rolllimit", 3);
607   }
608 
609   private HRegionServer startAndWriteData(TableName tableName, byte[] value)
610   throws IOException, InterruptedException {
611     // When the hbase:meta table can be opened, the region servers are running
612     new HTable(
613       TEST_UTIL.getConfiguration(), TableName.META_TABLE_NAME).close();
614 
615     // Create the test table and open it
616     HTableDescriptor desc = new HTableDescriptor(tableName);
617     desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
618     admin.createTable(desc);
619     Table table = new HTable(TEST_UTIL.getConfiguration(), tableName);
620 
621     HRegionServer regionServer = TEST_UTIL.getRSForFirstRegionInTable(tableName);
622     for (int i = 1; i <= 256; i++) { // 256 writes should cause 8 log rolls
623       Put put = new Put(Bytes.toBytes("row" + String.format("%1$04d", i)));
624       put.add(HConstants.CATALOG_FAMILY, null, value);
625       table.put(put);
626       if (i % 32 == 0) {
627         // After every 32 writes sleep to let the log roller run
628         try {
629           Thread.sleep(2000);
630         } catch (InterruptedException e) {
631           // continue
632         }
633       }
634     }
635 
636     table.close();
637     return regionServer;
638   }
639 
640   /**
641    * HBASE-4417 checkHBaseAvailable() doesn't close zk connections
642    */
643   @Test (timeout=300000)
644   public void testCheckHBaseAvailableClosesConnection() throws Exception {
645     Configuration conf = TEST_UTIL.getConfiguration();
646 
647     int initialCount = HConnectionTestingUtility.getConnectionCount();
648     HBaseAdmin.checkHBaseAvailable(conf);
649     int finalCount = HConnectionTestingUtility.getConnectionCount();
650 
651     Assert.assertEquals(initialCount, finalCount) ;
652   }
653 
654   /**
655    * Check that we have an exception if the cluster is not there.
656    */
657   @Test (timeout=300000)
658   public void testCheckHBaseAvailableWithoutCluster() {
659     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
660 
661     // Change the ZK address to go to something not used.
662     conf.setInt(HConstants.ZOOKEEPER_CLIENT_PORT,
663       conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 9999)+10);
664 
665     int initialCount = HConnectionTestingUtility.getConnectionCount();
666 
667     long start = System.currentTimeMillis();
668     try {
669       HBaseAdmin.checkHBaseAvailable(conf);
670       assertTrue(false);
671     } catch (MasterNotRunningException ignored) {
672     } catch (ZooKeeperConnectionException ignored) {
673     } catch (ServiceException ignored) {
674     } catch (IOException ignored) {
675     }
676     long end = System.currentTimeMillis();
677 
678     int finalCount = HConnectionTestingUtility.getConnectionCount();
679 
680     Assert.assertEquals(initialCount, finalCount) ;
681 
682     LOG.info("It took "+(end-start)+" ms to find out that" +
683       " HBase was not available");
684   }
685 
686   @Test (timeout=300000)
687   public void testDisableCatalogTable() throws Exception {
688     try {
689       this.admin.disableTable(TableName.META_TABLE_NAME);
690       fail("Expected to throw ConstraintException");
691     } catch (ConstraintException e) {
692     }
693     // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table
694     // actually getting disabled by the disableTable() call.
695     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testDisableCatalogTable".getBytes()));
696     HColumnDescriptor hcd = new HColumnDescriptor("cf1".getBytes());
697     htd.addFamily(hcd);
698     TEST_UTIL.getHBaseAdmin().createTable(htd);
699   }
700 
701   @Test (timeout=300000)
702   public void testIsEnabledOrDisabledOnUnknownTable() throws Exception {
703     try {
704       admin.isTableEnabled(TableName.valueOf("unkownTable"));
705       fail("Test should fail if isTableEnabled called on unknown table.");
706     } catch (IOException e) {
707     }
708 
709     try {
710       admin.isTableDisabled(TableName.valueOf("unkownTable"));
711       fail("Test should fail if isTableDisabled called on unknown table.");
712     } catch (IOException e) {
713     }
714   }
715 
716   @Test (timeout=300000)
717   public void testGetRegion() throws Exception {
718     // We use actual HBaseAdmin instance instead of going via Admin interface in
719     // here because makes use of an internal HBA method (TODO: Fix.).
720     HBaseAdmin rawAdmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
721 
722     final TableName tableName = TableName.valueOf("testGetRegion");
723     LOG.info("Started " + tableName);
724     HTable t = TEST_UTIL.createMultiRegionTable(tableName, HConstants.CATALOG_FAMILY);
725 
726     HRegionLocation regionLocation = t.getRegionLocation("mmm");
727     HRegionInfo region = regionLocation.getRegionInfo();
728     byte[] regionName = region.getRegionName();
729     Pair<HRegionInfo, ServerName> pair = rawAdmin.getRegion(regionName);
730     assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName()));
731     pair = rawAdmin.getRegion(region.getEncodedNameAsBytes());
732     assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName()));
733   }
734 
735   @Test(timeout = 30000)
736   public void testBalancer() throws Exception {
737     boolean initialState = admin.isBalancerEnabled();
738 
739     // Start the balancer, wait for it.
740     boolean prevState = admin.setBalancerRunning(!initialState, true);
741 
742     // The previous state should be the original state we observed
743     assertEquals(initialState, prevState);
744 
745     // Current state should be opposite of the original
746     assertEquals(!initialState, admin.isBalancerEnabled());
747 
748     // Reset it back to what it was
749     prevState = admin.setBalancerRunning(initialState, true);
750 
751     // The previous state should be the opposite of the initial state
752     assertEquals(!initialState, prevState);
753     // Current state should be the original state again
754     assertEquals(initialState, admin.isBalancerEnabled());
755   }
756 
757   @Test(timeout = 30000)
758   public void testRegionNormalizer() throws Exception {
759     boolean initialState = admin.isNormalizerEnabled();
760 
761     // flip state
762     boolean prevState = admin.setNormalizerRunning(!initialState);
763 
764     // The previous state should be the original state we observed
765     assertEquals(initialState, prevState);
766 
767     // Current state should be opposite of the original
768     assertEquals(!initialState, admin.isNormalizerEnabled());
769 
770     // Reset it back to what it was
771     prevState = admin.setNormalizerRunning(initialState);
772 
773     // The previous state should be the opposite of the initial state
774     assertEquals(!initialState, prevState);
775     // Current state should be the original state again
776     assertEquals(initialState, admin.isNormalizerEnabled());
777   }
778 
779   @Test(timeout = 30000)
780   public void testAbortProcedureFail() throws Exception {
781     Random randomGenerator = new Random();
782     long procId = randomGenerator.nextLong();
783 
784     boolean abortResult = admin.abortProcedure(procId, true);
785     assertFalse(abortResult);
786   }
787 
788   @Test(timeout = 300000)
789   public void testListProcedures() throws Exception {
790     ProcedureInfo[] procList = admin.listProcedures();
791     assertTrue(procList.length >= 0);
792   }
793 }