1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.atomic.AtomicBoolean;
27
28 import org.apache.commons.lang.RandomStringUtils;
29 import org.apache.commons.lang.math.RandomUtils;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.client.Admin;
34 import org.apache.hadoop.hbase.client.Connection;
35 import org.apache.hadoop.hbase.client.ConnectionFactory;
36 import org.apache.hadoop.hbase.client.Put;
37 import org.apache.hadoop.hbase.client.Table;
38 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
39 import org.apache.hadoop.hbase.testclassification.IntegrationTests;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.util.HBaseFsck;
42 import org.apache.hadoop.hbase.util.Threads;
43 import org.apache.hadoop.hbase.util.hbck.HbckTestingUtil;
44 import org.apache.hadoop.util.ToolRunner;
45 import org.junit.Assert;
46 import org.junit.Test;
47 import org.junit.experimental.categories.Category;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 @Category(IntegrationTests.class)
98 public class IntegrationTestDDLMasterFailover extends IntegrationTestBase {
99
100 private static final Log LOG = LogFactory.getLog(IntegrationTestDDLMasterFailover.class);
101
102 private static final int SERVER_COUNT = 1;
103
104 protected static final long DEFAULT_RUN_TIME = 20 * 60 * 1000;
105
106 protected static final int DEFAULT_NUM_THREADS = 20;
107
108 protected static final int DEFAULT_NUM_REGIONS = 50;
109
110 private boolean keepObjectsAtTheEnd = false;
111 protected HBaseCluster cluster;
112
113 protected Connection connection;
114
115
116
117
118 protected static final String RUN_TIME_KEY = "hbase.%s.runtime";
119 protected static final String NUM_THREADS_KEY = "hbase.%s.numThreads";
120 protected static final String NUM_REGIONS_KEY = "hbase.%s.numRegions";
121
122 protected AtomicBoolean running = new AtomicBoolean(true);
123
124 protected AtomicBoolean create_table = new AtomicBoolean(true);
125
126 protected int numThreads, numRegions;
127
128 ConcurrentHashMap<String, NamespaceDescriptor> namespaceMap =
129 new ConcurrentHashMap<String, NamespaceDescriptor>();
130
131 ConcurrentHashMap<TableName, HTableDescriptor> enabledTables =
132 new ConcurrentHashMap<TableName, HTableDescriptor>();
133
134 ConcurrentHashMap<TableName, HTableDescriptor> disabledTables =
135 new ConcurrentHashMap<TableName, HTableDescriptor>();
136
137 ConcurrentHashMap<TableName, HTableDescriptor> deletedTables =
138 new ConcurrentHashMap<TableName, HTableDescriptor>();
139
140 @Override
141 public void setUpCluster() throws Exception {
142 util = getTestingUtil(getConf());
143 LOG.debug("Initializing/checking cluster has " + SERVER_COUNT + " servers");
144 util.initializeCluster(getMinServerCount());
145 LOG.debug("Done initializing/checking cluster");
146 cluster = util.getHBaseClusterInterface();
147 }
148
149 @Override
150 public void cleanUpCluster() throws Exception {
151 if (!keepObjectsAtTheEnd) {
152 Admin admin = util.getHBaseAdmin();
153 admin.disableTables("ittable-\\d+");
154 admin.deleteTables("ittable-\\d+");
155 NamespaceDescriptor [] nsds = admin.listNamespaceDescriptors();
156 for(NamespaceDescriptor nsd: nsds) {
157 if(nsd.getName().matches("itnamespace\\d+")) {
158 LOG.info("Removing namespace="+nsd.getName());
159 admin.deleteNamespace(nsd.getName());
160 }
161 }
162 }
163
164 enabledTables.clear();
165 disabledTables.clear();
166 deletedTables.clear();
167 namespaceMap.clear();
168
169 Connection connection = getConnection();
170 connection.close();
171 super.cleanUpCluster();
172 }
173
174 protected int getMinServerCount() {
175 return SERVER_COUNT;
176 }
177
178 protected synchronized void setConnection(Connection connection){
179 this.connection = connection;
180 }
181
182 protected synchronized Connection getConnection(){
183 if (this.connection == null) {
184 try {
185 Connection connection = ConnectionFactory.createConnection(getConf());
186 setConnection(connection);
187 } catch (IOException e) {
188 LOG.fatal("Failed to establish connection.", e);
189 }
190 }
191 return connection;
192 }
193
194 protected void verifyNamespaces() throws IOException{
195 Connection connection = getConnection();
196 Admin admin = connection.getAdmin();
197
198 for (String nsName : namespaceMap.keySet()){
199 try {
200 Assert.assertTrue(
201 "Namespace: " + nsName + " in namespaceMap does not exist",
202 admin.getNamespaceDescriptor(nsName) != null);
203 } catch (NamespaceNotFoundException nsnfe) {
204 Assert.fail(
205 "Namespace: " + nsName + " in namespaceMap does not exist: " + nsnfe.getMessage());
206 }
207 }
208 admin.close();
209 }
210
211 protected void verifyTables() throws IOException{
212 Connection connection = getConnection();
213 Admin admin = connection.getAdmin();
214
215 for (TableName tableName : enabledTables.keySet()){
216 Assert.assertTrue("Table: " + tableName + " in enabledTables is not enabled",
217 admin.isTableEnabled(tableName));
218 }
219 for (TableName tableName : disabledTables.keySet()){
220 Assert.assertTrue("Table: " + tableName + " in disabledTables is not disabled",
221 admin.isTableDisabled(tableName));
222 }
223 for (TableName tableName : deletedTables.keySet()){
224 Assert.assertFalse("Table: " + tableName + " in deletedTables is not deleted",
225 admin.tableExists(tableName));
226 }
227 admin.close();
228 }
229
230 @Test
231 public void testAsUnitTest() throws Exception {
232 runTest();
233 }
234
235 @Override
236 public int runTestFromCommandLine() throws Exception {
237 int ret = runTest();
238 return ret;
239 }
240
241 private abstract class MasterAction{
242 Connection connection = getConnection();
243
244 abstract void perform() throws IOException;
245 }
246
247 private abstract class NamespaceAction extends MasterAction {
248 final String nsTestConfigKey = "hbase.namespace.testKey";
249
250
251 protected NamespaceDescriptor selectNamespace(
252 ConcurrentHashMap<String, NamespaceDescriptor> namespaceMap) {
253
254 synchronized (namespaceMap) {
255
256 if (namespaceMap.isEmpty()) {
257 return null;
258 }
259 ArrayList<String> namespaceList = new ArrayList<String>(namespaceMap.keySet());
260 String randomKey = namespaceList.get(RandomUtils.nextInt(namespaceList.size()));
261 NamespaceDescriptor randomNsd = namespaceMap.get(randomKey);
262
263 namespaceMap.remove(randomKey);
264 return randomNsd;
265 }
266 }
267 }
268
269 private class CreateNamespaceAction extends NamespaceAction {
270 @Override
271 void perform() throws IOException {
272 Admin admin = connection.getAdmin();
273 try {
274 NamespaceDescriptor nsd;
275 while (true) {
276 nsd = createNamespaceDesc();
277 try {
278 if (admin.getNamespaceDescriptor(nsd.getName()) != null) {
279
280 continue;
281 } else {
282
283
284
285
286 break;
287 }
288 } catch (NamespaceNotFoundException nsnfe) {
289
290 break;
291 }
292 }
293 LOG.info("Creating namespace:" + nsd);
294 admin.createNamespace(nsd);
295 NamespaceDescriptor freshNamespaceDesc = admin.getNamespaceDescriptor(nsd.getName());
296 Assert.assertTrue("Namespace: " + nsd + " was not created", freshNamespaceDesc != null);
297 namespaceMap.put(nsd.getName(), freshNamespaceDesc);
298 LOG.info("Created namespace:" + freshNamespaceDesc);
299 } catch (Exception e){
300 LOG.warn("Caught exception in action: " + this.getClass());
301 throw e;
302 } finally {
303 admin.close();
304 }
305 }
306
307 private NamespaceDescriptor createNamespaceDesc() {
308 String namespaceName = "itnamespace" + String.format("%010d",
309 RandomUtils.nextInt(Integer.MAX_VALUE));
310 NamespaceDescriptor nsd = NamespaceDescriptor.create(namespaceName).build();
311
312 nsd.setConfiguration(
313 nsTestConfigKey,
314 String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE)));
315 return nsd;
316 }
317 }
318
319 private class ModifyNamespaceAction extends NamespaceAction {
320 @Override
321 void perform() throws IOException {
322 NamespaceDescriptor selected = selectNamespace(namespaceMap);
323 if (selected == null) {
324 return;
325 }
326
327 Admin admin = connection.getAdmin();
328 try {
329 String namespaceName = selected.getName();
330 LOG.info("Modifying namespace :" + selected);
331 NamespaceDescriptor modifiedNsd = NamespaceDescriptor.create(namespaceName).build();
332 String nsValueNew;
333 do {
334 nsValueNew = String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE));
335 } while (selected.getConfigurationValue(nsTestConfigKey).equals(nsValueNew));
336 modifiedNsd.setConfiguration(nsTestConfigKey, nsValueNew);
337 admin.modifyNamespace(modifiedNsd);
338 NamespaceDescriptor freshNamespaceDesc = admin.getNamespaceDescriptor(namespaceName);
339 Assert.assertTrue(
340 "Namespace: " + selected + " was not modified",
341 freshNamespaceDesc.getConfigurationValue(nsTestConfigKey).equals(nsValueNew));
342 Assert.assertTrue(
343 "Namespace: " + namespaceName + " does not exist",
344 admin.getNamespaceDescriptor(namespaceName) != null);
345 namespaceMap.put(namespaceName, freshNamespaceDesc);
346 LOG.info("Modified namespace :" + freshNamespaceDesc);
347 } catch (Exception e){
348 LOG.warn("Caught exception in action: " + this.getClass());
349 throw e;
350 } finally {
351 admin.close();
352 }
353 }
354 }
355
356 private class DeleteNamespaceAction extends NamespaceAction {
357 @Override
358 void perform() throws IOException {
359 NamespaceDescriptor selected = selectNamespace(namespaceMap);
360 if (selected == null) {
361 return;
362 }
363
364 Admin admin = connection.getAdmin();
365 try {
366 String namespaceName = selected.getName();
367 LOG.info("Deleting namespace :" + selected);
368 admin.deleteNamespace(namespaceName);
369 try {
370 if (admin.getNamespaceDescriptor(namespaceName) != null) {
371
372 Assert.assertTrue("Namespace: " + selected + " was not deleted", false);
373 } else {
374 LOG.info("Deleted namespace :" + selected);
375 }
376 } catch (NamespaceNotFoundException nsnfe) {
377
378 LOG.info("Deleted namespace :" + selected);
379 }
380 } catch (Exception e){
381 LOG.warn("Caught exception in action: " + this.getClass());
382 throw e;
383 } finally {
384 admin.close();
385 }
386 }
387 }
388
389 private abstract class TableAction extends MasterAction{
390
391 protected HTableDescriptor selectTable(ConcurrentHashMap<TableName, HTableDescriptor> tableMap)
392 {
393
394 synchronized (tableMap){
395
396 if (tableMap.isEmpty()) {
397 return null;
398 }
399 ArrayList<TableName> tableList = new ArrayList<TableName>(tableMap.keySet());
400 TableName randomKey = tableList.get(RandomUtils.nextInt(tableList.size()));
401 HTableDescriptor randomHtd = tableMap.get(randomKey);
402
403 tableMap.remove(randomKey);
404 return randomHtd;
405 }
406 }
407 }
408
409 private class CreateTableAction extends TableAction {
410
411 @Override
412 void perform() throws IOException {
413 Admin admin = connection.getAdmin();
414 try {
415 HTableDescriptor htd = createTableDesc();
416 TableName tableName = htd.getTableName();
417 if ( admin.tableExists(tableName)){
418 return;
419 }
420 String numRegionKey = String.format(NUM_REGIONS_KEY, this.getClass().getSimpleName());
421 numRegions = getConf().getInt(numRegionKey, DEFAULT_NUM_REGIONS);
422 byte[] startKey = Bytes.toBytes("row-0000000000");
423 byte[] endKey = Bytes.toBytes("row-" + Integer.MAX_VALUE);
424 LOG.info("Creating table:" + htd);
425 admin.createTable(htd, startKey, endKey, numRegions);
426 Assert.assertTrue("Table: " + htd + " was not created", admin.tableExists(tableName));
427 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
428 Assert.assertTrue(
429 "After create, Table: " + tableName + " in not enabled", admin.isTableEnabled(tableName));
430 enabledTables.put(tableName, freshTableDesc);
431 LOG.info("Created table:" + freshTableDesc);
432 } catch (Exception e) {
433 LOG.warn("Caught exception in action: " + this.getClass());
434 throw e;
435 } finally {
436 admin.close();
437 }
438 }
439
440 private HTableDescriptor createTableDesc() {
441 String tableName = "ittable-" + String.format("%010d",
442 RandomUtils.nextInt(Integer.MAX_VALUE));
443 String familyName = "cf-" + Math.abs(RandomUtils.nextInt());
444 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName));
445
446 htd.addFamily(new HColumnDescriptor(familyName));
447 return htd;
448 }
449 }
450
451 private class DisableTableAction extends TableAction {
452
453 @Override
454 void perform() throws IOException {
455
456 HTableDescriptor selected = selectTable(enabledTables);
457 if (selected == null) {
458 return;
459 }
460
461 Admin admin = connection.getAdmin();
462 try {
463 TableName tableName = selected.getTableName();
464 LOG.info("Disabling table :" + selected);
465 admin.disableTable(tableName);
466 Assert.assertTrue("Table: " + selected + " was not disabled",
467 admin.isTableDisabled(tableName));
468 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
469 Assert.assertTrue(
470 "After disable, Table: " + tableName + " is not disabled",
471 admin.isTableDisabled(tableName));
472 disabledTables.put(tableName, freshTableDesc);
473 LOG.info("Disabled table :" + freshTableDesc);
474 } catch (Exception e){
475 LOG.warn("Caught exception in action: " + this.getClass());
476
477
478
479
480
481
482
483
484
485
486
487
488 if (e instanceof TableNotEnabledException) {
489 LOG.warn("Caught TableNotEnabledException in action: " + this.getClass());
490 e.printStackTrace();
491 } else {
492 throw e;
493 }
494 } finally {
495 admin.close();
496 }
497 }
498 }
499
500 private class EnableTableAction extends TableAction {
501
502 @Override
503 void perform() throws IOException {
504
505 HTableDescriptor selected = selectTable(disabledTables);
506 if (selected == null ) {
507 return;
508 }
509
510 Admin admin = connection.getAdmin();
511 try {
512 TableName tableName = selected.getTableName();
513 LOG.info("Enabling table :" + selected);
514 admin.enableTable(tableName);
515 Assert.assertTrue("Table: " + selected + " was not enabled",
516 admin.isTableEnabled(tableName));
517 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
518 Assert.assertTrue(
519 "After enable, Table: " + tableName + " in not enabled", admin.isTableEnabled(tableName));
520 enabledTables.put(tableName, freshTableDesc);
521 LOG.info("Enabled table :" + freshTableDesc);
522 } catch (Exception e){
523 LOG.warn("Caught exception in action: " + this.getClass());
524
525
526
527
528
529
530
531
532
533
534
535
536 if (e instanceof TableNotDisabledException) {
537 LOG.warn("Caught TableNotDisabledException in action: " + this.getClass());
538 e.printStackTrace();
539 } else {
540 throw e;
541 }
542 } finally {
543 admin.close();
544 }
545 }
546 }
547
548 private class DeleteTableAction extends TableAction {
549
550 @Override
551 void perform() throws IOException {
552
553 HTableDescriptor selected = selectTable(disabledTables);
554 if (selected == null) {
555 return;
556 }
557
558 Admin admin = connection.getAdmin();
559 try {
560 TableName tableName = selected.getTableName();
561 LOG.info("Deleting table :" + selected);
562 admin.deleteTable(tableName);
563 Assert.assertFalse("Table: " + selected + " was not deleted",
564 admin.tableExists(tableName));
565 deletedTables.put(tableName, selected);
566 LOG.info("Deleted table :" + selected);
567 } catch (Exception e) {
568 LOG.warn("Caught exception in action: " + this.getClass());
569 throw e;
570 } finally {
571 admin.close();
572 }
573 }
574 }
575
576
577 private abstract class ColumnAction extends TableAction{
578
579 protected HColumnDescriptor selectFamily(HTableDescriptor htd) {
580 if (htd == null) {
581 return null;
582 }
583 HColumnDescriptor[] families = htd.getColumnFamilies();
584 if (families.length == 0){
585 LOG.info("No column families in table: " + htd);
586 return null;
587 }
588 HColumnDescriptor randomCfd = families[RandomUtils.nextInt(families.length)];
589 return randomCfd;
590 }
591 }
592
593 private class AddColumnFamilyAction extends ColumnAction {
594
595 @Override
596 void perform() throws IOException {
597 HTableDescriptor selected = selectTable(disabledTables);
598 if (selected == null) {
599 return;
600 }
601
602 Admin admin = connection.getAdmin();
603 try {
604 HColumnDescriptor cfd = createFamilyDesc();
605 if (selected.hasFamily(cfd.getName())){
606 LOG.info(new String(cfd.getName()) + " already exists in table "
607 + selected.getTableName());
608 return;
609 }
610 TableName tableName = selected.getTableName();
611 LOG.info("Adding column family: " + cfd + " to table: " + tableName);
612 admin.addColumn(tableName, cfd);
613
614 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
615 Assert.assertTrue("Column family: " + cfd + " was not added",
616 freshTableDesc.hasFamily(cfd.getName()));
617 Assert.assertTrue(
618 "After add column family, Table: " + tableName + " is not disabled",
619 admin.isTableDisabled(tableName));
620 disabledTables.put(tableName, freshTableDesc);
621 LOG.info("Added column family: " + cfd + " to table: " + tableName);
622 } catch (Exception e) {
623 LOG.warn("Caught exception in action: " + this.getClass());
624 throw e;
625 } finally {
626 admin.close();
627 }
628 }
629
630 private HColumnDescriptor createFamilyDesc() {
631 String familyName = "cf-" + String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE));
632 HColumnDescriptor cfd = new HColumnDescriptor(familyName);
633 return cfd;
634 }
635 }
636
637 private class AlterFamilyVersionsAction extends ColumnAction {
638
639 @Override
640 void perform() throws IOException {
641 HTableDescriptor selected = selectTable(disabledTables);
642 if (selected == null) {
643 return;
644 }
645 HColumnDescriptor columnDesc = selectFamily(selected);
646 if (columnDesc == null){
647 return;
648 }
649
650 Admin admin = connection.getAdmin();
651 int versions = RandomUtils.nextInt(10) + 3;
652 try {
653 TableName tableName = selected.getTableName();
654 LOG.info("Altering versions of column family: " + columnDesc + " to: " + versions +
655 " in table: " + tableName);
656 columnDesc.setMinVersions(versions);
657 columnDesc.setMaxVersions(versions);
658 admin.modifyTable(tableName, selected);
659
660 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
661 HColumnDescriptor freshColumnDesc = freshTableDesc.getFamily(columnDesc.getName());
662 Assert.assertEquals("Column family: " + columnDesc + " was not altered",
663 freshColumnDesc.getMaxVersions(), versions);
664 Assert.assertEquals("Column family: " + freshColumnDesc + " was not altered",
665 freshColumnDesc.getMinVersions(), versions);
666 Assert.assertTrue(
667 "After alter versions of column family, Table: " + tableName + " is not disabled",
668 admin.isTableDisabled(tableName));
669 disabledTables.put(tableName, freshTableDesc);
670 LOG.info("Altered versions of column family: " + columnDesc + " to: " + versions +
671 " in table: " + tableName);
672 } catch (Exception e) {
673 LOG.warn("Caught exception in action: " + this.getClass());
674 throw e;
675 } finally {
676 admin.close();
677 }
678 }
679 }
680
681 private class AlterFamilyEncodingAction extends ColumnAction {
682
683 @Override
684 void perform() throws IOException {
685 HTableDescriptor selected = selectTable(disabledTables);
686 if (selected == null) {
687 return;
688 }
689 HColumnDescriptor columnDesc = selectFamily(selected);
690 if (columnDesc == null){
691 return;
692 }
693
694 Admin admin = connection.getAdmin();
695 try {
696 TableName tableName = selected.getTableName();
697
698 int[] possibleIds = {0, 2, 3, 4, 6};
699 short id = (short) possibleIds[RandomUtils.nextInt(possibleIds.length)];
700 LOG.info("Altering encoding of column family: " + columnDesc + " to: " + id +
701 " in table: " + tableName);
702 columnDesc.setDataBlockEncoding(DataBlockEncoding.getEncodingById(id));
703 admin.modifyTable(tableName, selected);
704
705 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
706 HColumnDescriptor freshColumnDesc = freshTableDesc.getFamily(columnDesc.getName());
707 Assert.assertEquals("Encoding of column family: " + columnDesc + " was not altered",
708 freshColumnDesc.getDataBlockEncoding().getId(), id);
709 Assert.assertTrue(
710 "After alter encoding of column family, Table: " + tableName + " is not disabled",
711 admin.isTableDisabled(tableName));
712 disabledTables.put(tableName, freshTableDesc);
713 LOG.info("Altered encoding of column family: " + freshColumnDesc + " to: " + id +
714 " in table: " + tableName);
715 } catch (Exception e) {
716 LOG.warn("Caught exception in action: " + this.getClass());
717 throw e;
718 } finally {
719 admin.close();
720 }
721 }
722 }
723
724 private class DeleteColumnFamilyAction extends ColumnAction {
725
726 @Override
727 void perform() throws IOException {
728 HTableDescriptor selected = selectTable(disabledTables);
729 HColumnDescriptor cfd = selectFamily(selected);
730 if (selected == null || cfd == null) {
731 return;
732 }
733
734 Admin admin = connection.getAdmin();
735 try {
736 if (selected.getColumnFamilies().length < 2) {
737 LOG.info("No enough column families to delete in table " + selected.getTableName());
738 return;
739 }
740 TableName tableName = selected.getTableName();
741 LOG.info("Deleting column family: " + cfd + " from table: " + tableName);
742 admin.deleteColumn(tableName, cfd.getName());
743
744 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
745 Assert.assertFalse("Column family: " + cfd + " was not added",
746 freshTableDesc.hasFamily(cfd.getName()));
747 Assert.assertTrue(
748 "After delete column family, Table: " + tableName + " is not disabled",
749 admin.isTableDisabled(tableName));
750 disabledTables.put(tableName, freshTableDesc);
751 LOG.info("Deleted column family: " + cfd + " from table: " + tableName);
752 } catch (Exception e) {
753 LOG.warn("Caught exception in action: " + this.getClass());
754 throw e;
755 } finally {
756 admin.close();
757 }
758 }
759 }
760
761 private class AddRowAction extends ColumnAction {
762
763 @Override
764 void perform() throws IOException {
765 HTableDescriptor selected = selectTable(enabledTables);
766 if (selected == null ) {
767 return;
768 }
769
770 Admin admin = connection.getAdmin();
771 TableName tableName = selected.getTableName();
772 try (Table table = connection.getTable(tableName)){
773 ArrayList<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>(admin.getTableRegions(
774 selected.getTableName()));
775 int numRegions = regionInfos.size();
776
777 int average_rows = 1;
778 int numRows = average_rows * numRegions;
779 LOG.info("Adding " + numRows + " rows to table: " + selected);
780 for (int i = 0; i < numRows; i++){
781
782 byte[] rowKey = Bytes.toBytes(
783 "row-" + String.format("%010d", RandomUtils.nextInt(Integer.MAX_VALUE)));
784 HColumnDescriptor cfd = selectFamily(selected);
785 if (cfd == null){
786 return;
787 }
788 byte[] family = cfd.getName();
789 byte[] qualifier = Bytes.toBytes("col-" + RandomUtils.nextInt(Integer.MAX_VALUE) % 10);
790 byte[] value = Bytes.toBytes("val-" + RandomStringUtils.randomAlphanumeric(10));
791 Put put = new Put(rowKey);
792 put.addColumn(family, qualifier, value);
793 table.put(put);
794 }
795 HTableDescriptor freshTableDesc = admin.getTableDescriptor(tableName);
796 Assert.assertTrue(
797 "After insert, Table: " + tableName + " in not enabled", admin.isTableEnabled(tableName));
798 enabledTables.put(tableName, freshTableDesc);
799 LOG.info("Added " + numRows + " rows to table: " + selected);
800 } catch (Exception e) {
801 LOG.warn("Caught exception in action: " + this.getClass());
802 throw e;
803 } finally {
804 admin.close();
805 }
806 }
807 }
808
809 private enum ACTION {
810 CREATE_NAMESPACE,
811 MODIFY_NAMESPACE,
812 DELETE_NAMESPACE,
813 CREATE_TABLE,
814 DISABLE_TABLE,
815 ENABLE_TABLE,
816 DELETE_TABLE,
817 ADD_COLUMNFAMILY,
818 DELETE_COLUMNFAMILY,
819 ALTER_FAMILYVERSIONS,
820 ALTER_FAMILYENCODING,
821 ADD_ROW
822 }
823
824 private class Worker extends Thread {
825
826 private Exception savedException;
827
828 private ACTION action;
829
830 @Override
831 public void run() {
832 while (running.get()) {
833
834 ACTION selectedAction = ACTION.values()[RandomUtils.nextInt() % ACTION.values().length];
835 this.action = selectedAction;
836 LOG.info("Performing Action: " + selectedAction);
837
838 try {
839 switch (selectedAction) {
840 case CREATE_NAMESPACE:
841 new CreateNamespaceAction().perform();
842 break;
843 case MODIFY_NAMESPACE:
844 new ModifyNamespaceAction().perform();
845 break;
846 case DELETE_NAMESPACE:
847 new DeleteNamespaceAction().perform();
848 break;
849 case CREATE_TABLE:
850
851
852 if (create_table.get()) {
853 new CreateTableAction().perform();
854 }
855 break;
856 case ADD_ROW:
857 new AddRowAction().perform();
858 break;
859 case DISABLE_TABLE:
860 new DisableTableAction().perform();
861 break;
862 case ENABLE_TABLE:
863 new EnableTableAction().perform();
864 break;
865 case DELETE_TABLE:
866
867 if (RandomUtils.nextInt(100) < 20) {
868 new DeleteTableAction().perform();
869 }
870 break;
871 case ADD_COLUMNFAMILY:
872 new AddColumnFamilyAction().perform();
873 break;
874 case DELETE_COLUMNFAMILY:
875
876 if (RandomUtils.nextInt(100) < 20) {
877 new DeleteColumnFamilyAction().perform();
878 }
879 break;
880 case ALTER_FAMILYVERSIONS:
881 new AlterFamilyVersionsAction().perform();
882 break;
883 case ALTER_FAMILYENCODING:
884 new AlterFamilyEncodingAction().perform();
885 break;
886 }
887 } catch (Exception ex) {
888 this.savedException = ex;
889 return;
890 }
891 }
892 LOG.info(this.getName() + " stopped");
893 }
894
895 public Exception getSavedException(){
896 return this.savedException;
897 }
898
899 public ACTION getAction(){
900 return this.action;
901 }
902 }
903
904 private void checkException(List<Worker> workers){
905 if(workers == null || workers.isEmpty())
906 return;
907 for (Worker worker : workers){
908 Exception e = worker.getSavedException();
909 if (e != null) {
910 LOG.error("Found exception in thread: " + worker.getName());
911 e.printStackTrace();
912 }
913 Assert.assertNull("Action failed: " + worker.getAction() + " in thread: "
914 + worker.getName(), e);
915 }
916 }
917
918 private int runTest() throws Exception {
919 LOG.info("Starting the test");
920
921 String runtimeKey = String.format(RUN_TIME_KEY, this.getClass().getSimpleName());
922 long runtime = util.getConfiguration().getLong(runtimeKey, DEFAULT_RUN_TIME);
923
924 String numThreadKey = String.format(NUM_THREADS_KEY, this.getClass().getSimpleName());
925 numThreads = util.getConfiguration().getInt(numThreadKey, DEFAULT_NUM_THREADS);
926
927 ArrayList<Worker> workers = new ArrayList<>();
928 for (int i = 0; i < numThreads; i++) {
929 checkException(workers);
930 Worker worker = new Worker();
931 LOG.info("Launching worker thread " + worker.getName());
932 workers.add(worker);
933 worker.start();
934 }
935
936 Threads.sleep(runtime / 2);
937 LOG.info("Stopping creating new tables");
938 create_table.set(false);
939 Threads.sleep(runtime / 2);
940 LOG.info("Runtime is up");
941 running.set(false);
942
943 checkException(workers);
944
945 for (Worker worker : workers) {
946 worker.join();
947 }
948 LOG.info("All Worker threads stopped");
949
950
951 LOG.info("Verify actions of all threads succeeded");
952 checkException(workers);
953 LOG.info("Verify namespaces");
954 verifyNamespaces();
955 LOG.info("Verify states of all tables");
956 verifyTables();
957
958
959
960 HBaseFsck hbck = null;
961 try {
962 LOG.info("Running hbck");
963 hbck = HbckTestingUtil.doFsck(util.getConfiguration(), false);
964 if (HbckTestingUtil.inconsistencyFound(hbck)) {
965
966
967 keepObjectsAtTheEnd = true;
968 }
969 HbckTestingUtil.assertNoErrors(hbck);
970 LOG.info("Finished hbck");
971 } finally {
972 if (hbck != null) {
973 hbck.close();
974 }
975 }
976 return 0;
977 }
978
979 @Override
980 public TableName getTablename() {
981 return null;
982 }
983
984 @Override
985 protected Set<String> getColumnFamilies() {
986 return null;
987 }
988
989 public static void main(String[] args) throws Exception {
990 Configuration conf = HBaseConfiguration.create();
991 IntegrationTestingUtility.setUseDistributedCluster(conf);
992 IntegrationTestDDLMasterFailover masterFailover = new IntegrationTestDDLMasterFailover();
993 Connection connection = null;
994 int ret = 1;
995 try {
996
997 LOG.debug("Setting up connection ...");
998 connection = ConnectionFactory.createConnection(conf);
999 masterFailover.setConnection(connection);
1000 ret = ToolRunner.run(conf, masterFailover, args);
1001 } catch (IOException e){
1002 LOG.fatal("Failed to establish connection. Aborting test ...", e);
1003 } finally {
1004 connection = masterFailover.getConnection();
1005 if (connection != null){
1006 connection.close();
1007 }
1008 System.exit(ret);
1009 }
1010 }
1011 }