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