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