1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.coprocessor;
21
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.IOException;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.NavigableMap;
32 import java.util.concurrent.CountDownLatch;
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.CoprocessorEnvironment;
38 import org.apache.hadoop.hbase.HBaseTestingUtility;
39 import org.apache.hadoop.hbase.HColumnDescriptor;
40 import org.apache.hadoop.hbase.HRegionInfo;
41 import org.apache.hadoop.hbase.HTableDescriptor;
42 import org.apache.hadoop.hbase.testclassification.MediumTests;
43 import org.apache.hadoop.hbase.MiniHBaseCluster;
44 import org.apache.hadoop.hbase.NamespaceDescriptor;
45 import org.apache.hadoop.hbase.ServerName;
46 import org.apache.hadoop.hbase.TableName;
47 import org.apache.hadoop.hbase.client.Admin;
48 import org.apache.hadoop.hbase.client.HTable;
49 import org.apache.hadoop.hbase.master.AssignmentManager;
50 import org.apache.hadoop.hbase.master.HMaster;
51 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
52 import org.apache.hadoop.hbase.master.RegionPlan;
53 import org.apache.hadoop.hbase.master.RegionState;
54 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
55 import org.apache.hadoop.hbase.protobuf.RequestConverter;
56 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
57 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
58 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
59 import org.apache.hadoop.hbase.regionserver.HRegionServer;
60 import org.apache.hadoop.hbase.util.Bytes;
61 import org.apache.hadoop.hbase.util.Threads;
62 import org.junit.AfterClass;
63 import org.junit.BeforeClass;
64 import org.junit.Test;
65 import org.junit.experimental.categories.Category;
66
67
68
69
70
71 @Category(MediumTests.class)
72 public class TestMasterObserver {
73 private static final Log LOG = LogFactory.getLog(TestMasterObserver.class);
74
75 public static CountDownLatch tableCreationLatch = new CountDownLatch(1);
76
77 public static class CPMasterObserver implements MasterObserver {
78
79 private boolean bypass = false;
80 private boolean preCreateTableCalled;
81 private boolean postCreateTableCalled;
82 private boolean preDeleteTableCalled;
83 private boolean postDeleteTableCalled;
84 private boolean preTruncateTableCalled;
85 private boolean postTruncateTableCalled;
86 private boolean preModifyTableCalled;
87 private boolean postModifyTableCalled;
88 private boolean preCreateNamespaceCalled;
89 private boolean postCreateNamespaceCalled;
90 private boolean preDeleteNamespaceCalled;
91 private boolean postDeleteNamespaceCalled;
92 private boolean preModifyNamespaceCalled;
93 private boolean postModifyNamespaceCalled;
94 private boolean preGetNamespaceDescriptorCalled;
95 private boolean postGetNamespaceDescriptorCalled;
96 private boolean preListNamespaceDescriptorsCalled;
97 private boolean postListNamespaceDescriptorsCalled;
98 private boolean preAddColumnCalled;
99 private boolean postAddColumnCalled;
100 private boolean preModifyColumnCalled;
101 private boolean postModifyColumnCalled;
102 private boolean preDeleteColumnCalled;
103 private boolean postDeleteColumnCalled;
104 private boolean preEnableTableCalled;
105 private boolean postEnableTableCalled;
106 private boolean preDisableTableCalled;
107 private boolean postDisableTableCalled;
108 private boolean preMoveCalled;
109 private boolean postMoveCalled;
110 private boolean preAssignCalled;
111 private boolean postAssignCalled;
112 private boolean preUnassignCalled;
113 private boolean postUnassignCalled;
114 private boolean preRegionOfflineCalled;
115 private boolean postRegionOfflineCalled;
116 private boolean preBalanceCalled;
117 private boolean postBalanceCalled;
118 private boolean preBalanceSwitchCalled;
119 private boolean postBalanceSwitchCalled;
120 private boolean preShutdownCalled;
121 private boolean preStopMasterCalled;
122 private boolean preMasterInitializationCalled;
123 private boolean postStartMasterCalled;
124 private boolean startCalled;
125 private boolean stopCalled;
126 private boolean preSnapshotCalled;
127 private boolean postSnapshotCalled;
128 private boolean preCloneSnapshotCalled;
129 private boolean postCloneSnapshotCalled;
130 private boolean preRestoreSnapshotCalled;
131 private boolean postRestoreSnapshotCalled;
132 private boolean preDeleteSnapshotCalled;
133 private boolean postDeleteSnapshotCalled;
134 private boolean preCreateTableHandlerCalled;
135 private boolean postCreateTableHandlerCalled;
136 private boolean preDeleteTableHandlerCalled;
137 private boolean postDeleteTableHandlerCalled;
138 private boolean preTruncateTableHandlerCalled;
139 private boolean postTruncateTableHandlerCalled;
140 private boolean preAddColumnHandlerCalled;
141 private boolean postAddColumnHandlerCalled;
142 private boolean preModifyColumnHandlerCalled;
143 private boolean postModifyColumnHandlerCalled;
144 private boolean preDeleteColumnHandlerCalled;
145 private boolean postDeleteColumnHandlerCalled;
146 private boolean preEnableTableHandlerCalled;
147 private boolean postEnableTableHandlerCalled;
148 private boolean preDisableTableHandlerCalled;
149 private boolean postDisableTableHandlerCalled;
150 private boolean preModifyTableHandlerCalled;
151 private boolean postModifyTableHandlerCalled;
152 private boolean preGetTableDescriptorsCalled;
153 private boolean postGetTableDescriptorsCalled;
154 private boolean postGetTableNamesCalled;
155 private boolean preGetTableNamesCalled;
156
157 public void enableBypass(boolean bypass) {
158 this.bypass = bypass;
159 }
160
161 public void resetStates() {
162 preCreateTableCalled = false;
163 postCreateTableCalled = false;
164 preDeleteTableCalled = false;
165 postDeleteTableCalled = false;
166 preTruncateTableCalled = false;
167 postTruncateTableCalled = false;
168 preModifyTableCalled = false;
169 postModifyTableCalled = false;
170 preCreateNamespaceCalled = false;
171 postCreateNamespaceCalled = false;
172 preDeleteNamespaceCalled = false;
173 postDeleteNamespaceCalled = false;
174 preModifyNamespaceCalled = false;
175 postModifyNamespaceCalled = false;
176 preGetNamespaceDescriptorCalled = false;
177 postGetNamespaceDescriptorCalled = false;
178 preListNamespaceDescriptorsCalled = false;
179 postListNamespaceDescriptorsCalled = false;
180 preAddColumnCalled = false;
181 postAddColumnCalled = false;
182 preModifyColumnCalled = false;
183 postModifyColumnCalled = false;
184 preDeleteColumnCalled = false;
185 postDeleteColumnCalled = false;
186 preEnableTableCalled = false;
187 postEnableTableCalled = false;
188 preDisableTableCalled = false;
189 postDisableTableCalled = false;
190 preMoveCalled= false;
191 postMoveCalled = false;
192 preAssignCalled = false;
193 postAssignCalled = false;
194 preUnassignCalled = false;
195 postUnassignCalled = false;
196 preRegionOfflineCalled = false;
197 postRegionOfflineCalled = false;
198 preBalanceCalled = false;
199 postBalanceCalled = false;
200 preBalanceSwitchCalled = false;
201 postBalanceSwitchCalled = false;
202 preSnapshotCalled = false;
203 postSnapshotCalled = false;
204 preCloneSnapshotCalled = false;
205 postCloneSnapshotCalled = false;
206 preRestoreSnapshotCalled = false;
207 postRestoreSnapshotCalled = false;
208 preDeleteSnapshotCalled = false;
209 postDeleteSnapshotCalled = false;
210 preCreateTableHandlerCalled = false;
211 postCreateTableHandlerCalled = false;
212 preDeleteTableHandlerCalled = false;
213 postDeleteTableHandlerCalled = false;
214 preTruncateTableHandlerCalled = false;
215 postTruncateTableHandlerCalled = false;
216 preModifyTableHandlerCalled = false;
217 postModifyTableHandlerCalled = false;
218 preAddColumnHandlerCalled = false;
219 postAddColumnHandlerCalled = false;
220 preModifyColumnHandlerCalled = false;
221 postModifyColumnHandlerCalled = false;
222 preDeleteColumnHandlerCalled = false;
223 postDeleteColumnHandlerCalled = false;
224 preEnableTableHandlerCalled = false;
225 postEnableTableHandlerCalled = false;
226 preDisableTableHandlerCalled = false;
227 postDisableTableHandlerCalled = false;
228 preModifyTableHandlerCalled = false;
229 postModifyTableHandlerCalled = false;
230 preGetTableDescriptorsCalled = false;
231 postGetTableDescriptorsCalled = false;
232 postGetTableNamesCalled = false;
233 preGetTableNamesCalled = false;
234 }
235
236 @Override
237 public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
238 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
239 if (bypass) {
240 env.bypass();
241 }
242 preCreateTableCalled = true;
243 }
244
245 @Override
246 public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
247 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
248 postCreateTableCalled = true;
249 }
250
251 public boolean wasCreateTableCalled() {
252 return preCreateTableCalled && postCreateTableCalled;
253 }
254
255 public boolean preCreateTableCalledOnly() {
256 return preCreateTableCalled && !postCreateTableCalled;
257 }
258
259 @Override
260 public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
261 TableName tableName) throws IOException {
262 if (bypass) {
263 env.bypass();
264 }
265 preDeleteTableCalled = true;
266 }
267
268 @Override
269 public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
270 TableName tableName) throws IOException {
271 postDeleteTableCalled = true;
272 }
273
274 public boolean wasDeleteTableCalled() {
275 return preDeleteTableCalled && postDeleteTableCalled;
276 }
277
278 public boolean preDeleteTableCalledOnly() {
279 return preDeleteTableCalled && !postDeleteTableCalled;
280 }
281
282 @Override
283 public void preTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
284 TableName tableName) throws IOException {
285 if (bypass) {
286 env.bypass();
287 }
288 preTruncateTableCalled = true;
289 }
290
291 @Override
292 public void postTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
293 TableName tableName) throws IOException {
294 postTruncateTableCalled = true;
295 }
296
297 public boolean wasTruncateTableCalled() {
298 return preTruncateTableCalled && postTruncateTableCalled;
299 }
300
301 public boolean preTruncateTableCalledOnly() {
302 return preTruncateTableCalled && !postTruncateTableCalled;
303 }
304
305 @Override
306 public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
307 TableName tableName, HTableDescriptor htd) throws IOException {
308 if (bypass) {
309 env.bypass();
310 }else{
311 env.shouldBypass();
312 }
313 preModifyTableCalled = true;
314 }
315
316 @Override
317 public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
318 TableName tableName, HTableDescriptor htd) throws IOException {
319 postModifyTableCalled = true;
320 }
321
322 public boolean wasModifyTableCalled() {
323 return preModifyTableCalled && postModifyTableCalled;
324 }
325
326 public boolean preModifyTableCalledOnly() {
327 return preModifyTableCalled && !postModifyTableCalled;
328 }
329
330 @Override
331 public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
332 NamespaceDescriptor ns) throws IOException {
333 if (bypass) {
334 env.bypass();
335 }
336 preCreateNamespaceCalled = true;
337 }
338
339 @Override
340 public void postCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
341 NamespaceDescriptor ns) throws IOException {
342 postCreateNamespaceCalled = true;
343 }
344
345 public boolean wasCreateNamespaceCalled() {
346 return preCreateNamespaceCalled && postCreateNamespaceCalled;
347 }
348
349 public boolean preCreateNamespaceCalledOnly() {
350 return preCreateNamespaceCalled && !postCreateNamespaceCalled;
351 }
352
353 @Override
354 public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
355 String name) throws IOException {
356 if (bypass) {
357 env.bypass();
358 }
359 preDeleteNamespaceCalled = true;
360 }
361
362 @Override
363 public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
364 String name) throws IOException {
365 postDeleteNamespaceCalled = true;
366 }
367
368 public boolean wasDeleteNamespaceCalled() {
369 return preDeleteNamespaceCalled && postDeleteNamespaceCalled;
370 }
371
372 public boolean preDeleteNamespaceCalledOnly() {
373 return preDeleteNamespaceCalled && !postDeleteNamespaceCalled;
374 }
375
376 @Override
377 public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
378 NamespaceDescriptor ns) throws IOException {
379 if (bypass) {
380 env.bypass();
381 }
382 preModifyNamespaceCalled = true;
383 }
384
385 @Override
386 public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
387 NamespaceDescriptor ns) throws IOException {
388 postModifyNamespaceCalled = true;
389 }
390
391 public boolean wasModifyNamespaceCalled() {
392 return preModifyNamespaceCalled && postModifyNamespaceCalled;
393 }
394
395 public boolean preModifyNamespaceCalledOnly() {
396 return preModifyNamespaceCalled && !postModifyNamespaceCalled;
397 }
398
399
400 @Override
401 public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
402 String namespace) throws IOException {
403 preGetNamespaceDescriptorCalled = true;
404 }
405
406 @Override
407 public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
408 NamespaceDescriptor ns) throws IOException {
409 postGetNamespaceDescriptorCalled = true;
410 }
411
412 public boolean wasGetNamespaceDescriptorCalled() {
413 return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
414 }
415
416 @Override
417 public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
418 List<NamespaceDescriptor> descriptors) throws IOException {
419 if (bypass) {
420 env.bypass();
421 }
422 preListNamespaceDescriptorsCalled = true;
423 }
424
425 @Override
426 public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
427 List<NamespaceDescriptor> descriptors) throws IOException {
428 postListNamespaceDescriptorsCalled = true;
429 }
430
431 public boolean wasListNamespaceDescriptorsCalled() {
432 return preListNamespaceDescriptorsCalled && postListNamespaceDescriptorsCalled;
433 }
434
435 public boolean preListNamespaceDescriptorsCalledOnly() {
436 return preListNamespaceDescriptorsCalled && !postListNamespaceDescriptorsCalled;
437 }
438
439 @Override
440 public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
441 TableName tableName, HColumnDescriptor column) throws IOException {
442 if (bypass) {
443 env.bypass();
444 }else{
445 env.shouldBypass();
446 }
447
448 preAddColumnCalled = true;
449 }
450
451 @Override
452 public void postAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
453 TableName tableName, HColumnDescriptor column) throws IOException {
454 postAddColumnCalled = true;
455 }
456
457 public boolean wasAddColumnCalled() {
458 return preAddColumnCalled && postAddColumnCalled;
459 }
460
461 public boolean preAddColumnCalledOnly() {
462 return preAddColumnCalled && !postAddColumnCalled;
463 }
464
465 @Override
466 public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
467 TableName tableName, HColumnDescriptor descriptor) throws IOException {
468 if (bypass) {
469 env.bypass();
470 }
471 preModifyColumnCalled = true;
472 }
473
474 @Override
475 public void postModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
476 TableName tableName, HColumnDescriptor descriptor) throws IOException {
477 postModifyColumnCalled = true;
478 }
479
480 public boolean wasModifyColumnCalled() {
481 return preModifyColumnCalled && postModifyColumnCalled;
482 }
483
484 public boolean preModifyColumnCalledOnly() {
485 return preModifyColumnCalled && !postModifyColumnCalled;
486 }
487
488 @Override
489 public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
490 TableName tableName, byte[] c) throws IOException {
491 if (bypass) {
492 env.bypass();
493 }
494 preDeleteColumnCalled = true;
495 }
496
497 @Override
498 public void postDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
499 TableName tableName, byte[] c) throws IOException {
500 postDeleteColumnCalled = true;
501 }
502
503 public boolean wasDeleteColumnCalled() {
504 return preDeleteColumnCalled && postDeleteColumnCalled;
505 }
506
507 public boolean preDeleteColumnCalledOnly() {
508 return preDeleteColumnCalled && !postDeleteColumnCalled;
509 }
510
511 @Override
512 public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
513 TableName tableName) throws IOException {
514 if (bypass) {
515 env.bypass();
516 }
517 preEnableTableCalled = true;
518 }
519
520 @Override
521 public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
522 TableName tableName) throws IOException {
523 postEnableTableCalled = true;
524 }
525
526 public boolean wasEnableTableCalled() {
527 return preEnableTableCalled && postEnableTableCalled;
528 }
529
530 public boolean preEnableTableCalledOnly() {
531 return preEnableTableCalled && !postEnableTableCalled;
532 }
533
534 @Override
535 public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
536 TableName tableName) throws IOException {
537 if (bypass) {
538 env.bypass();
539 }
540 preDisableTableCalled = true;
541 }
542
543 @Override
544 public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
545 TableName tableName) throws IOException {
546 postDisableTableCalled = true;
547 }
548
549 public boolean wasDisableTableCalled() {
550 return preDisableTableCalled && postDisableTableCalled;
551 }
552
553 public boolean preDisableTableCalledOnly() {
554 return preDisableTableCalled && !postDisableTableCalled;
555 }
556
557 @Override
558 public void preMove(ObserverContext<MasterCoprocessorEnvironment> env,
559 HRegionInfo region, ServerName srcServer, ServerName destServer)
560 throws IOException {
561 if (bypass) {
562 env.bypass();
563 }
564 preMoveCalled = true;
565 }
566
567 @Override
568 public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, HRegionInfo region,
569 ServerName srcServer, ServerName destServer)
570 throws IOException {
571 postMoveCalled = true;
572 }
573
574 public boolean wasMoveCalled() {
575 return preMoveCalled && postMoveCalled;
576 }
577
578 public boolean preMoveCalledOnly() {
579 return preMoveCalled && !postMoveCalled;
580 }
581
582 @Override
583 public void preAssign(ObserverContext<MasterCoprocessorEnvironment> env,
584 final HRegionInfo regionInfo) throws IOException {
585 if (bypass) {
586 env.bypass();
587 }
588 preAssignCalled = true;
589 }
590
591 @Override
592 public void postAssign(ObserverContext<MasterCoprocessorEnvironment> env,
593 final HRegionInfo regionInfo) throws IOException {
594 postAssignCalled = true;
595 }
596
597 public boolean wasAssignCalled() {
598 return preAssignCalled && postAssignCalled;
599 }
600
601 public boolean preAssignCalledOnly() {
602 return preAssignCalled && !postAssignCalled;
603 }
604
605 @Override
606 public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
607 final HRegionInfo regionInfo, final boolean force) throws IOException {
608 if (bypass) {
609 env.bypass();
610 }
611 preUnassignCalled = true;
612 }
613
614 @Override
615 public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
616 final HRegionInfo regionInfo, final boolean force) throws IOException {
617 postUnassignCalled = true;
618 }
619
620 public boolean wasUnassignCalled() {
621 return preUnassignCalled && postUnassignCalled;
622 }
623
624 public boolean preUnassignCalledOnly() {
625 return preUnassignCalled && !postUnassignCalled;
626 }
627
628 @Override
629 public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
630 final HRegionInfo regionInfo) throws IOException {
631 preRegionOfflineCalled = true;
632 }
633
634 @Override
635 public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
636 final HRegionInfo regionInfo) throws IOException {
637 postRegionOfflineCalled = true;
638 }
639
640 public boolean wasRegionOfflineCalled() {
641 return preRegionOfflineCalled && postRegionOfflineCalled;
642 }
643
644 public boolean preRegionOfflineCalledOnly() {
645 return preRegionOfflineCalled && !postRegionOfflineCalled;
646 }
647
648 @Override
649 public void preBalance(ObserverContext<MasterCoprocessorEnvironment> env)
650 throws IOException {
651 if (bypass) {
652 env.bypass();
653 }
654 preBalanceCalled = true;
655 }
656
657 @Override
658 public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env,
659 List<RegionPlan> plans) throws IOException {
660 postBalanceCalled = true;
661 }
662
663 public boolean wasBalanceCalled() {
664 return preBalanceCalled && postBalanceCalled;
665 }
666
667 public boolean preBalanceCalledOnly() {
668 return preBalanceCalled && !postBalanceCalled;
669 }
670
671 @Override
672 public boolean preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env, boolean b)
673 throws IOException {
674 if (bypass) {
675 env.bypass();
676 }
677 preBalanceSwitchCalled = true;
678 return b;
679 }
680
681 @Override
682 public void postBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env,
683 boolean oldValue, boolean newValue) throws IOException {
684 postBalanceSwitchCalled = true;
685 }
686
687 public boolean wasBalanceSwitchCalled() {
688 return preBalanceSwitchCalled && postBalanceSwitchCalled;
689 }
690
691 public boolean preBalanceSwitchCalledOnly() {
692 return preBalanceSwitchCalled && !postBalanceSwitchCalled;
693 }
694
695 @Override
696 public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> env)
697 throws IOException {
698 preShutdownCalled = true;
699 }
700
701 @Override
702 public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
703 throws IOException {
704 preStopMasterCalled = true;
705 }
706
707 @Override
708 public void preMasterInitialization(
709 ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
710 preMasterInitializationCalled = true;
711 }
712
713 public boolean wasMasterInitializationCalled(){
714 return preMasterInitializationCalled;
715 }
716
717 @Override
718 public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
719 throws IOException {
720 postStartMasterCalled = true;
721 }
722
723 public boolean wasStartMasterCalled() {
724 return postStartMasterCalled;
725 }
726
727 @Override
728 public void start(CoprocessorEnvironment env) throws IOException {
729 startCalled = true;
730 }
731
732 @Override
733 public void stop(CoprocessorEnvironment env) throws IOException {
734 stopCalled = true;
735 }
736
737 public boolean wasStarted() { return startCalled; }
738
739 public boolean wasStopped() { return stopCalled; }
740
741 @Override
742 public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
743 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
744 throws IOException {
745 preSnapshotCalled = true;
746 }
747
748 @Override
749 public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
750 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
751 throws IOException {
752 postSnapshotCalled = true;
753 }
754
755 public boolean wasSnapshotCalled() {
756 return preSnapshotCalled && postSnapshotCalled;
757 }
758
759 @Override
760 public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
761 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
762 throws IOException {
763 preCloneSnapshotCalled = true;
764 }
765
766 @Override
767 public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
768 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
769 throws IOException {
770 postCloneSnapshotCalled = true;
771 }
772
773 public boolean wasCloneSnapshotCalled() {
774 return preCloneSnapshotCalled && postCloneSnapshotCalled;
775 }
776
777 @Override
778 public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
779 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
780 throws IOException {
781 preRestoreSnapshotCalled = true;
782 }
783
784 @Override
785 public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
786 final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
787 throws IOException {
788 postRestoreSnapshotCalled = true;
789 }
790
791 public boolean wasRestoreSnapshotCalled() {
792 return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
793 }
794
795 @Override
796 public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
797 final SnapshotDescription snapshot) throws IOException {
798 preDeleteSnapshotCalled = true;
799 }
800
801 @Override
802 public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
803 final SnapshotDescription snapshot) throws IOException {
804 postDeleteSnapshotCalled = true;
805 }
806
807 public boolean wasDeleteSnapshotCalled() {
808 return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
809 }
810
811 @Override
812 public void preCreateTableHandler(
813 ObserverContext<MasterCoprocessorEnvironment> env,
814 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
815 if (bypass) {
816 env.bypass();
817 }
818 preCreateTableHandlerCalled = true;
819 }
820
821 @Override
822 public void postCreateTableHandler(
823 ObserverContext<MasterCoprocessorEnvironment> ctx,
824 HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
825 postCreateTableHandlerCalled = true;
826 tableCreationLatch.countDown();
827 }
828
829 public boolean wasPreCreateTableHandlerCalled(){
830 return preCreateTableHandlerCalled;
831 }
832 public boolean wasCreateTableHandlerCalled() {
833 return preCreateTableHandlerCalled && postCreateTableHandlerCalled;
834 }
835
836 public boolean wasCreateTableHandlerCalledOnly() {
837 return preCreateTableHandlerCalled && !postCreateTableHandlerCalled;
838 }
839
840 @Override
841 public void preDeleteTableHandler(
842 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
843 throws IOException {
844 if (bypass) {
845 env.bypass();
846 }
847 preDeleteTableHandlerCalled = true;
848 }
849
850 @Override
851 public void postDeleteTableHandler(
852 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
853 throws IOException {
854 postDeleteTableHandlerCalled = true;
855 }
856
857 public boolean wasDeleteTableHandlerCalled() {
858 return preDeleteTableHandlerCalled && postDeleteTableHandlerCalled;
859 }
860
861 public boolean wasDeleteTableHandlerCalledOnly() {
862 return preDeleteTableHandlerCalled && !postDeleteTableHandlerCalled;
863 }
864
865 @Override
866 public void preTruncateTableHandler(
867 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
868 throws IOException {
869 if (bypass) {
870 env.bypass();
871 }
872 preTruncateTableHandlerCalled = true;
873 }
874
875 @Override
876 public void postTruncateTableHandler(
877 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
878 throws IOException {
879 postTruncateTableHandlerCalled = true;
880 }
881
882 public boolean wasTruncateTableHandlerCalled() {
883 return preTruncateTableHandlerCalled && postTruncateTableHandlerCalled;
884 }
885
886 public boolean wasTruncateTableHandlerCalledOnly() {
887 return preTruncateTableHandlerCalled && !postTruncateTableHandlerCalled;
888 }
889
890 @Override
891 public void preModifyTableHandler(
892 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
893 HTableDescriptor htd) throws IOException {
894 if (bypass) {
895 env.bypass();
896 }
897 preModifyTableHandlerCalled = true;
898 }
899
900 @Override
901 public void postModifyTableHandler(
902 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
903 HTableDescriptor htd) throws IOException {
904 postModifyTableHandlerCalled = true;
905 }
906
907 public boolean wasModifyTableHandlerCalled() {
908 return preModifyColumnHandlerCalled && postModifyColumnHandlerCalled;
909 }
910
911 public boolean wasModifyTableHandlerCalledOnly() {
912 return preModifyColumnHandlerCalled && !postModifyColumnHandlerCalled;
913 }
914
915 @Override
916 public void preAddColumnHandler(
917 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
918 HColumnDescriptor column) throws IOException {
919 if (bypass) {
920 env.bypass();
921 }
922 preAddColumnHandlerCalled = true;
923 }
924
925 @Override
926 public void postAddColumnHandler(
927 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
928 HColumnDescriptor column) throws IOException {
929 postAddColumnHandlerCalled = true;
930 }
931 public boolean wasAddColumnHandlerCalled() {
932 return preAddColumnHandlerCalled && postAddColumnHandlerCalled;
933 }
934
935 public boolean preAddColumnHandlerCalledOnly() {
936 return preAddColumnHandlerCalled && !postAddColumnHandlerCalled;
937 }
938
939 @Override
940 public void preModifyColumnHandler(
941 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
942 HColumnDescriptor descriptor) throws IOException {
943 if (bypass) {
944 env.bypass();
945 }
946 preModifyColumnHandlerCalled = true;
947 }
948
949 @Override
950 public void postModifyColumnHandler(
951 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
952 HColumnDescriptor descriptor) throws IOException {
953 postModifyColumnHandlerCalled = true;
954 }
955
956 public boolean wasModifyColumnHandlerCalled() {
957 return preModifyColumnHandlerCalled && postModifyColumnHandlerCalled;
958 }
959
960 public boolean preModifyColumnHandlerCalledOnly() {
961 return preModifyColumnHandlerCalled && !postModifyColumnHandlerCalled;
962 }
963 @Override
964 public void preDeleteColumnHandler(
965 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
966 byte[] c) throws IOException {
967 if (bypass) {
968 env.bypass();
969 }
970 preDeleteColumnHandlerCalled = true;
971 }
972
973 @Override
974 public void postDeleteColumnHandler(
975 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
976 byte[] c) throws IOException {
977 postDeleteColumnHandlerCalled = true;
978 }
979
980 public boolean wasDeleteColumnHandlerCalled() {
981 return preDeleteColumnHandlerCalled && postDeleteColumnHandlerCalled;
982 }
983
984 public boolean preDeleteColumnHandlerCalledOnly() {
985 return preDeleteColumnHandlerCalled && !postDeleteColumnHandlerCalled;
986 }
987
988 @Override
989 public void preEnableTableHandler(
990 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
991 throws IOException {
992 if (bypass) {
993 env.bypass();
994 }
995 preEnableTableHandlerCalled = true;
996 }
997
998 @Override
999 public void postEnableTableHandler(
1000 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
1001 throws IOException {
1002 postEnableTableHandlerCalled = true;
1003 }
1004
1005 public boolean wasEnableTableHandlerCalled() {
1006 return preEnableTableHandlerCalled && postEnableTableHandlerCalled;
1007 }
1008
1009 public boolean preEnableTableHandlerCalledOnly() {
1010 return preEnableTableHandlerCalled && !postEnableTableHandlerCalled;
1011 }
1012
1013 @Override
1014 public void preDisableTableHandler(
1015 ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
1016 throws IOException {
1017 if (bypass) {
1018 env.bypass();
1019 }
1020 preDisableTableHandlerCalled = true;
1021 }
1022
1023 @Override
1024 public void postDisableTableHandler(
1025 ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
1026 throws IOException {
1027 postDisableTableHandlerCalled = true;
1028 }
1029
1030 public boolean wasDisableTableHandlerCalled() {
1031 return preDisableTableHandlerCalled && postDisableTableHandlerCalled;
1032 }
1033
1034 public boolean preDisableTableHandlerCalledOnly() {
1035 return preDisableTableHandlerCalled && !postDisableTableHandlerCalled;
1036 }
1037
1038 @Override
1039 public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1040 List<TableName> tableNamesList, List<HTableDescriptor> descriptors) throws IOException {
1041 }
1042
1043 @Override
1044 public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1045 List<HTableDescriptor> descriptors) throws IOException {
1046 }
1047
1048 @Override
1049 public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1050 List<TableName> tableNamesList, List<HTableDescriptor> descriptors,
1051 String regex) throws IOException {
1052 preGetTableDescriptorsCalled = true;
1053 }
1054
1055 @Override
1056 public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1057 List<TableName> tableNamesList, List<HTableDescriptor> descriptors,
1058 String regex) throws IOException {
1059 postGetTableDescriptorsCalled = true;
1060 }
1061
1062 public boolean wasGetTableDescriptorsCalled() {
1063 return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
1064 }
1065
1066 @Override
1067 public void preGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1068 List<HTableDescriptor> descriptors, String regex) throws IOException {
1069 preGetTableNamesCalled = true;
1070 }
1071
1072 @Override
1073 public void postGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1074 List<HTableDescriptor> descriptors, String regex) throws IOException {
1075 postGetTableNamesCalled = true;
1076 }
1077
1078 public boolean wasGetTableNamesCalled() {
1079 return preGetTableNamesCalled && postGetTableNamesCalled;
1080 }
1081
1082 @Override
1083 public void preTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1084 TableName tableName) throws IOException {
1085 }
1086
1087 @Override
1088 public void postTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1089 TableName tableName) throws IOException {
1090 }
1091 }
1092
1093 private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
1094 private static byte[] TEST_SNAPSHOT = Bytes.toBytes("observed_snapshot");
1095 private static TableName TEST_TABLE = TableName.valueOf("observed_table");
1096 private static TableName TEST_CLONE = TableName.valueOf("observed_clone");
1097 private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
1098 private static byte[] TEST_FAMILY2 = Bytes.toBytes("fam2");
1099 private static byte[] TEST_FAMILY3 = Bytes.toBytes("fam3");
1100
1101 @BeforeClass
1102 public static void setupBeforeClass() throws Exception {
1103 Configuration conf = UTIL.getConfiguration();
1104 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
1105 CPMasterObserver.class.getName());
1106 conf.set("hbase.master.hfilecleaner.plugins",
1107 "org.apache.hadoop.hbase.master.cleaner.HFileLinkCleaner," +
1108 "org.apache.hadoop.hbase.master.snapshot.SnapshotHFileCleaner");
1109 conf.set("hbase.master.logcleaner.plugins",
1110 "org.apache.hadoop.hbase.master.snapshot.SnapshotLogCleaner");
1111
1112 UTIL.startMiniCluster(2);
1113 }
1114
1115 @AfterClass
1116 public static void tearDownAfterClass() throws Exception {
1117 UTIL.shutdownMiniCluster();
1118 }
1119
1120 @Test
1121 public void testStarted() throws Exception {
1122 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1123
1124 HMaster master = cluster.getMaster();
1125 assertTrue("Master should be active", master.isActiveMaster());
1126 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1127 assertNotNull("CoprocessorHost should not be null", host);
1128 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1129 CPMasterObserver.class.getName());
1130 assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
1131
1132
1133 assertTrue("MasterObserver should have been started", cp.wasStarted());
1134 assertTrue("preMasterInitialization() hook should have been called",
1135 cp.wasMasterInitializationCalled());
1136 assertTrue("postStartMaster() hook should have been called",
1137 cp.wasStartMasterCalled());
1138 }
1139
1140 @Test
1141 public void testTableOperations() throws Exception {
1142 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1143
1144 HMaster master = cluster.getMaster();
1145 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1146 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1147 CPMasterObserver.class.getName());
1148 cp.enableBypass(true);
1149 cp.resetStates();
1150 assertFalse("No table created yet", cp.wasCreateTableCalled());
1151
1152
1153 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
1154 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1155 Admin admin = UTIL.getHBaseAdmin();
1156
1157 tableCreationLatch = new CountDownLatch(1);
1158 admin.createTable(htd);
1159
1160 assertTrue("Test table should be created", cp.wasCreateTableCalled());
1161 tableCreationLatch.await();
1162 assertTrue("Table pre create handler called.", cp
1163 .wasPreCreateTableHandlerCalled());
1164 assertTrue("Table create handler should be called.",
1165 cp.wasCreateTableHandlerCalled());
1166
1167 tableCreationLatch = new CountDownLatch(1);
1168 admin.disableTable(TEST_TABLE);
1169 assertTrue(admin.isTableDisabled(TEST_TABLE));
1170
1171 assertTrue("Coprocessor should have been called on table disable",
1172 cp.wasDisableTableCalled());
1173 assertTrue("Disable table handler should be called.",
1174 cp.wasDisableTableHandlerCalled());
1175
1176
1177 assertFalse(cp.wasEnableTableCalled());
1178 admin.enableTable(TEST_TABLE);
1179 assertTrue(admin.isTableEnabled(TEST_TABLE));
1180
1181 assertTrue("Coprocessor should have been called on table enable",
1182 cp.wasEnableTableCalled());
1183 assertTrue("Enable table handler should be called.",
1184 cp.wasEnableTableHandlerCalled());
1185
1186 admin.disableTable(TEST_TABLE);
1187 assertTrue(admin.isTableDisabled(TEST_TABLE));
1188
1189
1190 htd.setMaxFileSize(512 * 1024 * 1024);
1191 modifyTableSync(admin, TEST_TABLE, htd);
1192
1193 assertTrue("Test table should have been modified",
1194 cp.wasModifyTableCalled());
1195
1196
1197 admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
1198 assertTrue("New column family shouldn't have been added to test table",
1199 cp.preAddColumnCalledOnly());
1200
1201
1202 HColumnDescriptor hcd1 = new HColumnDescriptor(TEST_FAMILY2);
1203 hcd1.setMaxVersions(25);
1204 admin.modifyColumn(TEST_TABLE, hcd1);
1205 assertTrue("Second column family should be modified",
1206 cp.preModifyColumnCalledOnly());
1207
1208
1209 admin.truncateTable(TEST_TABLE, false);
1210
1211
1212 admin.disableTable(TEST_TABLE);
1213 assertTrue(admin.isTableDisabled(TEST_TABLE));
1214 admin.deleteTable(TEST_TABLE);
1215 assertFalse("Test table should have been deleted",
1216 admin.tableExists(TEST_TABLE));
1217
1218 assertTrue("Coprocessor should have been called on table delete",
1219 cp.wasDeleteTableCalled());
1220 assertTrue("Delete table handler should be called.",
1221 cp.wasDeleteTableHandlerCalled());
1222
1223
1224 cp.enableBypass(false);
1225 cp.resetStates();
1226
1227 admin.createTable(htd);
1228 assertTrue("Test table should be created", cp.wasCreateTableCalled());
1229 tableCreationLatch.await();
1230 assertTrue("Table pre create handler called.", cp
1231 .wasPreCreateTableHandlerCalled());
1232 assertTrue("Table create handler should be called.",
1233 cp.wasCreateTableHandlerCalled());
1234
1235
1236 assertFalse(cp.wasDisableTableCalled());
1237 assertFalse(cp.wasDisableTableHandlerCalled());
1238 admin.disableTable(TEST_TABLE);
1239 assertTrue(admin.isTableDisabled(TEST_TABLE));
1240 assertTrue("Coprocessor should have been called on table disable",
1241 cp.wasDisableTableCalled());
1242 assertTrue("Disable table handler should be called.",
1243 cp.wasDisableTableHandlerCalled());
1244
1245
1246 htd.setMaxFileSize(512 * 1024 * 1024);
1247 modifyTableSync(admin, TEST_TABLE, htd);
1248 assertTrue("Test table should have been modified",
1249 cp.wasModifyTableCalled());
1250
1251 admin.addColumn(TEST_TABLE, new HColumnDescriptor(TEST_FAMILY2));
1252 assertTrue("New column family should have been added to test table",
1253 cp.wasAddColumnCalled());
1254 assertTrue("Add column handler should be called.",
1255 cp.wasAddColumnHandlerCalled());
1256
1257
1258 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
1259 hcd.setMaxVersions(25);
1260 admin.modifyColumn(TEST_TABLE, hcd);
1261 assertTrue("Second column family should be modified",
1262 cp.wasModifyColumnCalled());
1263 assertTrue("Modify table handler should be called.",
1264 cp.wasModifyColumnHandlerCalled());
1265
1266
1267 assertFalse(cp.wasEnableTableCalled());
1268 assertFalse(cp.wasEnableTableHandlerCalled());
1269 admin.enableTable(TEST_TABLE);
1270 assertTrue(admin.isTableEnabled(TEST_TABLE));
1271 assertTrue("Coprocessor should have been called on table enable",
1272 cp.wasEnableTableCalled());
1273 assertTrue("Enable table handler should be called.",
1274 cp.wasEnableTableHandlerCalled());
1275
1276
1277 admin.disableTable(TEST_TABLE);
1278 assertTrue(admin.isTableDisabled(TEST_TABLE));
1279
1280
1281 assertFalse("No column family deleted yet", cp.wasDeleteColumnCalled());
1282 assertFalse("Delete table column handler should not be called.",
1283 cp.wasDeleteColumnHandlerCalled());
1284 admin.deleteColumn(TEST_TABLE, TEST_FAMILY2);
1285 HTableDescriptor tableDesc = admin.getTableDescriptor(TEST_TABLE);
1286 assertNull("'"+Bytes.toString(TEST_FAMILY2)+"' should have been removed",
1287 tableDesc.getFamily(TEST_FAMILY2));
1288 assertTrue("Coprocessor should have been called on column delete",
1289 cp.wasDeleteColumnCalled());
1290 assertTrue("Delete table column handler should be called.",
1291 cp.wasDeleteColumnHandlerCalled());
1292
1293
1294 assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
1295 assertFalse("Delete table handler should not be called.",
1296 cp.wasDeleteTableHandlerCalled());
1297 admin.deleteTable(TEST_TABLE);
1298 assertFalse("Test table should have been deleted",
1299 admin.tableExists(TEST_TABLE));
1300 assertTrue("Coprocessor should have been called on table delete",
1301 cp.wasDeleteTableCalled());
1302 assertTrue("Delete table handler should be called.",
1303 cp.wasDeleteTableHandlerCalled());
1304 }
1305
1306 @Test
1307 public void testSnapshotOperations() throws Exception {
1308 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1309 HMaster master = cluster.getMaster();
1310 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1311 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1312 CPMasterObserver.class.getName());
1313 cp.resetStates();
1314
1315
1316 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
1317 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1318 Admin admin = UTIL.getHBaseAdmin();
1319
1320 tableCreationLatch = new CountDownLatch(1);
1321 admin.createTable(htd);
1322 tableCreationLatch.await();
1323 tableCreationLatch = new CountDownLatch(1);
1324
1325 admin.disableTable(TEST_TABLE);
1326 assertTrue(admin.isTableDisabled(TEST_TABLE));
1327
1328 try {
1329
1330 assertFalse("Coprocessor should not have been called yet",
1331 cp.wasSnapshotCalled());
1332 admin.snapshot(TEST_SNAPSHOT, TEST_TABLE);
1333 assertTrue("Coprocessor should have been called on snapshot",
1334 cp.wasSnapshotCalled());
1335
1336
1337 admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
1338 assertTrue("Coprocessor should have been called on snapshot clone",
1339 cp.wasCloneSnapshotCalled());
1340 assertFalse("Coprocessor restore should not have been called on snapshot clone",
1341 cp.wasRestoreSnapshotCalled());
1342 admin.disableTable(TEST_CLONE);
1343 assertTrue(admin.isTableDisabled(TEST_TABLE));
1344 admin.deleteTable(TEST_CLONE);
1345
1346
1347 cp.resetStates();
1348 admin.restoreSnapshot(TEST_SNAPSHOT);
1349 assertTrue("Coprocessor should have been called on snapshot restore",
1350 cp.wasRestoreSnapshotCalled());
1351 assertFalse("Coprocessor clone should not have been called on snapshot restore",
1352 cp.wasCloneSnapshotCalled());
1353
1354 admin.deleteSnapshot(TEST_SNAPSHOT);
1355 assertTrue("Coprocessor should have been called on snapshot delete",
1356 cp.wasDeleteSnapshotCalled());
1357 } finally {
1358 admin.deleteTable(TEST_TABLE);
1359 }
1360 }
1361
1362 @Test
1363 public void testNamespaceOperations() throws Exception {
1364 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1365 String testNamespace = "observed_ns";
1366 HMaster master = cluster.getMaster();
1367 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1368 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1369 CPMasterObserver.class.getName());
1370
1371 cp.enableBypass(false);
1372 cp.resetStates();
1373
1374
1375
1376 Admin admin = UTIL.getHBaseAdmin();
1377 admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1378 assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
1379
1380 assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1381 assertTrue("Test namespace descriptor should have been called",
1382 cp.wasGetNamespaceDescriptorCalled());
1383
1384
1385 cp.enableBypass(true);
1386 cp.resetStates();
1387
1388 admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
1389 assertTrue("Test namespace should not have been modified",
1390 cp.preModifyNamespaceCalledOnly());
1391
1392 assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1393 assertTrue("Test namespace descriptor should have been called",
1394 cp.wasGetNamespaceDescriptorCalled());
1395
1396 admin.deleteNamespace(testNamespace);
1397 assertTrue("Test namespace should not have been deleted", cp.preDeleteNamespaceCalledOnly());
1398
1399 assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1400 assertTrue("Test namespace descriptor should have been called",
1401 cp.wasGetNamespaceDescriptorCalled());
1402
1403 cp.enableBypass(false);
1404 cp.resetStates();
1405
1406
1407 admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
1408 assertTrue("Test namespace should have been modified", cp.wasModifyNamespaceCalled());
1409
1410 admin.deleteNamespace(testNamespace);
1411 assertTrue("Test namespace should have been deleted", cp.wasDeleteNamespaceCalled());
1412
1413 cp.enableBypass(true);
1414 cp.resetStates();
1415
1416 admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1417 assertTrue("Test namespace should not be created", cp.preCreateNamespaceCalledOnly());
1418
1419
1420 cp.enableBypass(true);
1421 cp.resetStates();
1422
1423 admin.listNamespaceDescriptors();
1424 assertTrue("post listNamespace should not have been called",
1425 cp.preListNamespaceDescriptorsCalledOnly());
1426
1427
1428 cp.enableBypass(false);
1429 cp.resetStates();
1430
1431 admin.listNamespaceDescriptors();
1432 assertTrue("post listNamespace should have been called",
1433 cp.wasListNamespaceDescriptorsCalled());
1434 }
1435
1436 private void modifyTableSync(Admin admin, TableName tableName, HTableDescriptor htd)
1437 throws IOException {
1438 admin.modifyTable(tableName, htd);
1439
1440 for (int t = 0; t < 100; t++) {
1441 HTableDescriptor td = admin.getTableDescriptor(htd.getTableName());
1442 if (td.equals(htd)) {
1443 break;
1444 }
1445 Threads.sleep(100);
1446 }
1447 }
1448
1449 @Test
1450 public void testRegionTransitionOperations() throws Exception {
1451 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1452
1453 HMaster master = cluster.getMaster();
1454 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1455 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1456 CPMasterObserver.class.getName());
1457 cp.enableBypass(false);
1458 cp.resetStates();
1459
1460 HTable table = UTIL.createTable(TEST_TABLE, TEST_FAMILY);
1461
1462 try {
1463 UTIL.createMultiRegions(table, TEST_FAMILY);
1464 UTIL.waitUntilAllRegionsAssigned(TEST_TABLE);
1465
1466 NavigableMap<HRegionInfo, ServerName> regions = table.getRegionLocations();
1467 Map.Entry<HRegionInfo, ServerName> firstGoodPair = null;
1468 for (Map.Entry<HRegionInfo, ServerName> e: regions.entrySet()) {
1469 if (e.getValue() != null) {
1470 firstGoodPair = e;
1471 break;
1472 }
1473 }
1474 assertNotNull("Found a non-null entry", firstGoodPair);
1475 LOG.info("Found " + firstGoodPair.toString());
1476
1477 Collection<ServerName> servers = master.getClusterStatus().getServers();
1478 String destName = null;
1479 String serverNameForFirstRegion = firstGoodPair.getValue().toString();
1480 LOG.info("serverNameForFirstRegion=" + serverNameForFirstRegion);
1481 ServerName masterServerName = master.getServerName();
1482 boolean found = false;
1483
1484 for (ServerName info : servers) {
1485 LOG.info("ServerName=" + info);
1486 if (!serverNameForFirstRegion.equals(info.getServerName())
1487 && !masterServerName.equals(info)) {
1488 destName = info.toString();
1489 found = true;
1490 break;
1491 }
1492 }
1493 assertTrue("Found server", found);
1494 LOG.info("Found " + destName);
1495 master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1496 firstGoodPair.getKey().getEncodedNameAsBytes(),Bytes.toBytes(destName)));
1497 assertTrue("Coprocessor should have been called on region move",
1498 cp.wasMoveCalled());
1499
1500
1501 master.balanceSwitch(true);
1502 assertTrue("Coprocessor should have been called on balance switch",
1503 cp.wasBalanceSwitchCalled());
1504
1505
1506 master.balanceSwitch(false);
1507
1508
1509 AssignmentManager mgr = master.getAssignmentManager();
1510 Collection<RegionState> transRegions =
1511 mgr.getRegionStates().getRegionsInTransition().values();
1512 for (RegionState state : transRegions) {
1513 mgr.getRegionStates().waitOnRegionToClearRegionsInTransition(state.getRegion());
1514 }
1515
1516
1517 HRegionServer rs = cluster.getRegionServer(0);
1518 byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
1519
1520 waitForRITtoBeZero(master);
1521 List<HRegionInfo> openRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
1522 int moveCnt = openRegions.size()/2;
1523 for (int i=0; i<moveCnt; i++) {
1524 HRegionInfo info = openRegions.get(i);
1525 if (!info.isMetaTable()) {
1526 master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1527 openRegions.get(i).getEncodedNameAsBytes(), destRS));
1528 }
1529 }
1530
1531 waitForRITtoBeZero(master);
1532
1533 master.balanceSwitch(true);
1534 boolean balanceRun = master.balance();
1535 assertTrue("Coprocessor should be called on region rebalancing",
1536 cp.wasBalanceCalled());
1537 } finally {
1538 UTIL.deleteTable(TEST_TABLE);
1539 }
1540 }
1541
1542 private void waitForRITtoBeZero(HMaster master) throws Exception {
1543
1544 AssignmentManager mgr = master.getAssignmentManager();
1545 Collection<RegionState> transRegions =
1546 mgr.getRegionStates().getRegionsInTransition().values();
1547 for (RegionState state : transRegions) {
1548 mgr.getRegionStates().waitOnRegionToClearRegionsInTransition(state.getRegion());
1549 }
1550 }
1551
1552 @Test
1553 public void testTableDescriptorsEnumeration() throws Exception {
1554 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1555
1556 HMaster master = cluster.getMaster();
1557 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1558 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1559 CPMasterObserver.class.getName());
1560 cp.resetStates();
1561
1562 GetTableDescriptorsRequest req =
1563 RequestConverter.buildGetTableDescriptorsRequest((List<TableName>)null);
1564 master.getMasterRpcServices().getTableDescriptors(null, req);
1565
1566 assertTrue("Coprocessor should be called on table descriptors request",
1567 cp.wasGetTableDescriptorsCalled());
1568 }
1569
1570 @Test
1571 public void testTableNamesEnumeration() throws Exception {
1572 MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1573
1574 HMaster master = cluster.getMaster();
1575 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1576 CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1577 CPMasterObserver.class.getName());
1578 cp.resetStates();
1579
1580 master.getMasterRpcServices().getTableNames(null,
1581 GetTableNamesRequest.newBuilder().build());
1582 assertTrue("Coprocessor should be called on table names request",
1583 cp.wasGetTableNamesCalled());
1584 }
1585 }