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.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
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.MetaTableAccessor;
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.Waiter;
51 import org.apache.hadoop.hbase.exceptions.MergeRegionException;
52 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
53 import org.apache.hadoop.hbase.testclassification.LargeTests;
54 import org.apache.hadoop.hbase.util.Bytes;
55 import org.apache.hadoop.hbase.util.FSUtils;
56 import org.apache.hadoop.hbase.zookeeper.ZKTableStateClientSideReader;
57 import org.apache.hadoop.hbase.master.AssignmentManager;
58 import org.apache.hadoop.hbase.master.RegionState;
59 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
60 import org.apache.hadoop.hbase.protobuf.RequestConverter;
61 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
62 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
63 import org.apache.hadoop.hbase.regionserver.HRegion;
64 import org.apache.hadoop.hbase.regionserver.Store;
65 import org.apache.hadoop.hbase.regionserver.StoreFile;
66 import org.apache.hadoop.hbase.util.Pair;
67 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
68 import org.junit.After;
69 import org.junit.AfterClass;
70 import org.junit.Before;
71 import org.junit.BeforeClass;
72 import org.junit.Test;
73 import org.junit.experimental.categories.Category;
74
75 import com.google.protobuf.ServiceException;
76
77
78
79
80
81
82 @Category(LargeTests.class)
83 public class TestAdmin1 {
84 private static final Log LOG = LogFactory.getLog(TestAdmin1.class);
85 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
86 private Admin admin;
87
88 @BeforeClass
89 public static void setUpBeforeClass() throws Exception {
90 TEST_UTIL.getConfiguration().setBoolean("hbase.online.schema.update.enable", true);
91 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
92 TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
93 TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
94 TEST_UTIL.getConfiguration().setBoolean(
95 "hbase.master.enabletable.roundrobin", true);
96 TEST_UTIL.startMiniCluster(3);
97 }
98
99 @AfterClass
100 public static void tearDownAfterClass() throws Exception {
101 TEST_UTIL.shutdownMiniCluster();
102 }
103
104 @Before
105 public void setUp() throws Exception {
106 this.admin = TEST_UTIL.getHBaseAdmin();
107 }
108
109 @After
110 public void tearDown() throws Exception {
111 for (HTableDescriptor htd : this.admin.listTables()) {
112 TEST_UTIL.deleteTable(htd.getName());
113 }
114 }
115
116 @Test (timeout=300000)
117 public void testSplitFlushCompactUnknownTable() throws InterruptedException {
118 final TableName unknowntable = TableName.valueOf("fubar");
119 Exception exception = null;
120 try {
121 this.admin.compact(unknowntable);
122 } catch (IOException e) {
123 exception = e;
124 }
125 assertTrue(exception instanceof TableNotFoundException);
126
127 exception = null;
128 try {
129 this.admin.flush(unknowntable);
130 } catch (IOException e) {
131 exception = e;
132 }
133 assertTrue(exception instanceof TableNotFoundException);
134
135 exception = null;
136 try {
137 this.admin.split(unknowntable);
138 } catch (IOException e) {
139 exception = e;
140 }
141 assertTrue(exception instanceof TableNotFoundException);
142 }
143
144 @Test (timeout=300000)
145 public void testDeleteEditUnknownColumnFamilyAndOrTable() throws IOException {
146
147 final TableName nonexistentTable = TableName.valueOf("nonexistent");
148 final byte[] nonexistentColumn = Bytes.toBytes("nonexistent");
149 HColumnDescriptor nonexistentHcd = new HColumnDescriptor(nonexistentColumn);
150 Exception exception = null;
151 try {
152 this.admin.addColumn(nonexistentTable, nonexistentHcd);
153 } catch (IOException e) {
154 exception = e;
155 }
156 assertTrue(exception instanceof TableNotFoundException);
157
158 exception = null;
159 try {
160 this.admin.deleteTable(nonexistentTable);
161 } catch (IOException e) {
162 exception = e;
163 }
164 assertTrue(exception instanceof TableNotFoundException);
165
166 exception = null;
167 try {
168 this.admin.deleteColumn(nonexistentTable, nonexistentColumn);
169 } catch (IOException e) {
170 exception = e;
171 }
172 assertTrue(exception instanceof TableNotFoundException);
173
174 exception = null;
175 try {
176 this.admin.disableTable(nonexistentTable);
177 } catch (IOException e) {
178 exception = e;
179 }
180 assertTrue(exception instanceof TableNotFoundException);
181
182 exception = null;
183 try {
184 this.admin.enableTable(nonexistentTable);
185 } catch (IOException e) {
186 exception = e;
187 }
188 assertTrue(exception instanceof TableNotFoundException);
189
190 exception = null;
191 try {
192 this.admin.modifyColumn(nonexistentTable, nonexistentHcd);
193 } catch (IOException e) {
194 exception = e;
195 }
196 assertTrue(exception instanceof TableNotFoundException);
197
198 exception = null;
199 try {
200 HTableDescriptor htd = new HTableDescriptor(nonexistentTable);
201 htd.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
202 this.admin.modifyTable(htd.getTableName(), htd);
203 } catch (IOException e) {
204 exception = e;
205 }
206 assertTrue(exception instanceof TableNotFoundException);
207
208
209
210 final TableName tableName =
211 TableName.valueOf("testDeleteEditUnknownColumnFamilyAndOrTable" + System.currentTimeMillis());
212 HTableDescriptor htd = new HTableDescriptor(tableName);
213 htd.addFamily(new HColumnDescriptor("cf"));
214 this.admin.createTable(htd);
215 try {
216 exception = null;
217 try {
218 this.admin.deleteColumn(htd.getTableName(), nonexistentHcd.getName());
219 } catch (IOException e) {
220 exception = e;
221 }
222 assertNotNull(exception);
223 assertTrue("found=" + exception.getClass().getName(),
224 exception instanceof InvalidFamilyOperationException);
225
226 exception = null;
227 try {
228 this.admin.modifyColumn(htd.getTableName(), nonexistentHcd);
229 } catch (IOException e) {
230 exception = e;
231 }
232 assertNotNull(exception);
233 assertTrue("found=" + exception.getClass().getName(),
234 exception instanceof InvalidFamilyOperationException);
235 } finally {
236 this.admin.disableTable(tableName);
237 this.admin.deleteTable(tableName);
238 }
239 }
240
241 @Test (timeout=300000)
242 public void testDisableAndEnableTable() throws IOException {
243 final byte [] row = Bytes.toBytes("row");
244 final byte [] qualifier = Bytes.toBytes("qualifier");
245 final byte [] value = Bytes.toBytes("value");
246 final TableName table = TableName.valueOf("testDisableAndEnableTable");
247 Table ht = TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
248 Put put = new Put(row);
249 put.add(HConstants.CATALOG_FAMILY, qualifier, value);
250 ht.put(put);
251 Get get = new Get(row);
252 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
253 ht.get(get);
254
255 this.admin.disableTable(ht.getName());
256 assertTrue("Table must be disabled.", TEST_UTIL.getHBaseCluster()
257 .getMaster().getAssignmentManager().getTableStateManager().isTableState(
258 ht.getName(), ZooKeeperProtos.Table.State.DISABLED));
259
260
261 get = new Get(row);
262 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
263 boolean ok = false;
264 try {
265 ht.get(get);
266 } catch (TableNotEnabledException e) {
267 ok = true;
268 }
269 ok = false;
270
271 Scan scan = new Scan();
272 try {
273 ResultScanner scanner = ht.getScanner(scan);
274 Result res = null;
275 do {
276 res = scanner.next();
277 } while (res != null);
278 } catch (TableNotEnabledException e) {
279 ok = true;
280 }
281 assertTrue(ok);
282 this.admin.enableTable(table);
283 assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
284 .getMaster().getAssignmentManager().getTableStateManager().isTableState(
285 ht.getName(), ZooKeeperProtos.Table.State.ENABLED));
286
287
288 try {
289 ht.get(get);
290 } catch (RetriesExhaustedException e) {
291 ok = false;
292 }
293 assertTrue(ok);
294 ht.close();
295 }
296
297 @Test (timeout=300000)
298 public void testDisableAndEnableTables() throws IOException {
299 final byte [] row = Bytes.toBytes("row");
300 final byte [] qualifier = Bytes.toBytes("qualifier");
301 final byte [] value = Bytes.toBytes("value");
302 final TableName table1 = TableName.valueOf("testDisableAndEnableTable1");
303 final TableName table2 = TableName.valueOf("testDisableAndEnableTable2");
304 Table ht1 = TEST_UTIL.createTable(table1, HConstants.CATALOG_FAMILY);
305 Table ht2 = TEST_UTIL.createTable(table2, HConstants.CATALOG_FAMILY);
306 Put put = new Put(row);
307 put.add(HConstants.CATALOG_FAMILY, qualifier, value);
308 ht1.put(put);
309 ht2.put(put);
310 Get get = new Get(row);
311 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
312 ht1.get(get);
313 ht2.get(get);
314
315 this.admin.disableTables("testDisableAndEnableTable.*");
316
317
318 get = new Get(row);
319 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
320 boolean ok = false;
321 try {
322 ht1.get(get);
323 ht2.get(get);
324 } catch (org.apache.hadoop.hbase.DoNotRetryIOException e) {
325 ok = true;
326 }
327
328 assertTrue(ok);
329 this.admin.enableTables("testDisableAndEnableTable.*");
330
331
332 try {
333 ht1.get(get);
334 } catch (IOException e) {
335 ok = false;
336 }
337 try {
338 ht2.get(get);
339 } catch (IOException e) {
340 ok = false;
341 }
342 assertTrue(ok);
343
344 ht1.close();
345 ht2.close();
346 }
347
348 @Test (timeout=300000)
349 public void testCreateTable() throws IOException {
350 HTableDescriptor [] tables = admin.listTables();
351 int numTables = tables.length;
352 TEST_UTIL.createTable(TableName.valueOf("testCreateTable"), HConstants.CATALOG_FAMILY).close();
353 tables = this.admin.listTables();
354 assertEquals(numTables + 1, tables.length);
355 assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster()
356 .getMaster().getAssignmentManager().getTableStateManager().isTableState(
357 TableName.valueOf("testCreateTable"), ZooKeeperProtos.Table.State.ENABLED));
358 }
359
360 @Test (timeout=300000)
361 public void testTruncateTable() throws IOException {
362 testTruncateTable(TableName.valueOf("testTruncateTable"), false);
363 }
364
365 @Test (timeout=300000)
366 public void testTruncateTablePreservingSplits() throws IOException {
367 testTruncateTable(TableName.valueOf("testTruncateTablePreservingSplits"), true);
368 }
369
370 private void testTruncateTable(final TableName tableName, boolean preserveSplits)
371 throws IOException {
372 byte[][] splitKeys = new byte[2][];
373 splitKeys[0] = Bytes.toBytes(4);
374 splitKeys[1] = Bytes.toBytes(8);
375
376
377 HTable table = TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY, splitKeys);
378 try {
379 TEST_UTIL.loadNumericRows(table, HConstants.CATALOG_FAMILY, 0, 10);
380 assertEquals(10, TEST_UTIL.countRows(table));
381 } finally {
382 table.close();
383 }
384 assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
385
386
387 this.admin.disableTable(tableName);
388 this.admin.truncateTable(tableName, preserveSplits);
389 table = new HTable(TEST_UTIL.getConfiguration(), tableName);
390 try {
391 assertEquals(0, TEST_UTIL.countRows(table));
392 } finally {
393 table.close();
394 }
395 if (preserveSplits) {
396 assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
397 } else {
398 assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(tableName).size());
399 }
400 }
401
402 @Test (timeout=300000)
403 public void testGetTableDescriptor() throws IOException {
404 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
405 HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
406 HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
407 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("myTestTable"));
408 htd.addFamily(fam1);
409 htd.addFamily(fam2);
410 htd.addFamily(fam3);
411 this.admin.createTable(htd);
412 Table table = new HTable(TEST_UTIL.getConfiguration(), htd.getTableName());
413 HTableDescriptor confirmedHtd = table.getTableDescriptor();
414 assertEquals(htd.compareTo(confirmedHtd), 0);
415 table.close();
416 }
417
418 @Test (timeout=300000)
419 public void testCompactionTimestamps() throws Exception {
420 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
421 TableName tableName = TableName.valueOf("testCompactionTimestampsTable");
422 HTableDescriptor htd = new HTableDescriptor(tableName);
423 htd.addFamily(fam1);
424 this.admin.createTable(htd);
425 HTable table = (HTable)TEST_UTIL.getConnection().getTable(htd.getTableName());
426 long ts = this.admin.getLastMajorCompactionTimestamp(tableName);
427 assertEquals(0, ts);
428 Put p = new Put(Bytes.toBytes("row1"));
429 p.add(Bytes.toBytes("fam1"), Bytes.toBytes("fam1"), Bytes.toBytes("fam1"));
430 table.put(p);
431 ts = this.admin.getLastMajorCompactionTimestamp(tableName);
432
433 assertEquals(0, ts);
434
435 this.admin.flush(tableName);
436 ts = this.admin.getLastMajorCompactionTimestamp(tableName);
437
438 assertEquals(0, ts);
439
440 byte[] regionName =
441 table.getRegionLocator().getAllRegionLocations().get(0).getRegionInfo().getRegionName();
442 long ts1 = this.admin.getLastMajorCompactionTimestampForRegion(regionName);
443 assertEquals(ts, ts1);
444 p = new Put(Bytes.toBytes("row2"));
445 p.add(Bytes.toBytes("fam1"), Bytes.toBytes("fam1"), Bytes.toBytes("fam1"));
446 table.put(p);
447 this.admin.flush(tableName);
448 ts = this.admin.getLastMajorCompactionTimestamp(tableName);
449
450 assertEquals(ts1, ts);
451
452 TEST_UTIL.compact(tableName, true);
453 table.put(p);
454
455 this.admin.flush(tableName);
456 ts = this.admin.getLastMajorCompactionTimestamp(tableName);
457
458 assertTrue(ts > ts1);
459
460
461 ts1 = this.admin.getLastMajorCompactionTimestampForRegion(regionName);
462 assertEquals(ts, ts1);
463 table.put(p);
464 this.admin.flush(tableName);
465 ts = this.admin.getLastMajorCompactionTimestamp(tableName);
466 assertEquals(ts, ts1);
467 table.close();
468 }
469
470 @Test (timeout=300000)
471 public void testHColumnValidName() {
472 boolean exceptionThrown;
473 try {
474 new HColumnDescriptor("\\test\\abc");
475 } catch(IllegalArgumentException iae) {
476 exceptionThrown = true;
477 assertTrue(exceptionThrown);
478 }
479 }
480
481
482
483
484
485
486 @Test (timeout=300000)
487 public void testOnlineChangeTableSchema() throws IOException, InterruptedException {
488 final TableName tableName =
489 TableName.valueOf("changeTableSchemaOnline");
490 TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
491 "hbase.online.schema.update.enable", true);
492 HTableDescriptor [] tables = admin.listTables();
493 int numTables = tables.length;
494 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
495 tables = this.admin.listTables();
496 assertEquals(numTables + 1, tables.length);
497
498
499 HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
500
501 HTableDescriptor copy = new HTableDescriptor(htd);
502 assertTrue(htd.equals(copy));
503
504 long newFlushSize = htd.getMemStoreFlushSize() / 2;
505 if (newFlushSize <=0) {
506 newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
507 }
508 copy.setMemStoreFlushSize(newFlushSize);
509 final String key = "anyoldkey";
510 assertTrue(htd.getValue(key) == null);
511 copy.setValue(key, key);
512 boolean expectedException = false;
513 try {
514 admin.modifyTable(tableName, copy);
515 } catch (TableNotDisabledException re) {
516 expectedException = true;
517 }
518 assertFalse(expectedException);
519 HTableDescriptor modifiedHtd = this.admin.getTableDescriptor(tableName);
520 assertFalse(htd.equals(modifiedHtd));
521 assertTrue(copy.equals(modifiedHtd));
522 assertEquals(newFlushSize, modifiedHtd.getMemStoreFlushSize());
523 assertEquals(key, modifiedHtd.getValue(key));
524
525
526 int countOfFamilies = modifiedHtd.getFamilies().size();
527 assertTrue(countOfFamilies > 0);
528 HColumnDescriptor hcd = modifiedHtd.getFamilies().iterator().next();
529 int maxversions = hcd.getMaxVersions();
530 final int newMaxVersions = maxversions + 1;
531 hcd.setMaxVersions(newMaxVersions);
532 final byte [] hcdName = hcd.getName();
533 expectedException = false;
534 try {
535 this.admin.modifyColumn(tableName, hcd);
536 } catch (TableNotDisabledException re) {
537 expectedException = true;
538 }
539 assertFalse(expectedException);
540 modifiedHtd = this.admin.getTableDescriptor(tableName);
541 HColumnDescriptor modifiedHcd = modifiedHtd.getFamily(hcdName);
542 assertEquals(newMaxVersions, modifiedHcd.getMaxVersions());
543
544
545 assertFalse(this.admin.isTableDisabled(tableName));
546 final String xtracolName = "xtracol";
547 HColumnDescriptor xtracol = new HColumnDescriptor(xtracolName);
548 xtracol.setValue(xtracolName, xtracolName);
549 expectedException = false;
550 try {
551 this.admin.addColumn(tableName, xtracol);
552 } catch (TableNotDisabledException re) {
553 expectedException = true;
554 }
555
556 assertFalse(expectedException);
557 modifiedHtd = this.admin.getTableDescriptor(tableName);
558 hcd = modifiedHtd.getFamily(xtracol.getName());
559 assertTrue(hcd != null);
560 assertTrue(hcd.getValue(xtracolName).equals(xtracolName));
561
562
563 this.admin.deleteColumn(tableName, xtracol.getName());
564 modifiedHtd = this.admin.getTableDescriptor(tableName);
565 hcd = modifiedHtd.getFamily(xtracol.getName());
566 assertTrue(hcd == null);
567
568
569 this.admin.disableTable(tableName);
570 this.admin.deleteTable(tableName);
571 this.admin.listTables();
572 assertFalse(this.admin.tableExists(tableName));
573 }
574
575 @Test (timeout=300000)
576 public void testShouldFailOnlineSchemaUpdateIfOnlineSchemaIsNotEnabled()
577 throws Exception {
578 final TableName tableName = TableName.valueOf("changeTableSchemaOnlineFailure");
579 TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
580 "hbase.online.schema.update.enable", false);
581 HTableDescriptor[] tables = admin.listTables();
582 int numTables = tables.length;
583 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
584 tables = this.admin.listTables();
585 assertEquals(numTables + 1, tables.length);
586
587
588 HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
589
590 HTableDescriptor copy = new HTableDescriptor(htd);
591 assertTrue(htd.equals(copy));
592
593 long newFlushSize = htd.getMemStoreFlushSize() / 2;
594 if (newFlushSize <=0) {
595 newFlushSize = HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE / 2;
596 }
597 copy.setMemStoreFlushSize(newFlushSize);
598 final String key = "anyoldkey";
599 assertTrue(htd.getValue(key) == null);
600 copy.setValue(key, key);
601 boolean expectedException = false;
602 try {
603 admin.modifyTable(tableName, copy);
604 } catch (TableNotDisabledException re) {
605 expectedException = true;
606 }
607 assertTrue("Online schema update should not happen.", expectedException);
608
609
610 TEST_UTIL.getMiniHBaseCluster().getMaster().getConfiguration().setBoolean(
611 "hbase.online.schema.update.enable", true);
612 }
613
614 @SuppressWarnings("deprecation")
615 protected void verifyRoundRobinDistribution(HTable ht, int expectedRegions) throws IOException {
616 int numRS = ht.getConnection().getCurrentNrHRS();
617 Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
618 Map<ServerName, List<HRegionInfo>> server2Regions = new HashMap<ServerName, List<HRegionInfo>>();
619 for (Map.Entry<HRegionInfo, ServerName> entry : regions.entrySet()) {
620 ServerName server = entry.getValue();
621 List<HRegionInfo> regs = server2Regions.get(server);
622 if (regs == null) {
623 regs = new ArrayList<HRegionInfo>();
624 server2Regions.put(server, regs);
625 }
626 regs.add(entry.getKey());
627 }
628 float average = (float) expectedRegions/numRS;
629 int min = (int)Math.floor(average);
630 int max = (int)Math.ceil(average);
631 for (List<HRegionInfo> regionList : server2Regions.values()) {
632 assertTrue(regionList.size() == min || regionList.size() == max);
633 }
634 }
635
636 @Test (timeout=300000)
637 public void testCreateTableNumberOfRegions() throws IOException, InterruptedException {
638 TableName tableName = TableName.valueOf("testCreateTableNumberOfRegions");
639 HTableDescriptor desc = new HTableDescriptor(tableName);
640 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
641 admin.createTable(desc);
642 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
643 Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
644 assertEquals("Table should have only 1 region", 1, regions.size());
645 ht.close();
646
647 TableName TABLE_2 = TableName.valueOf(tableName.getNameAsString() + "_2");
648 desc = new HTableDescriptor(TABLE_2);
649 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
650 admin.createTable(desc, new byte[][]{new byte[]{42}});
651 HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
652 regions = ht2.getRegionLocations();
653 assertEquals("Table should have only 2 region", 2, regions.size());
654 ht2.close();
655
656 TableName TABLE_3 = TableName.valueOf(tableName.getNameAsString() + "_3");
657 desc = new HTableDescriptor(TABLE_3);
658 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
659 admin.createTable(desc, "a".getBytes(), "z".getBytes(), 3);
660 HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
661 regions = ht3.getRegionLocations();
662 assertEquals("Table should have only 3 region", 3, regions.size());
663 ht3.close();
664
665 TableName TABLE_4 = TableName.valueOf(tableName.getNameAsString() + "_4");
666 desc = new HTableDescriptor(TABLE_4);
667 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
668 try {
669 admin.createTable(desc, "a".getBytes(), "z".getBytes(), 2);
670 fail("Should not be able to create a table with only 2 regions using this API.");
671 } catch (IllegalArgumentException eae) {
672
673 }
674
675 TableName TABLE_5 = TableName.valueOf(tableName.getNameAsString() + "_5");
676 desc = new HTableDescriptor(TABLE_5);
677 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
678 admin.createTable(desc, new byte[] {1}, new byte[] {127}, 16);
679 HTable ht5 = new HTable(TEST_UTIL.getConfiguration(), TABLE_5);
680 regions = ht5.getRegionLocations();
681 assertEquals("Table should have 16 region", 16, regions.size());
682 ht5.close();
683 }
684
685 @Test (timeout=300000)
686 public void testCreateTableWithRegions() throws IOException, InterruptedException {
687
688 TableName tableName = TableName.valueOf("testCreateTableWithRegions");
689
690 byte [][] splitKeys = {
691 new byte [] { 1, 1, 1 },
692 new byte [] { 2, 2, 2 },
693 new byte [] { 3, 3, 3 },
694 new byte [] { 4, 4, 4 },
695 new byte [] { 5, 5, 5 },
696 new byte [] { 6, 6, 6 },
697 new byte [] { 7, 7, 7 },
698 new byte [] { 8, 8, 8 },
699 new byte [] { 9, 9, 9 },
700 };
701 int expectedRegions = splitKeys.length + 1;
702
703 HTableDescriptor desc = new HTableDescriptor(tableName);
704 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
705 admin.createTable(desc, splitKeys);
706
707 boolean tableAvailable = admin.isTableAvailable(tableName, splitKeys);
708 assertTrue("Table should be created with splitKyes + 1 rows in META", tableAvailable);
709
710 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
711 Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
712 assertEquals("Tried to create " + expectedRegions + " regions " +
713 "but only found " + regions.size(),
714 expectedRegions, regions.size());
715 System.err.println("Found " + regions.size() + " regions");
716
717 Iterator<HRegionInfo> hris = regions.keySet().iterator();
718 HRegionInfo hri = hris.next();
719 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
720 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
721 hri = hris.next();
722 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
723 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
724 hri = hris.next();
725 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
726 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
727 hri = hris.next();
728 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
729 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
730 hri = hris.next();
731 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
732 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
733 hri = hris.next();
734 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
735 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
736 hri = hris.next();
737 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
738 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
739 hri = hris.next();
740 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
741 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
742 hri = hris.next();
743 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
744 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
745 hri = hris.next();
746 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
747 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
748
749 verifyRoundRobinDistribution(ht, expectedRegions);
750 ht.close();
751
752
753
754
755 byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
756 byte [] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
757
758
759
760
761 expectedRegions = 10;
762
763 TableName TABLE_2 = TableName.valueOf(tableName.getNameAsString() + "_2");
764
765 desc = new HTableDescriptor(TABLE_2);
766 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
767 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
768 admin.createTable(desc, startKey, endKey, expectedRegions);
769
770 HTable ht2 = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
771 regions = ht2.getRegionLocations();
772 assertEquals("Tried to create " + expectedRegions + " regions " +
773 "but only found " + regions.size(),
774 expectedRegions, regions.size());
775 System.err.println("Found " + regions.size() + " regions");
776
777 hris = regions.keySet().iterator();
778 hri = hris.next();
779 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
780 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
781 hri = hris.next();
782 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
783 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
784 hri = hris.next();
785 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
786 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
787 hri = hris.next();
788 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
789 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
790 hri = hris.next();
791 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
792 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
793 hri = hris.next();
794 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
795 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
796 hri = hris.next();
797 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
798 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
799 hri = hris.next();
800 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
801 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
802 hri = hris.next();
803 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
804 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
805 hri = hris.next();
806 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
807 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
808
809 verifyRoundRobinDistribution(ht2, expectedRegions);
810 ht2.close();
811
812
813
814 startKey = new byte [] { 0, 0, 0, 0, 0, 0 };
815 endKey = new byte [] { 1, 0, 0, 0, 0, 0 };
816
817 expectedRegions = 5;
818
819 TableName TABLE_3 = TableName.valueOf(tableName.getNameAsString() + "_3");
820
821 desc = new HTableDescriptor(TABLE_3);
822 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
823 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
824 admin.createTable(desc, startKey, endKey, expectedRegions);
825
826
827 HTable ht3 = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
828 regions = ht3.getRegionLocations();
829 assertEquals("Tried to create " + expectedRegions + " regions " +
830 "but only found " + regions.size(),
831 expectedRegions, regions.size());
832 System.err.println("Found " + regions.size() + " regions");
833
834 verifyRoundRobinDistribution(ht3, expectedRegions);
835 ht3.close();
836
837
838
839 splitKeys = new byte [][] {
840 new byte [] { 1, 1, 1 },
841 new byte [] { 2, 2, 2 },
842 new byte [] { 3, 3, 3 },
843 new byte [] { 2, 2, 2 }
844 };
845
846 TableName TABLE_4 = TableName.valueOf(tableName.getNameAsString() + "_4");
847 desc = new HTableDescriptor(TABLE_4);
848 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
849 Admin ladmin = new HBaseAdmin(TEST_UTIL.getConfiguration());
850 try {
851 ladmin.createTable(desc, splitKeys);
852 assertTrue("Should not be able to create this table because of " +
853 "duplicate split keys", false);
854 } catch(IllegalArgumentException iae) {
855
856 }
857 ladmin.close();
858 }
859
860 @Test (timeout=300000)
861 public void testTableAvailableWithRandomSplitKeys() throws Exception {
862 TableName tableName = TableName.valueOf("testTableAvailableWithRandomSplitKeys");
863 HTableDescriptor desc = new HTableDescriptor(tableName);
864 desc.addFamily(new HColumnDescriptor("col"));
865 byte[][] splitKeys = new byte[1][];
866 splitKeys = new byte [][] {
867 new byte [] { 1, 1, 1 },
868 new byte [] { 2, 2, 2 }
869 };
870 admin.createTable(desc);
871 boolean tableAvailable = admin.isTableAvailable(tableName, splitKeys);
872 assertFalse("Table should be created with 1 row in META", tableAvailable);
873 }
874
875 @Test (timeout=300000)
876 public void testCreateTableWithOnlyEmptyStartRow() throws IOException {
877 byte[] tableName = Bytes.toBytes("testCreateTableWithOnlyEmptyStartRow");
878 byte[][] splitKeys = new byte[1][];
879 splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
880 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
881 desc.addFamily(new HColumnDescriptor("col"));
882 try {
883 admin.createTable(desc, splitKeys);
884 fail("Test case should fail as empty split key is passed.");
885 } catch (IllegalArgumentException e) {
886 }
887 }
888
889 @Test (timeout=300000)
890 public void testCreateTableWithEmptyRowInTheSplitKeys() throws IOException{
891 byte[] tableName = Bytes.toBytes("testCreateTableWithEmptyRowInTheSplitKeys");
892 byte[][] splitKeys = new byte[3][];
893 splitKeys[0] = "region1".getBytes();
894 splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY;
895 splitKeys[2] = "region2".getBytes();
896 HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
897 desc.addFamily(new HColumnDescriptor("col"));
898 try {
899 admin.createTable(desc, splitKeys);
900 fail("Test case should fail as empty split key is passed.");
901 } catch (IllegalArgumentException e) {
902 LOG.info("Expected ", e);
903 }
904 }
905
906 @Test (timeout=120000)
907 public void testTableExist() throws IOException {
908 final TableName table = TableName.valueOf("testTableExist");
909 boolean exist;
910 exist = this.admin.tableExists(table);
911 assertEquals(false, exist);
912 TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
913 exist = this.admin.tableExists(table);
914 assertEquals(true, exist);
915 }
916
917
918
919
920
921
922 @Test (timeout=400000)
923 public void testForceSplit() throws Exception {
924 byte[][] familyNames = new byte[][] { Bytes.toBytes("cf") };
925 int[] rowCounts = new int[] { 6000 };
926 int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
927 int blockSize = 256;
928 splitTest(null, familyNames, rowCounts, numVersions, blockSize);
929
930 byte[] splitKey = Bytes.toBytes(3500);
931 splitTest(splitKey, familyNames, rowCounts, numVersions, blockSize);
932 }
933
934
935
936
937
938
939 @Test (timeout=300000)
940 public void testEnableTableRetainAssignment() throws IOException {
941 final TableName tableName = TableName.valueOf("testEnableTableAssignment");
942 byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 },
943 new byte[] { 3, 3, 3 }, new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 },
944 new byte[] { 6, 6, 6 }, new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 },
945 new byte[] { 9, 9, 9 } };
946 int expectedRegions = splitKeys.length + 1;
947 HTableDescriptor desc = new HTableDescriptor(tableName);
948 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
949 admin.createTable(desc, splitKeys);
950 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
951 Map<HRegionInfo, ServerName> regions = ht.getRegionLocations();
952 assertEquals("Tried to create " + expectedRegions + " regions "
953 + "but only found " + regions.size(), expectedRegions, regions.size());
954
955 admin.disableTable(tableName);
956
957 admin.enableTable(tableName);
958 Map<HRegionInfo, ServerName> regions2 = ht.getRegionLocations();
959
960
961 assertEquals(regions.size(), regions2.size());
962 for (Map.Entry<HRegionInfo, ServerName> entry : regions.entrySet()) {
963 assertEquals(regions2.get(entry.getKey()), entry.getValue());
964 }
965 }
966
967
968
969
970
971
972
973 @Test (timeout=800000)
974 public void testForceSplitMultiFamily() throws Exception {
975 int numVersions = HColumnDescriptor.DEFAULT_VERSIONS;
976
977
978
979
980 int blockSize = 256;
981 byte[][] familyNames = new byte[][] { Bytes.toBytes("cf1"),
982 Bytes.toBytes("cf2") };
983
984
985 int[] rowCounts = new int[] { 6000, 1 };
986 splitTest(null, familyNames, rowCounts, numVersions, blockSize);
987
988 rowCounts = new int[] { 1, 6000 };
989 splitTest(null, familyNames, rowCounts, numVersions, blockSize);
990
991
992
993 rowCounts = new int[] { 6000, 300 };
994 splitTest(null, familyNames, rowCounts, numVersions, blockSize);
995
996 rowCounts = new int[] { 300, 6000 };
997 splitTest(null, familyNames, rowCounts, numVersions, blockSize);
998
999 }
1000
1001 void splitTest(byte[] splitPoint, byte[][] familyNames, int[] rowCounts,
1002 int numVersions, int blockSize) throws Exception {
1003 TableName tableName = TableName.valueOf("testForceSplit");
1004 StringBuilder sb = new StringBuilder();
1005
1006 for (int i = 0; i < rowCounts.length; i++) {
1007 sb.append("_").append(Integer.toString(rowCounts[i]));
1008 }
1009 assertFalse(admin.tableExists(tableName));
1010 final HTable table = TEST_UTIL.createTable(tableName, familyNames,
1011 numVersions, blockSize);
1012
1013 int rowCount = 0;
1014 byte[] q = new byte[0];
1015
1016
1017
1018 for (int index = 0; index < familyNames.length; index++) {
1019 ArrayList<Put> puts = new ArrayList<Put>(rowCounts[index]);
1020 for (int i = 0; i < rowCounts[index]; i++) {
1021 byte[] k = Bytes.toBytes(i);
1022 Put put = new Put(k);
1023 put.add(familyNames[index], q, k);
1024 puts.add(put);
1025 }
1026 table.put(puts);
1027
1028 if ( rowCount < rowCounts[index] ) {
1029 rowCount = rowCounts[index];
1030 }
1031 }
1032
1033
1034 Map<HRegionInfo, ServerName> m = table.getRegionLocations();
1035 LOG.info("Initial regions (" + m.size() + "): " + m);
1036 assertTrue(m.size() == 1);
1037
1038
1039 Scan scan = new Scan();
1040 ResultScanner scanner = table.getScanner(scan);
1041 int rows = 0;
1042 for(@SuppressWarnings("unused") Result result : scanner) {
1043 rows++;
1044 }
1045 scanner.close();
1046 assertEquals(rowCount, rows);
1047
1048
1049 scan = new Scan();
1050 scanner = table.getScanner(scan);
1051
1052 scanner.next();
1053
1054
1055 this.admin.split(tableName, splitPoint);
1056
1057 final AtomicInteger count = new AtomicInteger(0);
1058 Thread t = new Thread("CheckForSplit") {
1059 @Override
1060 public void run() {
1061 for (int i = 0; i < 45; i++) {
1062 try {
1063 sleep(1000);
1064 } catch (InterruptedException e) {
1065 continue;
1066 }
1067
1068 Map<HRegionInfo, ServerName> regions = null;
1069 try {
1070 regions = table.getRegionLocations();
1071 } catch (IOException e) {
1072 e.printStackTrace();
1073 }
1074 if (regions == null) continue;
1075 count.set(regions.size());
1076 if (count.get() >= 2) {
1077 LOG.info("Found: " + regions);
1078 break;
1079 }
1080 LOG.debug("Cycle waiting on split");
1081 }
1082 LOG.debug("CheckForSplit thread exited, current region count: " + count.get());
1083 }
1084 };
1085 t.setPriority(Thread.NORM_PRIORITY - 2);
1086 t.start();
1087 t.join();
1088
1089
1090 rows = 1;
1091 for (@SuppressWarnings("unused") Result result : scanner) {
1092 rows++;
1093 if (rows > rowCount) {
1094 scanner.close();
1095 assertTrue("Scanned more than expected (" + rowCount + ")", false);
1096 }
1097 }
1098 scanner.close();
1099 assertEquals(rowCount, rows);
1100
1101 Map<HRegionInfo, ServerName> regions = null;
1102 try {
1103 regions = table.getRegionLocations();
1104 } catch (IOException e) {
1105 e.printStackTrace();
1106 }
1107 assertNotNull(regions);
1108 assertEquals(2, regions.size());
1109 Set<HRegionInfo> hRegionInfos = regions.keySet();
1110 HRegionInfo[] r = hRegionInfos.toArray(new HRegionInfo[hRegionInfos.size()]);
1111 if (splitPoint != null) {
1112
1113 assertEquals(Bytes.toString(splitPoint),
1114 Bytes.toString(r[0].getEndKey()));
1115 assertEquals(Bytes.toString(splitPoint),
1116 Bytes.toString(r[1].getStartKey()));
1117 LOG.debug("Properly split on " + Bytes.toString(splitPoint));
1118 } else {
1119 if (familyNames.length > 1) {
1120 int splitKey = Bytes.toInt(r[0].getEndKey());
1121
1122
1123 int deltaForLargestFamily = Math.abs(rowCount/2 - splitKey);
1124 LOG.debug("SplitKey=" + splitKey + "&deltaForLargestFamily=" + deltaForLargestFamily +
1125 ", r=" + r[0]);
1126 for (int index = 0; index < familyNames.length; index++) {
1127 int delta = Math.abs(rowCounts[index]/2 - splitKey);
1128 if (delta < deltaForLargestFamily) {
1129 assertTrue("Delta " + delta + " for family " + index
1130 + " should be at least deltaForLargestFamily " + deltaForLargestFamily,
1131 false);
1132 }
1133 }
1134 }
1135 }
1136 TEST_UTIL.deleteTable(tableName);
1137 table.close();
1138 }
1139
1140 @Test
1141 public void testSplitAndMergeWithReplicaTable() throws Exception {
1142
1143
1144
1145
1146 TableName tableName = TableName.valueOf("testSplitAndMergeWithReplicaTable");
1147 byte[] cf = "f".getBytes();
1148 createReplicaTable(tableName, cf);
1149 List<HRegion> oldRegions;
1150 do {
1151 oldRegions = TEST_UTIL.getHBaseCluster().getRegions(tableName);
1152 Thread.sleep(10);
1153 } while (oldRegions.size() != 9);
1154
1155 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
1156 List<Put> puts = new ArrayList<Put>();
1157 byte[] qualifier = "c".getBytes();
1158 Put put = new Put(new byte[]{(byte)'1'});
1159 put.add(cf, qualifier, "100".getBytes());
1160 puts.add(put);
1161 put = new Put(new byte[]{(byte)'6'});
1162 put.add(cf, qualifier, "100".getBytes());
1163 puts.add(put);
1164 put = new Put(new byte[]{(byte)'8'});
1165 put.add(cf, qualifier, "100".getBytes());
1166 puts.add(put);
1167 ht.put(puts);
1168 ht.flushCommits();
1169 ht.close();
1170 List<Pair<HRegionInfo, ServerName>> regions =
1171 MetaTableAccessor.getTableRegionsAndLocations(TEST_UTIL.getZooKeeperWatcher(),
1172 TEST_UTIL.getConnection(), tableName);
1173 boolean gotException = false;
1174
1175
1176 try {
1177 TEST_UTIL.getHBaseAdmin().split(regions.get(1).getFirst().getRegionName());
1178 } catch (IllegalArgumentException ex) {
1179 gotException = true;
1180 }
1181 assertTrue(gotException);
1182 gotException = false;
1183
1184
1185
1186 try {
1187 TEST_UTIL.getHBaseAdmin().split(regions.get(1).getSecond(), regions.get(1).getFirst(),
1188 new byte[]{(byte)'1'});
1189 } catch (IOException ex) {
1190 gotException = true;
1191 }
1192 assertTrue(gotException);
1193 gotException = false;
1194
1195 try {
1196 TEST_UTIL.getHBaseAdmin().mergeRegions(regions.get(1).getFirst().getEncodedNameAsBytes(),
1197 regions.get(2).getFirst().getEncodedNameAsBytes(), true);
1198 } catch (IllegalArgumentException m) {
1199 gotException = true;
1200 }
1201 assertTrue(gotException);
1202
1203 try {
1204 DispatchMergingRegionsRequest request = RequestConverter
1205 .buildDispatchMergingRegionsRequest(regions.get(1).getFirst().getEncodedNameAsBytes(),
1206 regions.get(2).getFirst().getEncodedNameAsBytes(), true);
1207 TEST_UTIL.getHBaseAdmin().getConnection().getMaster().dispatchMergingRegions(null, request);
1208 } catch (ServiceException m) {
1209 Throwable t = m.getCause();
1210 do {
1211 if (t instanceof MergeRegionException) {
1212 gotException = true;
1213 break;
1214 }
1215 t = t.getCause();
1216 } while (t != null);
1217 }
1218 assertTrue(gotException);
1219 gotException = false;
1220
1221
1222 if (!regions.get(2).getSecond().equals(regions.get(1).getSecond())) {
1223 TEST_UTIL.moveRegionAndWait(regions.get(2).getFirst(), regions.get(1).getSecond());
1224 }
1225 try {
1226 AdminService.BlockingInterface admin = TEST_UTIL.getHBaseAdmin().getConnection()
1227 .getAdmin(regions.get(1).getSecond());
1228 ProtobufUtil.mergeRegions(null, admin, regions.get(1).getFirst(), regions.get(2).getFirst(),
1229 true, null);
1230 } catch (MergeRegionException mm) {
1231 gotException = true;
1232 }
1233 assertTrue(gotException);
1234 }
1235
1236
1237
1238
1239
1240 @Test
1241 public void testRegionStateCleanupFromAMMemoryAfterRegionSplitAndMerge() throws Exception {
1242 final TableName tableName =
1243 TableName.valueOf("testRegionStateCleanupFromAMMemoryAfterRegionSplitAndMerge");
1244 createReplicaTable(tableName, "f".getBytes());
1245 final int regionReplication = admin.getTableDescriptor(tableName).getRegionReplication();
1246
1247 List<Pair<HRegionInfo, ServerName>> regions = MetaTableAccessor.getTableRegionsAndLocations(
1248 TEST_UTIL.getZooKeeperWatcher(), TEST_UTIL.getConnection(), tableName);
1249 assertEquals(9, regions.size());
1250 final int primaryRegionCount = regions.size() / regionReplication;
1251
1252 final AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager();
1253 List<HRegionInfo> splitRegions =
1254 am.getRegionStates().getRegionByStateOfTable(tableName).get(RegionState.State.SPLIT);
1255 assertEquals(0, splitRegions.size());
1256
1257
1258 byte[] regionName = regions.get(0).getFirst().getRegionName();
1259 try {
1260 TEST_UTIL.getHBaseAdmin().split(regionName, Bytes.toBytes('2'));
1261 } catch (IllegalArgumentException ex) {
1262 fail("Exception occured during region split" + ex);
1263 }
1264
1265
1266 TEST_UTIL.waitFor(60000, 500, new Waiter.Predicate<IOException>() {
1267 @Override
1268 public boolean evaluate() throws IOException {
1269 return am.getRegionStates().getRegionByStateOfTable(tableName).get(RegionState.State.OPEN)
1270 .size() == (primaryRegionCount + 1) * regionReplication;
1271 }
1272 });
1273
1274 regions = MetaTableAccessor.getTableRegionsAndLocations(TEST_UTIL.getZooKeeperWatcher(),
1275 TEST_UTIL.getConnection(), tableName);
1276 assertEquals(12, regions.size());
1277 final int primaryRegionCountAfterSplit = regions.size() / regionReplication;
1278
1279
1280 splitRegions =
1281 am.getRegionStates().getRegionByStateOfTable(tableName).get(RegionState.State.SPLIT);
1282
1283 assertEquals(1, splitRegions.size());
1284
1285
1286 HRegionInfo regionA = regions.get(3).getFirst();
1287 HRegionInfo regionB = regions.get(6).getFirst();
1288 try {
1289 TEST_UTIL.getHBaseAdmin().mergeRegions(regionA.getRegionName(), regionB.getRegionName(),
1290 true);
1291 } catch (IllegalArgumentException ex) {
1292 fail("Exception occured during region merge" + ex);
1293 }
1294
1295
1296 TEST_UTIL.waitFor(60000, 500, new Waiter.Predicate<IOException>() {
1297 @Override
1298 public boolean evaluate() throws IOException {
1299 return am.getRegionStates().getRegionByStateOfTable(tableName).get(RegionState.State.OPEN)
1300 .size() == (primaryRegionCountAfterSplit - 1) * regionReplication;
1301 }
1302 });
1303
1304 regions = MetaTableAccessor.getTableRegionsAndLocations(TEST_UTIL.getZooKeeperWatcher(),
1305 TEST_UTIL.getConnection(), tableName);
1306 assertEquals(9, regions.size());
1307
1308 List<HRegionInfo> offlineRegions =
1309 am.getRegionStates().getRegionByStateOfTable(tableName).get(RegionState.State.OFFLINE);
1310
1311 assertEquals(0, offlineRegions.size());
1312 }
1313
1314 private byte[] createReplicaTable(TableName tableName, byte[] cf) throws IOException {
1315 HTableDescriptor desc = new HTableDescriptor(tableName);
1316 desc.setRegionReplication(3);
1317 HColumnDescriptor hcd = new HColumnDescriptor(cf);
1318 desc.addFamily(hcd);
1319 byte[][] splitRows = new byte[2][];
1320 splitRows[0] = new byte[] { (byte) '4' };
1321 splitRows[1] = new byte[] { (byte) '7' };
1322 TEST_UTIL.getHBaseAdmin().createTable(desc, splitRows);
1323 return cf;
1324 }
1325
1326
1327
1328
1329
1330 @SuppressWarnings("deprecation")
1331 @Test (expected=IllegalArgumentException.class, timeout=300000)
1332 public void testEmptyHTableDescriptor() throws IOException {
1333 this.admin.createTable(new HTableDescriptor());
1334 }
1335
1336 @Test (expected=IllegalArgumentException.class, timeout=300000)
1337 public void testInvalidHColumnDescriptor() throws IOException {
1338 new HColumnDescriptor("/cfamily/name");
1339 }
1340
1341 @Test (timeout=300000)
1342 public void testEnableDisableAddColumnDeleteColumn() throws Exception {
1343 ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(TEST_UTIL);
1344 TableName tableName = TableName.valueOf("testEnableDisableAddColumnDeleteColumn");
1345 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
1346 while (!ZKTableStateClientSideReader.isEnabledTable(zkw,
1347 TableName.valueOf("testEnableDisableAddColumnDeleteColumn"))) {
1348 Thread.sleep(10);
1349 }
1350 this.admin.disableTable(tableName);
1351 try {
1352 new HTable(TEST_UTIL.getConfiguration(), tableName);
1353 } catch (org.apache.hadoop.hbase.DoNotRetryIOException e) {
1354
1355 }
1356
1357 this.admin.addColumn(tableName, new HColumnDescriptor("col2"));
1358 this.admin.enableTable(tableName);
1359 try {
1360 this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
1361 } catch (TableNotDisabledException e) {
1362 LOG.info(e);
1363 }
1364 this.admin.disableTable(tableName);
1365 this.admin.deleteTable(tableName);
1366 }
1367
1368 @Test (timeout=300000)
1369 public void testDeleteLastColumnFamily() throws Exception {
1370 TableName tableName = TableName.valueOf("testDeleteLastColumnFamily");
1371 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close();
1372 while (!this.admin.isTableEnabled(TableName.valueOf("testDeleteLastColumnFamily"))) {
1373 Thread.sleep(10);
1374 }
1375
1376
1377 try {
1378 this.admin.deleteColumn(tableName, HConstants.CATALOG_FAMILY);
1379 fail("Should have failed to delete the only column family of a table");
1380 } catch (InvalidFamilyOperationException ex) {
1381
1382 }
1383
1384
1385 this.admin.disableTable(tableName);
1386
1387 try {
1388 this.admin.deleteColumn(tableName, HConstants.CATALOG_FAMILY);
1389 fail("Should have failed to delete the only column family of a table");
1390 } catch (InvalidFamilyOperationException ex) {
1391
1392 }
1393
1394 this.admin.deleteTable(tableName);
1395 }
1396
1397
1398
1399
1400
1401 @Test(timeout = 300000)
1402 public void testHFileReplication() throws Exception {
1403 TableName name = TableName.valueOf("testHFileReplication");
1404 String fn1 = "rep1";
1405 HColumnDescriptor hcd1 = new HColumnDescriptor(fn1);
1406 hcd1.setDFSReplication((short) 1);
1407 String fn = "defaultRep";
1408 HColumnDescriptor hcd = new HColumnDescriptor(fn);
1409 HTableDescriptor htd = new HTableDescriptor(name);
1410 htd.addFamily(hcd);
1411 htd.addFamily(hcd1);
1412 Table table = TEST_UTIL.createTable(htd, null);
1413 TEST_UTIL.waitTableAvailable(name);
1414 Put p = new Put(Bytes.toBytes("defaultRep_rk"));
1415 byte[] q1 = Bytes.toBytes("q1");
1416 byte[] v1 = Bytes.toBytes("v1");
1417 p.addColumn(Bytes.toBytes(fn), q1, v1);
1418 List<Put> puts = new ArrayList<Put>(2);
1419 puts.add(p);
1420 p = new Put(Bytes.toBytes("rep1_rk"));
1421 p.addColumn(Bytes.toBytes(fn1), q1, v1);
1422 puts.add(p);
1423 try {
1424 table.put(puts);
1425 admin.flush(name);
1426
1427 List<HRegion> regions = TEST_UTIL.getMiniHBaseCluster().getRegions(name);
1428 for (HRegion r : regions) {
1429 Store store = r.getStore(Bytes.toBytes(fn));
1430 for (StoreFile sf : store.getStorefiles()) {
1431 assertTrue(sf.toString().contains(fn));
1432 assertTrue("Column family " + fn + " should have 3 copies",
1433 FSUtils.getDefaultReplication(TEST_UTIL.getTestFileSystem(), sf.getPath()) == (sf
1434 .getFileInfo().getFileStatus().getReplication()));
1435 }
1436
1437 store = r.getStore(Bytes.toBytes(fn1));
1438 for (StoreFile sf : store.getStorefiles()) {
1439 assertTrue(sf.toString().contains(fn1));
1440 assertTrue("Column family " + fn1 + " should have only 1 copy", 1 == sf.getFileInfo()
1441 .getFileStatus().getReplication());
1442 }
1443 }
1444 } finally {
1445 if (admin.isTableEnabled(name)) {
1446 this.admin.disableTable(name);
1447 this.admin.deleteTable(name);
1448 }
1449 }
1450 }
1451
1452 @Test
1453 public void testMergeRegions() throws Exception {
1454 TableName tableName = TableName.valueOf("testMergeWithFullRegionName");
1455 HColumnDescriptor cd = new HColumnDescriptor("d");
1456 HTableDescriptor td = new HTableDescriptor(tableName);
1457 td.addFamily(cd);
1458 byte[][] splitRows = new byte[2][];
1459 splitRows[0] = new byte[]{(byte)'3'};
1460 splitRows[1] = new byte[]{(byte)'6'};
1461 try {
1462 TEST_UTIL.createTable(td, splitRows);
1463 TEST_UTIL.waitTableAvailable(tableName);
1464
1465 List<HRegionInfo> tableRegions;
1466 HRegionInfo regionA;
1467 HRegionInfo regionB;
1468
1469
1470 tableRegions = admin.getTableRegions(tableName);
1471 assertEquals(3, admin.getTableRegions(tableName).size());
1472 regionA = tableRegions.get(0);
1473 regionB = tableRegions.get(1);
1474 admin.mergeRegions(regionA.getRegionName(), regionB.getRegionName(), false);
1475 Thread.sleep(1000);
1476 assertEquals(2, admin.getTableRegions(tableName).size());
1477
1478
1479 tableRegions = admin.getTableRegions(tableName);
1480 regionA = tableRegions.get(0);
1481 regionB = tableRegions.get(1);
1482 admin.mergeRegions(regionA.getEncodedNameAsBytes(), regionB.getEncodedNameAsBytes(), false);
1483 Thread.sleep(1000);
1484 assertEquals(1, admin.getTableRegions(tableName).size());
1485 } finally {
1486 this.admin.disableTable(tableName);
1487 this.admin.deleteTable(tableName);
1488 }
1489 }
1490
1491 @Test (timeout=30000)
1492 public void testTableNotFoundException() throws Exception {
1493 ZooKeeperWatcher zkw = TEST_UTIL.getZooKeeperWatcher();
1494 TableName table = TableName.valueOf("tableNotExists");
1495 try {
1496 ZKTableStateClientSideReader.isDisabledTable(zkw, table);
1497 fail("Shouldn't be here");
1498 } catch (TableNotFoundException e) {
1499
1500 }
1501 }
1502 }