1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.coprocessor;
22
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27
28 import java.io.IOException;
29 import java.util.Collection;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.NavigableMap;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.hbase.*;
38 import org.apache.hadoop.hbase.client.HBaseAdmin;
39 import org.apache.hadoop.hbase.client.HTable;
40 import org.apache.hadoop.hbase.master.AssignmentManager;
41 import org.apache.hadoop.hbase.master.HMaster;
42 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
43 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
44 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
45 import org.apache.hadoop.hbase.regionserver.HRegionServer;
46 import org.apache.hadoop.hbase.util.Bytes;
47 import org.apache.hadoop.hbase.util.Threads;
48 import org.junit.AfterClass;
49 import org.junit.BeforeClass;
50 import org.junit.Test;
51 import org.junit.experimental.categories.Category;
52
53
54
55
56
57 @Category(MediumTests.class)
58 public class TestMasterObserver {
59 private static final Log LOG = LogFactory.getLog(TestMasterObserver.class);
60
61 public static class CPMasterObserver implements MasterObserver {
62
63 private boolean bypass = false;
64 private boolean preCreateTableCalled;
65 private boolean postCreateTableCalled;
66 private boolean preDeleteTableCalled;
67 private boolean postDeleteTableCalled;
68 private boolean preModifyTableCalled;
69 private boolean postModifyTableCalled;
70 private boolean preAddColumnCalled;
71 private boolean postAddColumnCalled;
72 private boolean preModifyColumnCalled;
73 private boolean postModifyColumnCalled;
74 private boolean preDeleteColumnCalled;
75 private boolean postDeleteColumnCalled;
76 private boolean preEnableTableCalled;
77 private boolean postEnableTableCalled;
78 private boolean preDisableTableCalled;
79 private boolean postDisableTableCalled;
80 private boolean preMoveCalled;
81 private boolean postMoveCalled;
82 private boolean preAssignCalled;
83 private boolean postAssignCalled;
84 private boolean preUnassignCalled;
85 private boolean postUnassignCalled;
86 private boolean preBalanceCalled;
87 private boolean postBalanceCalled;
88 private boolean preBalanceSwitchCalled;
89 private boolean postBalanceSwitchCalled;
90 private boolean preShutdownCalled;
91 private boolean preStopMasterCalled;
92 private boolean postStartMasterCalled;
93 private boolean startCalled;
94 private boolean stopCalled;
95 private boolean preSnapshotCalled;
96 private boolean postSnapshotCalled;
97 private boolean preCloneSnapshotCalled;
98 private boolean postCloneSnapshotCalled;
99 private boolean preRestoreSnapshotCalled;
100 private boolean postRestoreSnapshotCalled;
101 private boolean preDeleteSnapshotCalled;
102 private boolean postDeleteSnapshotCalled;
103 private boolean preGetTableDescriptorsCalled;
104 private boolean postGetTableDescriptorsCalled;
105
106 public void enableBypass(boolean bypass) {
107 this.bypass = bypass;
108 }
109
110 public void resetStates() {
111 preCreateTableCalled = false;
112 postCreateTableCalled = false;
113 preDeleteTableCalled = false;
114 postDeleteTableCalled = false;
115 preModifyTableCalled = false;
116 postModifyTableCalled = false;
117 preAddColumnCalled = false;
118 postAddColumnCalled = false;
119 preModifyColumnCalled = false;
120 postModifyColumnCalled = false;
121 preDeleteColumnCalled = false;
122 postDeleteColumnCalled = false;
123 preEnableTableCalled = false;
124 postEnableTableCalled = false;
125 preDisableTableCalled = false;
126 postDisableTableCalled = false;
127 preMoveCalled= false;
128 postMoveCalled = false;
129 preAssignCalled = false;
130 postAssignCalled = false;
131 preUnassignCalled = false;
132 postUnassignCalled = false;
133 preBalanceCalled = false;
134 postBalanceCalled = false;
135 preBalanceSwitchCalled = false;
136 postBalanceSwitchCalled = false;
137 preSnapshotCalled = false;
138 postSnapshotCalled = false;
139 preCloneSnapshotCalled = false;
140 postCloneSnapshotCalled = false;
141 preRestoreSnapshotCalled = false;
142 postRestoreSnapshotCalled = false;
143 preDeleteSnapshotCalled = false;
144 postDeleteSnapshotCalled = false;
145 preGetTableDescriptorsCalled = false;
146 postGetTableDescriptorsCalled = false;
147 }
148
149 @Override
150 public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
151 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
152 if (bypass) {
153 env.bypass();
154 }
155 preCreateTableCalled = true;
156 }
157
158 @Override
159 public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
160 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
161 postCreateTableCalled = true;
162 }
163
164 public boolean wasCreateTableCalled() {
165 return preCreateTableCalled && postCreateTableCalled;
166 }
167
168 public boolean preCreateTableCalledOnly() {
169 return preCreateTableCalled && !postCreateTableCalled;
170 }
171
172 @Override
173 public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
174 byte[] tableName) throws IOException {
175 if (bypass) {
176 env.bypass();
177 }
178 preDeleteTableCalled = true;
179 }
180
181 @Override
182 public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
183 byte[] tableName) throws IOException {
184 postDeleteTableCalled = true;
185 }
186
187 public boolean wasDeleteTableCalled() {
188 return preDeleteTableCalled && postDeleteTableCalled;
189 }
190
191 public boolean preDeleteTableCalledOnly() {
192 return preDeleteTableCalled && !postDeleteTableCalled;
193 }
194
195 @Override
196 public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
197 byte[] tableName, HTableDescriptor htd) throws IOException {
198 if (bypass) {
199 env.bypass();
200 }
201 preModifyTableCalled = true;
202 }
203
204 @Override
205 public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
206 byte[] tableName, HTableDescriptor htd) throws IOException {
207 postModifyTableCalled = true;
208 }
209
210 public boolean wasModifyTableCalled() {
211 return preModifyTableCalled && postModifyTableCalled;
212 }
213
214 public boolean preModifyTableCalledOnly() {
215 return preModifyTableCalled && !postModifyTableCalled;
216 }
217
218 @Override
219 public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
220 byte[] tableName, HColumnDescriptor column) throws IOException {
221 if (bypass) {
222 env.bypass();
223 }
224 preAddColumnCalled = true;
225 }
226
227 @Override
228 public void postAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
229 byte[] tableName, HColumnDescriptor column) throws IOException {
230 postAddColumnCalled = true;
231 }
232
233 public boolean wasAddColumnCalled() {
234 return preAddColumnCalled && postAddColumnCalled;
235 }
236
237 public boolean preAddColumnCalledOnly() {
238 return preAddColumnCalled && !postAddColumnCalled;
239 }
240
241 @Override
242 public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
243 byte[] tableName, HColumnDescriptor descriptor) throws IOException {
244 if (bypass) {
245 env.bypass();
246 }
247 preModifyColumnCalled = true;
248 }
249
250 @Override
251 public void postModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
252 byte[] tableName, HColumnDescriptor descriptor) throws IOException {
253 postModifyColumnCalled = true;
254 }
255
256 public boolean wasModifyColumnCalled() {
257 return preModifyColumnCalled && postModifyColumnCalled;
258 }
259
260 public boolean preModifyColumnCalledOnly() {
261 return preModifyColumnCalled && !postModifyColumnCalled;
262 }
263
264 @Override
265 public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
266 byte[] tableName, byte[] c) throws IOException {
267 if (bypass) {
268 env.bypass();
269 }
270 preDeleteColumnCalled = true;
271 }
272
273 @Override
274 public void postDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
275 byte[] tableName, byte[] c) throws IOException {
276 postDeleteColumnCalled = true;
277 }
278
279 public boolean wasDeleteColumnCalled() {
280 return preDeleteColumnCalled && postDeleteColumnCalled;
281 }
282
283 public boolean preDeleteColumnCalledOnly() {
284 return preDeleteColumnCalled && !postDeleteColumnCalled;
285 }
286
287 @Override
288 public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
289 byte[] tableName) throws IOException {
290 if (bypass) {
291 env.bypass();
292 }
293 preEnableTableCalled = true;
294 }
295
296 @Override
297 public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
298 byte[] tableName) throws IOException {
299 postEnableTableCalled = true;
300 }
301
302 public boolean wasEnableTableCalled() {
303 return preEnableTableCalled && postEnableTableCalled;
304 }
305
306 public boolean preEnableTableCalledOnly() {
307 return preEnableTableCalled && !postEnableTableCalled;
308 }
309
310 @Override
311 public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
312 byte[] tableName) throws IOException {
313 if (bypass) {
314 env.bypass();
315 }
316 preDisableTableCalled = true;
317 }
318
319 @Override
320 public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
321 byte[] tableName) throws IOException {
322 postDisableTableCalled = true;
323 }
324
325 public boolean wasDisableTableCalled() {
326 return preDisableTableCalled && postDisableTableCalled;
327 }
328
329 public boolean preDisableTableCalledOnly() {
330 return preDisableTableCalled && !postDisableTableCalled;
331 }
332
333 @Override
334 public void preMove(ObserverContext<MasterCoprocessorEnvironment> env,
335 HRegionInfo region, ServerName srcServer, ServerName destServer)
336 throws IOException {
337 if (bypass) {
338 env.bypass();
339 }
340 preMoveCalled = true;
341 }
342
343 @Override
344 public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, HRegionInfo region,
345 ServerName srcServer, ServerName destServer)
346 throws IOException {
347 postMoveCalled = true;
348 }
349
350 public boolean wasMoveCalled() {
351 return preMoveCalled && postMoveCalled;
352 }
353
354 public boolean preMoveCalledOnly() {
355 return preMoveCalled && !postMoveCalled;
356 }
357
358 @Override
359 public void preAssign(ObserverContext<MasterCoprocessorEnvironment> env,
360 final HRegionInfo regionInfo) throws IOException {
361 if (bypass) {
362 env.bypass();
363 }
364 preAssignCalled = true;
365 }
366
367 @Override
368 public void postAssign(ObserverContext<MasterCoprocessorEnvironment> env,
369 final HRegionInfo regionInfo) throws IOException {
370 postAssignCalled = true;
371 }
372
373 public boolean wasAssignCalled() {
374 return preAssignCalled && postAssignCalled;
375 }
376
377 public boolean preAssignCalledOnly() {
378 return preAssignCalled && !postAssignCalled;
379 }
380
381 @Override
382 public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
383 final HRegionInfo regionInfo, final boolean force) throws IOException {
384 if (bypass) {
385 env.bypass();
386 }
387 preUnassignCalled = true;
388 }
389
390 @Override
391 public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
392 final HRegionInfo regionInfo, final boolean force) throws IOException {
393 postUnassignCalled = true;
394 }
395
396 public boolean wasUnassignCalled() {
397 return preUnassignCalled && postUnassignCalled;
398 }
399
400 public boolean preUnassignCalledOnly() {
401 return preUnassignCalled && !postUnassignCalled;
402 }
403
404 @Override
405 public void preBalance(ObserverContext<MasterCoprocessorEnvironment> env)
406 throws IOException {
407 if (bypass) {
408 env.bypass();
409 }
410 preBalanceCalled = true;
411 }
412
413 @Override
414 public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env)
415 throws IOException {
416 postBalanceCalled = true;
417 }
418
419 public boolean wasBalanceCalled() {
420 return preBalanceCalled && postBalanceCalled;
421 }
422
423 public boolean preBalanceCalledOnly() {
424 return preBalanceCalled && !postBalanceCalled;
425 }
426
427 @Override
428 public boolean preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env, boolean b)
429 throws IOException {
430 if (bypass) {
431 env.bypass();
432 }
433 preBalanceSwitchCalled = true;
434 return b;
435 }
436
437 @Override
438 public void postBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env,
439 boolean oldValue, boolean newValue) throws IOException {
440 postBalanceSwitchCalled = true;
441 }
442
443 public boolean wasBalanceSwitchCalled() {
444 return preBalanceSwitchCalled && postBalanceSwitchCalled;
445 }
446
447 public boolean preBalanceSwitchCalledOnly() {
448 return preBalanceSwitchCalled && !postBalanceSwitchCalled;
449 }
450
451 @Override
452 public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> env)
453 throws IOException {
454 preShutdownCalled = true;
455 }
456
457 @Override
458 public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
459 throws IOException {
460 preStopMasterCalled = true;
461 }
462
463 @Override
464 public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
465 throws IOException {
466 postStartMasterCalled = true;
467 }
468
469 public boolean wasStartMasterCalled() {
470 return postStartMasterCalled;
471 }
472
473 @Override
474 public void start(CoprocessorEnvironment env) throws IOException {
475 startCalled = true;
476 }
477
478 @Override
479 public void stop(CoprocessorEnvironment env) throws IOException {
480 stopCalled = true;
481 }
482
483 public boolean wasStarted() { return startCalled; }
484
485 public boolean wasStopped() { return stopCalled; }
486
487 @Override
488 public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
489 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
490 throws IOException {
491 preSnapshotCalled = true;
492 }
493
494 @Override
495 public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
496 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
497 throws IOException {
498 postSnapshotCalled = true;
499 }
500
501 public boolean wasSnapshotCalled() {
502 return preSnapshotCalled && postSnapshotCalled;
503 }
504
505 @Override
506 public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
507 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
508 throws IOException {
509 preCloneSnapshotCalled = true;
510 }
511
512 @Override
513 public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
514 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
515 throws IOException {
516 postCloneSnapshotCalled = true;
517 }
518
519 public boolean wasCloneSnapshotCalled() {
520 return preCloneSnapshotCalled && postCloneSnapshotCalled;
521 }
522
523 @Override
524 public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
525 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
526 throws IOException {
527 preRestoreSnapshotCalled = true;
528 }
529
530 @Override
531 public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
532 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
533 throws IOException {
534 postRestoreSnapshotCalled = true;
535 }
536
537 public boolean wasRestoreSnapshotCalled() {
538 return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
539 }
540
541 @Override
542 public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
543 final SnapshotDescription snapshot) throws IOException {
544 preDeleteSnapshotCalled = true;
545 }
546
547 @Override
548 public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
549 final SnapshotDescription snapshot) throws IOException {
550 postDeleteSnapshotCalled = true;
551 }
552
553 public boolean wasDeleteSnapshotCalled() {
554 return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
555 }
556
557 @Override
558 public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
559 List<String> tableNamesList, List<HTableDescriptor> descriptors) throws IOException {
560 preGetTableDescriptorsCalled = true;
561 }
562
563 @Override
564 public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
565 List<HTableDescriptor> descriptors) throws IOException {
566 postGetTableDescriptorsCalled = true;
567 }
568
569 public boolean wasGetTableDescriptorsCalled() {
570 return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
571 }
572 }
573
574 private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
575 private static byte[] TEST_SNAPSHOT = Bytes.toBytes("observed_snapshot");
576 private static byte[] TEST_TABLE = Bytes.toBytes("observed_table");
577 private static byte[] TEST_CLONE = Bytes.toBytes("observed_clone");
578 private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
579 private static byte[] TEST_FAMILY2 = Bytes.toBytes("fam2");
580
581 @BeforeClass
582 public static void setupBeforeClass() throws Exception {
583 Configuration conf = UTIL.getConfiguration();
584 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
585 CPMasterObserver.class.getName());
586
587 conf.setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
588
589 UTIL.startMiniCluster(2);
590 }
591
592 @AfterClass
593 public static void tearDownAfterClass() throws Exception {
594 UTIL.shutdownMiniCluster();
595 }
596
597 @Test
598 public void testStarted() throws Exception {
599 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
600
601 HMaster master = cluster.getMaster();
602 assertTrue("Master should be active", master.isActiveMaster());
603 MasterCoprocessorHost host = master.getCoprocessorHost();
604 assertNotNull("CoprocessorHost should not be null", host);
605 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
606 CPMasterObserver.class.getName());
607 assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
608
609
610 assertTrue("MasterObserver should have been started", cp.wasStarted());
611 assertTrue("postStartMaster() hook should have been called",
612 cp.wasStartMasterCalled());
613 }
614
615 @Test
616 public void testTableOperations() throws Exception {
617 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
618
619 HMaster master = cluster.getMaster();
620 MasterCoprocessorHost host = master.getCoprocessorHost();
621 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
622 CPMasterObserver.class.getName());
623 cp.enableBypass(true);
624 cp.resetStates();
625 assertFalse("No table created yet", cp.wasCreateTableCalled());
626
627
628 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
629 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
630 HBaseAdmin admin = UTIL.getHBaseAdmin();
631
632 admin.createTable(htd);
633
634 assertTrue("Test table should be created", cp.wasCreateTableCalled());
635
636 admin.disableTable(TEST_TABLE);
637 assertTrue(admin.isTableDisabled(TEST_TABLE));
638
639 assertTrue("Coprocessor should have been called on table disable",
640 cp.wasDisableTableCalled());
641
642
643 assertFalse(cp.wasEnableTableCalled());
644 admin.enableTable(TEST_TABLE);
645 assertTrue(admin.isTableEnabled(TEST_TABLE));
646
647 assertTrue("Coprocessor should have been called on table enable",
648 cp.wasEnableTableCalled());
649
650 admin.disableTable(TEST_TABLE);
651 assertTrue(admin.isTableDisabled(TEST_TABLE));
652
653
654 htd.setMaxFileSize(512 * 1024 * 1024);
655 modifyTableSync(admin, TEST_TABLE, htd);
656
657 assertTrue("Test table should have been modified",
658 cp.wasModifyTableCalled());
659
660
661 admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
662 assertTrue("New column family shouldn't have been added to test table",
663 cp.preAddColumnCalledOnly());
664
665
666 HColumnDescriptor hcd1 = new HColumnDescriptor(TEST_FAMILY2);
667 hcd1.setMaxVersions(25);
668 admin.modifyColumn(TEST_TABLE, hcd1);
669 assertTrue("Second column family should be modified",
670 cp.preModifyColumnCalledOnly());
671
672
673 admin.deleteTable(TEST_TABLE);
674 assertFalse("Test table should have been deleted",
675 admin.tableExists(TEST_TABLE));
676
677 assertTrue("Coprocessor should have been called on table delete",
678 cp.wasDeleteTableCalled());
679
680
681
682 cp.enableBypass(false);
683 cp.resetStates();
684
685 admin.createTable(htd);
686 assertTrue("Test table should be created", cp.wasCreateTableCalled());
687
688
689 assertFalse(cp.wasDisableTableCalled());
690
691 admin.disableTable(TEST_TABLE);
692 assertTrue(admin.isTableDisabled(TEST_TABLE));
693 assertTrue("Coprocessor should have been called on table disable",
694 cp.wasDisableTableCalled());
695
696
697 htd.setMaxFileSize(512 * 1024 * 1024);
698 modifyTableSync(admin, TEST_TABLE, htd);
699 assertTrue("Test table should have been modified",
700 cp.wasModifyTableCalled());
701
702
703 admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
704 assertTrue("New column family should have been added to test table",
705 cp.wasAddColumnCalled());
706
707
708 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
709 hcd.setMaxVersions(25);
710 admin.modifyColumn(TEST_TABLE, hcd);
711 assertTrue("Second column family should be modified",
712 cp.wasModifyColumnCalled());
713
714
715 assertFalse(cp.wasEnableTableCalled());
716 admin.enableTable(TEST_TABLE);
717 assertTrue(admin.isTableEnabled(TEST_TABLE));
718 assertTrue("Coprocessor should have been called on table enable",
719 cp.wasEnableTableCalled());
720
721
722 admin.disableTable(TEST_TABLE);
723 assertTrue(admin.isTableDisabled(TEST_TABLE));
724
725
726 assertFalse("No column family deleted yet", cp.wasDeleteColumnCalled());
727 admin.deleteColumn(TEST_TABLE, TEST_FAMILY2);
728 HTableDescriptor tableDesc = admin.getTableDescriptor(TEST_TABLE);
729 assertNull("'"+Bytes.toString(TEST_FAMILY2)+"' should have been removed",
730 tableDesc.getFamily(TEST_FAMILY2));
731 assertTrue("Coprocessor should have been called on column delete",
732 cp.wasDeleteColumnCalled());
733
734
735 assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
736 admin.deleteTable(TEST_TABLE);
737 assertFalse("Test table should have been deleted",
738 admin.tableExists(TEST_TABLE));
739 assertTrue("Coprocessor should have been called on table delete",
740 cp.wasDeleteTableCalled());
741 }
742
743 private void modifyTableSync(HBaseAdmin admin, byte[] tableName, HTableDescriptor htd)
744 throws IOException {
745 admin.modifyTable(tableName, htd);
746
747 for (int t = 0; t < 100; t++) {
748 HTableDescriptor td = admin.getTableDescriptor(htd.getName());
749 if (td.equals(htd)) {
750 break;
751 }
752 Threads.sleep(100);
753 }
754 }
755
756 @Test
757 public void testRegionTransitionOperations() throws Exception {
758 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
759
760 HMaster master = cluster.getMaster();
761 MasterCoprocessorHost host = master.getCoprocessorHost();
762 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
763 CPMasterObserver.class.getName());
764 cp.enableBypass(false);
765 cp.resetStates();
766
767 HTable table = UTIL.createTable(TEST_TABLE, TEST_FAMILY);
768 UTIL.createMultiRegions(table, TEST_FAMILY);
769 UTIL.waitUntilAllRegionsAssigned(TEST_TABLE);
770
771 NavigableMap<HRegionInfo, ServerName> regions = table.getRegionLocations();
772 Map.Entry<HRegionInfo, ServerName> firstGoodPair = null;
773 for (Map.Entry<HRegionInfo, ServerName> e: regions.entrySet()) {
774 if (e.getValue() != null) {
775 firstGoodPair = e;
776 break;
777 }
778 }
779 assertNotNull("Found a non-null entry", firstGoodPair);
780 LOG.info("Found " + firstGoodPair.toString());
781
782 Collection<ServerName> servers = master.getClusterStatus().getServers();
783 String destName = null;
784 String firstRegionHostnamePortStr = firstGoodPair.getValue().toString();
785 LOG.info("firstRegionHostnamePortStr=" + firstRegionHostnamePortStr);
786 boolean found = false;
787
788 for (ServerName info : servers) {
789 LOG.info("ServerName=" + info);
790 if (!firstRegionHostnamePortStr.equals(info.getHostAndPort())) {
791 destName = info.toString();
792 found = true;
793 break;
794 }
795 }
796 assertTrue("Found server", found);
797 LOG.info("Found " + destName);
798 master.move(firstGoodPair.getKey().getEncodedNameAsBytes(),
799 Bytes.toBytes(destName));
800 assertTrue("Coprocessor should have been called on region move",
801 cp.wasMoveCalled());
802
803
804 master.balanceSwitch(true);
805 assertTrue("Coprocessor should have been called on balance switch",
806 cp.wasBalanceSwitchCalled());
807
808
809 master.balanceSwitch(false);
810
811 HRegionServer rs = cluster.getRegionServer(0);
812 byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
813
814 waitForRITtoBeZero(master);
815 List<HRegionInfo> openRegions = rs.getOnlineRegions();
816 int moveCnt = openRegions.size()/2;
817 for (int i=0; i<moveCnt; i++) {
818 HRegionInfo info = openRegions.get(i);
819 if (!info.isMetaTable()) {
820 master.move(openRegions.get(i).getEncodedNameAsBytes(), destRS);
821 }
822 }
823
824 waitForRITtoBeZero(master);
825
826 master.balanceSwitch(true);
827 boolean balanceRun = master.balance();
828 assertTrue("Coprocessor should be called on region rebalancing",
829 cp.wasBalanceCalled());
830 }
831
832 @Test
833 public void testSnapshotOperations() throws Exception {
834 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
835 HMaster master = cluster.getMaster();
836 MasterCoprocessorHost host = master.getCoprocessorHost();
837 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
838 CPMasterObserver.class.getName());
839 cp.resetStates();
840
841
842 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
843 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
844 HBaseAdmin admin = UTIL.getHBaseAdmin();
845
846
847 if (admin.tableExists(TEST_TABLE)) {
848 UTIL.deleteTable(TEST_TABLE);
849 }
850
851 admin.createTable(htd);
852 admin.disableTable(TEST_TABLE);
853 assertTrue(admin.isTableDisabled(TEST_TABLE));
854
855 try {
856
857 assertFalse("Coprocessor should not have been called yet",
858 cp.wasSnapshotCalled());
859 admin.snapshot(TEST_SNAPSHOT, TEST_TABLE);
860 assertTrue("Coprocessor should have been called on snapshot",
861 cp.wasSnapshotCalled());
862
863
864 admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
865 assertTrue("Coprocessor should have been called on snapshot clone",
866 cp.wasCloneSnapshotCalled());
867 assertFalse("Coprocessor restore should not have been called on snapshot clone",
868 cp.wasRestoreSnapshotCalled());
869 admin.disableTable(TEST_CLONE);
870 assertTrue(admin.isTableDisabled(TEST_TABLE));
871 admin.deleteTable(TEST_CLONE);
872
873
874 cp.resetStates();
875 admin.restoreSnapshot(TEST_SNAPSHOT);
876 assertTrue("Coprocessor should have been called on snapshot restore",
877 cp.wasRestoreSnapshotCalled());
878 assertFalse("Coprocessor clone should not have been called on snapshot restore",
879 cp.wasCloneSnapshotCalled());
880
881 admin.deleteSnapshot(TEST_SNAPSHOT);
882 assertTrue("Coprocessor should have been called on snapshot delete",
883 cp.wasDeleteSnapshotCalled());
884 } finally {
885 admin.deleteTable(TEST_TABLE);
886 }
887 }
888
889 private void waitForRITtoBeZero(HMaster master) throws IOException {
890
891 AssignmentManager mgr = master.getAssignmentManager();
892 Collection<AssignmentManager.RegionState> transRegions =
893 mgr.getRegionsInTransition().values();
894 for (AssignmentManager.RegionState state : transRegions) {
895 mgr.waitOnRegionToClearRegionsInTransition(state.getRegion());
896 }
897 }
898
899 @Test
900 public void testTableDescriptorsEnumeration() throws Exception {
901 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
902
903 HMaster master = cluster.getMaster();
904 MasterCoprocessorHost host = master.getCoprocessorHost();
905 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
906 CPMasterObserver.class.getName());
907 cp.resetStates();
908
909 master.getHTableDescriptors();
910
911 assertTrue("Coprocessor should be called on table descriptors request",
912 cp.wasGetTableDescriptorsCalled());
913 }
914
915 @org.junit.Rule
916 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
917 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
918 }
919