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