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