View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
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.Arrays;
29  import java.util.Collection;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.NavigableMap;
33  import java.util.Set;
34  import java.util.concurrent.CountDownLatch;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.hadoop.conf.Configuration;
39  import org.apache.hadoop.hbase.ClusterStatus;
40  import org.apache.hadoop.hbase.CoprocessorEnvironment;
41  import org.apache.hadoop.hbase.HBaseTestingUtility;
42  import org.apache.hadoop.hbase.HColumnDescriptor;
43  import org.apache.hadoop.hbase.HRegionInfo;
44  import org.apache.hadoop.hbase.HRegionLocation;
45  import org.apache.hadoop.hbase.HTableDescriptor;
46  import org.apache.hadoop.hbase.MiniHBaseCluster;
47  import org.apache.hadoop.hbase.NamespaceDescriptor;
48  import org.apache.hadoop.hbase.ProcedureInfo;
49  import org.apache.hadoop.hbase.ServerName;
50  import org.apache.hadoop.hbase.TableName;
51  import org.apache.hadoop.hbase.client.Admin;
52  import org.apache.hadoop.hbase.client.Connection;
53  import org.apache.hadoop.hbase.client.ConnectionFactory;
54  import org.apache.hadoop.hbase.client.HTable;
55  import org.apache.hadoop.hbase.client.RegionLocator;
56  import org.apache.hadoop.hbase.master.HMaster;
57  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
58  import org.apache.hadoop.hbase.master.RegionPlan;
59  import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
60  import org.apache.hadoop.hbase.net.Address;
61  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
62  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
63  import org.apache.hadoop.hbase.protobuf.RequestConverter;
64  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
65  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
66  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
67  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
68  import org.apache.hadoop.hbase.regionserver.HRegionServer;
69  import org.apache.hadoop.hbase.testclassification.MediumTests;
70  import org.apache.hadoop.hbase.util.Bytes;
71  import org.apache.hadoop.hbase.util.Threads;
72  import org.junit.AfterClass;
73  import org.junit.BeforeClass;
74  import org.junit.Rule;
75  import org.junit.Test;
76  import org.junit.experimental.categories.Category;
77  import org.junit.rules.TestName;
78  
79  /**
80   * Tests invocation of the {@link org.apache.hadoop.hbase.coprocessor.MasterObserver}
81   * interface hooks at all appropriate times during normal HMaster operations.
82   */
83  @Category(MediumTests.class)
84  public class TestMasterObserver {
85    private static final Log LOG = LogFactory.getLog(TestMasterObserver.class);
86  
87    public static CountDownLatch tableCreationLatch = new CountDownLatch(1);
88    public static CountDownLatch tableDeletionLatch = new CountDownLatch(1);
89  
90    public static class CPMasterObserver implements MasterObserver {
91  
92      private boolean bypass = false;
93      private boolean preCreateTableCalled;
94      private boolean postCreateTableCalled;
95      private boolean preDeleteTableCalled;
96      private boolean postDeleteTableCalled;
97      private boolean preTruncateTableCalled;
98      private boolean postTruncateTableCalled;
99      private boolean preModifyTableCalled;
100     private boolean postModifyTableCalled;
101     private boolean preCreateNamespaceCalled;
102     private boolean postCreateNamespaceCalled;
103     private boolean preDeleteNamespaceCalled;
104     private boolean postDeleteNamespaceCalled;
105     private boolean preModifyNamespaceCalled;
106     private boolean postModifyNamespaceCalled;
107     private boolean preGetNamespaceDescriptorCalled;
108     private boolean postGetNamespaceDescriptorCalled;
109     private boolean preListNamespaceDescriptorsCalled;
110     private boolean postListNamespaceDescriptorsCalled;
111     private boolean preAddColumnCalled;
112     private boolean postAddColumnCalled;
113     private boolean preModifyColumnCalled;
114     private boolean postModifyColumnCalled;
115     private boolean preDeleteColumnCalled;
116     private boolean postDeleteColumnCalled;
117     private boolean preEnableTableCalled;
118     private boolean postEnableTableCalled;
119     private boolean preDisableTableCalled;
120     private boolean postDisableTableCalled;
121     private boolean preMoveCalled;
122     private boolean postMoveCalled;
123     private boolean preAssignCalled;
124     private boolean postAssignCalled;
125     private boolean preUnassignCalled;
126     private boolean postUnassignCalled;
127     private boolean preRegionOfflineCalled;
128     private boolean postRegionOfflineCalled;
129     private boolean preBalanceCalled;
130     private boolean postBalanceCalled;
131     private boolean preBalanceSwitchCalled;
132     private boolean postBalanceSwitchCalled;
133     private boolean preShutdownCalled;
134     private boolean preStopMasterCalled;
135     private boolean preMasterInitializationCalled;
136     private boolean postStartMasterCalled;
137     private boolean startCalled;
138     private boolean stopCalled;
139     private boolean preSnapshotCalled;
140     private boolean postSnapshotCalled;
141     private boolean preListSnapshotCalled;
142     private boolean postListSnapshotCalled;
143     private boolean preCloneSnapshotCalled;
144     private boolean postCloneSnapshotCalled;
145     private boolean preRestoreSnapshotCalled;
146     private boolean postRestoreSnapshotCalled;
147     private boolean preDeleteSnapshotCalled;
148     private boolean postDeleteSnapshotCalled;
149     private boolean preCreateTableHandlerCalled;
150     private boolean postCreateTableHandlerCalled;
151     private boolean preDeleteTableHandlerCalled;
152     private boolean postDeleteTableHandlerCalled;
153     private boolean preTruncateTableHandlerCalled;
154     private boolean postTruncateTableHandlerCalled;
155     private boolean preAddColumnHandlerCalled;
156     private boolean postAddColumnHandlerCalled;
157     private boolean preModifyColumnHandlerCalled;
158     private boolean postModifyColumnHandlerCalled;
159     private boolean preDeleteColumnHandlerCalled;
160     private boolean postDeleteColumnHandlerCalled;
161     private boolean preEnableTableHandlerCalled;
162     private boolean postEnableTableHandlerCalled;
163     private boolean preDisableTableHandlerCalled;
164     private boolean postDisableTableHandlerCalled;
165     private boolean preModifyTableHandlerCalled;
166     private boolean postModifyTableHandlerCalled;
167     private boolean preAbortProcedureCalled;
168     private boolean postAbortProcedureCalled;
169     private boolean preListProceduresCalled;
170     private boolean postListProceduresCalled;
171     private boolean preGetTableDescriptorsCalled;
172     private boolean postGetTableDescriptorsCalled;
173     private boolean postGetTableNamesCalled;
174     private boolean preGetTableNamesCalled;
175     private boolean preDispatchMergeCalled;
176     private boolean postDispatchMergeCalled;
177 
178     public void enableBypass(boolean bypass) {
179       this.bypass = bypass;
180     }
181 
182     public void resetStates() {
183       preCreateTableCalled = false;
184       postCreateTableCalled = false;
185       preDeleteTableCalled = false;
186       postDeleteTableCalled = false;
187       preTruncateTableCalled = false;
188       postTruncateTableCalled = false;
189       preModifyTableCalled = false;
190       postModifyTableCalled = false;
191       preCreateNamespaceCalled = false;
192       postCreateNamespaceCalled = false;
193       preDeleteNamespaceCalled = false;
194       postDeleteNamespaceCalled = false;
195       preModifyNamespaceCalled = false;
196       postModifyNamespaceCalled = false;
197       preGetNamespaceDescriptorCalled = false;
198       postGetNamespaceDescriptorCalled = false;
199       preListNamespaceDescriptorsCalled = false;
200       postListNamespaceDescriptorsCalled = false;
201       preAddColumnCalled = false;
202       postAddColumnCalled = false;
203       preModifyColumnCalled = false;
204       postModifyColumnCalled = false;
205       preDeleteColumnCalled = false;
206       postDeleteColumnCalled = false;
207       preEnableTableCalled = false;
208       postEnableTableCalled = false;
209       preDisableTableCalled = false;
210       postDisableTableCalled = false;
211       preAbortProcedureCalled = false;
212       postAbortProcedureCalled = false;
213       preListProceduresCalled = false;
214       postListProceduresCalled = false;
215       preMoveCalled= false;
216       postMoveCalled = false;
217       preAssignCalled = false;
218       postAssignCalled = false;
219       preUnassignCalled = false;
220       postUnassignCalled = false;
221       preRegionOfflineCalled = false;
222       postRegionOfflineCalled = false;
223       preBalanceCalled = false;
224       postBalanceCalled = false;
225       preBalanceSwitchCalled = false;
226       postBalanceSwitchCalled = false;
227       preSnapshotCalled = false;
228       postSnapshotCalled = false;
229       preListSnapshotCalled = false;
230       postListSnapshotCalled = false;
231       preCloneSnapshotCalled = false;
232       postCloneSnapshotCalled = false;
233       preRestoreSnapshotCalled = false;
234       postRestoreSnapshotCalled = false;
235       preDeleteSnapshotCalled = false;
236       postDeleteSnapshotCalled = false;
237       preCreateTableHandlerCalled = false;
238       postCreateTableHandlerCalled = false;
239       preDeleteTableHandlerCalled = false;
240       postDeleteTableHandlerCalled = false;
241       preTruncateTableHandlerCalled = false;
242       postTruncateTableHandlerCalled = false;
243       preModifyTableHandlerCalled = false;
244       postModifyTableHandlerCalled = false;
245       preAddColumnHandlerCalled = false;
246       postAddColumnHandlerCalled = false;
247       preModifyColumnHandlerCalled = false;
248       postModifyColumnHandlerCalled = false;
249       preDeleteColumnHandlerCalled = false;
250       postDeleteColumnHandlerCalled = false;
251       preEnableTableHandlerCalled = false;
252       postEnableTableHandlerCalled = false;
253       preDisableTableHandlerCalled = false;
254       postDisableTableHandlerCalled = false;
255       preGetTableDescriptorsCalled = false;
256       postGetTableDescriptorsCalled = false;
257       postGetTableNamesCalled = false;
258       preGetTableNamesCalled = false;
259       preDispatchMergeCalled = false;
260       postDispatchMergeCalled = false;
261     }
262 
263     @Override
264     public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
265         HRegionInfo regionA, HRegionInfo regionB) throws IOException {
266       preDispatchMergeCalled = true;
267     }
268 
269     @Override
270     public void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
271         HRegionInfo regionA, HRegionInfo regionB) throws IOException {
272       postDispatchMergeCalled = true;
273     }
274 
275     @Override
276     public void preGetClusterStatus(ObserverContext<MasterCoprocessorEnvironment> ctx)
277         throws IOException {
278     }
279 
280     @Override
281     public void postGetClusterStatus(ObserverContext<MasterCoprocessorEnvironment> ctx,
282         ClusterStatus status) throws IOException {
283     }
284 
285     @Override
286     public void preClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx)
287         throws IOException {
288     }
289 
290     @Override
291     public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
292         List<ServerName> servers, List<ServerName> notClearedServers) throws IOException {
293     }
294 
295     public boolean wasDispatchMergeCalled() {
296       return preDispatchMergeCalled && postDispatchMergeCalled;
297     }
298 
299     @Override
300     public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
301         HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
302       if (bypass) {
303         env.bypass();
304       }
305       preCreateTableCalled = true;
306     }
307 
308     @Override
309     public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
310         HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
311       postCreateTableCalled = true;
312     }
313 
314     public boolean wasCreateTableCalled() {
315       return preCreateTableCalled && postCreateTableCalled;
316     }
317 
318     public boolean preCreateTableCalledOnly() {
319       return preCreateTableCalled && !postCreateTableCalled;
320     }
321 
322     @Override
323     public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
324         TableName tableName) throws IOException {
325       if (bypass) {
326         env.bypass();
327       }
328       preDeleteTableCalled = true;
329     }
330 
331     @Override
332     public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
333         TableName tableName) throws IOException {
334       postDeleteTableCalled = true;
335     }
336 
337     public boolean wasDeleteTableCalled() {
338       return preDeleteTableCalled && postDeleteTableCalled;
339     }
340 
341     public boolean preDeleteTableCalledOnly() {
342       return preDeleteTableCalled && !postDeleteTableCalled;
343     }
344 
345     @Override
346     public void preTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
347         TableName tableName) throws IOException {
348       if (bypass) {
349         env.bypass();
350       }
351       preTruncateTableCalled = true;
352     }
353 
354     @Override
355     public void postTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
356         TableName tableName) throws IOException {
357       postTruncateTableCalled = true;
358     }
359 
360     public boolean wasTruncateTableCalled() {
361       return preTruncateTableCalled && postTruncateTableCalled;
362     }
363 
364     public boolean preTruncateTableCalledOnly() {
365       return preTruncateTableCalled && !postTruncateTableCalled;
366     }
367 
368     @Override
369     public boolean preSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
370         final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException {
371       return false;
372     }
373 
374     @Override
375     public void postSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
376         final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException {
377     }
378 
379     @Override
380     public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
381         TableName tableName, HTableDescriptor htd) throws IOException {
382       if (bypass) {
383         env.bypass();
384       }else{
385         env.shouldBypass();
386       }
387       preModifyTableCalled = true;
388     }
389 
390     @Override
391     public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
392         TableName tableName, HTableDescriptor htd) throws IOException {
393       postModifyTableCalled = true;
394     }
395 
396     public boolean wasModifyTableCalled() {
397       return preModifyTableCalled && postModifyTableCalled;
398     }
399 
400     public boolean preModifyTableCalledOnly() {
401       return preModifyTableCalled && !postModifyTableCalled;
402     }
403 
404     @Override
405     public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
406         NamespaceDescriptor ns) throws IOException {
407       if (bypass) {
408         env.bypass();
409       }
410       preCreateNamespaceCalled = true;
411     }
412 
413     @Override
414     public void postCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
415         NamespaceDescriptor ns) throws IOException {
416       postCreateNamespaceCalled = true;
417     }
418 
419     public boolean wasCreateNamespaceCalled() {
420       return preCreateNamespaceCalled && postCreateNamespaceCalled;
421     }
422 
423     public boolean preCreateNamespaceCalledOnly() {
424       return preCreateNamespaceCalled && !postCreateNamespaceCalled;
425     }
426 
427     @Override
428     public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
429         String name) throws IOException {
430       if (bypass) {
431         env.bypass();
432       }
433       preDeleteNamespaceCalled = true;
434     }
435 
436     @Override
437     public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
438         String name) throws IOException {
439       postDeleteNamespaceCalled = true;
440     }
441 
442     public boolean wasDeleteNamespaceCalled() {
443       return preDeleteNamespaceCalled && postDeleteNamespaceCalled;
444     }
445 
446     public boolean preDeleteNamespaceCalledOnly() {
447       return preDeleteNamespaceCalled && !postDeleteNamespaceCalled;
448     }
449 
450     @Override
451     public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
452         NamespaceDescriptor ns) throws IOException {
453       if (bypass) {
454         env.bypass();
455       }
456       preModifyNamespaceCalled = true;
457     }
458 
459     @Override
460     public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
461         NamespaceDescriptor ns) throws IOException {
462       postModifyNamespaceCalled = true;
463     }
464 
465     public boolean wasModifyNamespaceCalled() {
466       return preModifyNamespaceCalled && postModifyNamespaceCalled;
467     }
468 
469     public boolean preModifyNamespaceCalledOnly() {
470       return preModifyNamespaceCalled && !postModifyNamespaceCalled;
471     }
472 
473 
474     @Override
475     public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
476         String namespace) throws IOException {
477       preGetNamespaceDescriptorCalled = true;
478     }
479 
480     @Override
481     public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
482         NamespaceDescriptor ns) throws IOException {
483       postGetNamespaceDescriptorCalled = true;
484     }
485 
486     public boolean wasGetNamespaceDescriptorCalled() {
487       return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
488     }
489 
490     @Override
491     public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
492         List<NamespaceDescriptor> descriptors) throws IOException {
493       if (bypass) {
494         env.bypass();
495       }
496       preListNamespaceDescriptorsCalled = true;
497     }
498 
499     @Override
500     public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
501         List<NamespaceDescriptor> descriptors) throws IOException {
502       postListNamespaceDescriptorsCalled = true;
503     }
504 
505     public boolean wasListNamespaceDescriptorsCalled() {
506       return preListNamespaceDescriptorsCalled && postListNamespaceDescriptorsCalled;
507     }
508 
509     public boolean preListNamespaceDescriptorsCalledOnly() {
510       return preListNamespaceDescriptorsCalled && !postListNamespaceDescriptorsCalled;
511     }
512 
513     @Override
514     public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
515         TableName tableName, HColumnDescriptor column) throws IOException {
516       if (bypass) {
517         env.bypass();
518       }else{
519         env.shouldBypass();
520       }
521 
522       preAddColumnCalled = true;
523     }
524 
525     @Override
526     public void postAddColumn(ObserverContext<MasterCoprocessorEnvironment> env,
527         TableName tableName, HColumnDescriptor column) throws IOException {
528       postAddColumnCalled = true;
529     }
530 
531     public boolean wasAddColumnCalled() {
532       return preAddColumnCalled && postAddColumnCalled;
533     }
534 
535     public boolean preAddColumnCalledOnly() {
536       return preAddColumnCalled && !postAddColumnCalled;
537     }
538 
539     @Override
540     public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
541         TableName tableName, HColumnDescriptor descriptor) throws IOException {
542       if (bypass) {
543         env.bypass();
544       }
545       preModifyColumnCalled = true;
546     }
547 
548     @Override
549     public void postModifyColumn(ObserverContext<MasterCoprocessorEnvironment> env,
550         TableName tableName, HColumnDescriptor descriptor) throws IOException {
551       postModifyColumnCalled = true;
552     }
553 
554     public boolean wasModifyColumnCalled() {
555       return preModifyColumnCalled && postModifyColumnCalled;
556     }
557 
558     public boolean preModifyColumnCalledOnly() {
559       return preModifyColumnCalled && !postModifyColumnCalled;
560     }
561 
562     @Override
563     public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
564         TableName tableName, byte[] c) throws IOException {
565       if (bypass) {
566         env.bypass();
567       }
568       preDeleteColumnCalled = true;
569     }
570 
571     @Override
572     public void postDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> env,
573         TableName tableName, byte[] c) throws IOException {
574       postDeleteColumnCalled = true;
575     }
576 
577     public boolean wasDeleteColumnCalled() {
578       return preDeleteColumnCalled && postDeleteColumnCalled;
579     }
580 
581     public boolean preDeleteColumnCalledOnly() {
582       return preDeleteColumnCalled && !postDeleteColumnCalled;
583     }
584 
585     @Override
586     public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
587         TableName tableName) throws IOException {
588       if (bypass) {
589         env.bypass();
590       }
591       preEnableTableCalled = true;
592     }
593 
594     @Override
595     public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
596         TableName tableName) throws IOException {
597       postEnableTableCalled = true;
598     }
599 
600     public boolean wasEnableTableCalled() {
601       return preEnableTableCalled && postEnableTableCalled;
602     }
603 
604     public boolean preEnableTableCalledOnly() {
605       return preEnableTableCalled && !postEnableTableCalled;
606     }
607 
608     @Override
609     public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
610         TableName tableName) throws IOException {
611       if (bypass) {
612         env.bypass();
613       }
614       preDisableTableCalled = true;
615     }
616 
617     @Override
618     public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
619         TableName tableName) throws IOException {
620       postDisableTableCalled = true;
621     }
622 
623     public boolean wasDisableTableCalled() {
624       return preDisableTableCalled && postDisableTableCalled;
625     }
626 
627     public boolean preDisableTableCalledOnly() {
628       return preDisableTableCalled && !postDisableTableCalled;
629     }
630 
631     @Override
632     public void preAbortProcedure(
633         ObserverContext<MasterCoprocessorEnvironment> ctx,
634         final ProcedureExecutor<MasterProcedureEnv> procEnv,
635         final long procId) throws IOException {
636       preAbortProcedureCalled = true;
637     }
638 
639     @Override
640     public void postAbortProcedure(
641         ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
642       postAbortProcedureCalled = true;
643     }
644 
645     public boolean wasAbortProcedureCalled() {
646       return preAbortProcedureCalled && postAbortProcedureCalled;
647     }
648 
649     public boolean wasPreAbortProcedureCalledOnly() {
650       return preAbortProcedureCalled && !postAbortProcedureCalled;
651     }
652 
653     @Override
654     public void preListProcedures(
655         ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
656       preListProceduresCalled = true;
657     }
658 
659     @Override
660     public void postListProcedures(
661         ObserverContext<MasterCoprocessorEnvironment> ctx,
662         List<ProcedureInfo> procInfoList) throws IOException {
663       postListProceduresCalled = true;
664     }
665 
666     public boolean wasListProceduresCalled() {
667       return preListProceduresCalled && postListProceduresCalled;
668     }
669 
670     public boolean wasPreListProceduresCalledOnly() {
671       return preListProceduresCalled && !postListProceduresCalled;
672     }
673 
674     @Override
675     public void preMove(ObserverContext<MasterCoprocessorEnvironment> env,
676         HRegionInfo region, ServerName srcServer, ServerName destServer)
677     throws IOException {
678       if (bypass) {
679         env.bypass();
680       }
681       preMoveCalled = true;
682     }
683 
684     @Override
685     public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, HRegionInfo region,
686         ServerName srcServer, ServerName destServer)
687     throws IOException {
688       postMoveCalled = true;
689     }
690 
691     public boolean wasMoveCalled() {
692       return preMoveCalled && postMoveCalled;
693     }
694 
695     public boolean preMoveCalledOnly() {
696       return preMoveCalled && !postMoveCalled;
697     }
698 
699     @Override
700     public void preAssign(ObserverContext<MasterCoprocessorEnvironment> env,
701         final HRegionInfo regionInfo) throws IOException {
702       if (bypass) {
703         env.bypass();
704       }
705       preAssignCalled = true;
706     }
707 
708     @Override
709     public void postAssign(ObserverContext<MasterCoprocessorEnvironment> env,
710         final HRegionInfo regionInfo) throws IOException {
711       postAssignCalled = true;
712     }
713 
714     public boolean wasAssignCalled() {
715       return preAssignCalled && postAssignCalled;
716     }
717 
718     public boolean preAssignCalledOnly() {
719       return preAssignCalled && !postAssignCalled;
720     }
721 
722     @Override
723     public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
724         final HRegionInfo regionInfo, final boolean force) throws IOException {
725       if (bypass) {
726         env.bypass();
727       }
728       preUnassignCalled = true;
729     }
730 
731     @Override
732     public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
733         final HRegionInfo regionInfo, final boolean force) throws IOException {
734       postUnassignCalled = true;
735     }
736 
737     public boolean wasUnassignCalled() {
738       return preUnassignCalled && postUnassignCalled;
739     }
740 
741     public boolean preUnassignCalledOnly() {
742       return preUnassignCalled && !postUnassignCalled;
743     }
744 
745     @Override
746     public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
747         final HRegionInfo regionInfo) throws IOException {
748       preRegionOfflineCalled = true;
749     }
750 
751     @Override
752     public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
753         final HRegionInfo regionInfo) throws IOException {
754       postRegionOfflineCalled = true;
755     }
756 
757     public boolean wasRegionOfflineCalled() {
758       return preRegionOfflineCalled && postRegionOfflineCalled;
759     }
760 
761     public boolean preRegionOfflineCalledOnly() {
762       return preRegionOfflineCalled && !postRegionOfflineCalled;
763     }
764 
765     @Override
766     public void preBalance(ObserverContext<MasterCoprocessorEnvironment> env)
767         throws IOException {
768       if (bypass) {
769         env.bypass();
770       }
771       preBalanceCalled = true;
772     }
773 
774     @Override
775     public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env,
776         List<RegionPlan> plans) throws IOException {
777       postBalanceCalled = true;
778     }
779 
780     public boolean wasBalanceCalled() {
781       return preBalanceCalled && postBalanceCalled;
782     }
783 
784     public boolean preBalanceCalledOnly() {
785       return preBalanceCalled && !postBalanceCalled;
786     }
787 
788     @Override
789     public boolean preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env, boolean b)
790         throws IOException {
791       if (bypass) {
792         env.bypass();
793       }
794       preBalanceSwitchCalled = true;
795       return b;
796     }
797 
798     @Override
799     public void postBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env,
800         boolean oldValue, boolean newValue) throws IOException {
801       postBalanceSwitchCalled = true;
802     }
803 
804     public boolean wasBalanceSwitchCalled() {
805       return preBalanceSwitchCalled && postBalanceSwitchCalled;
806     }
807 
808     public boolean preBalanceSwitchCalledOnly() {
809       return preBalanceSwitchCalled && !postBalanceSwitchCalled;
810     }
811 
812     @Override
813     public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> env)
814         throws IOException {
815       preShutdownCalled = true;
816     }
817 
818     public boolean wasShutdownCalled() {
819       return preShutdownCalled;
820     }
821 
822     @Override
823     public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
824         throws IOException {
825       preStopMasterCalled = true;
826     }
827 
828     public boolean wasStopMasterCalled() {
829       return preStopMasterCalled;
830     }
831 
832     @Override
833     public void preMasterInitialization(
834         ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
835       preMasterInitializationCalled = true;
836     }
837 
838     public boolean wasMasterInitializationCalled(){
839       return preMasterInitializationCalled;
840     }
841 
842     @Override
843     public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
844         throws IOException {
845       postStartMasterCalled = true;
846     }
847 
848     public boolean wasStartMasterCalled() {
849       return postStartMasterCalled;
850     }
851 
852     @Override
853     public void start(CoprocessorEnvironment env) throws IOException {
854       startCalled = true;
855     }
856 
857     @Override
858     public void stop(CoprocessorEnvironment env) throws IOException {
859       stopCalled = true;
860     }
861 
862     public boolean wasStarted() { return startCalled; }
863 
864     public boolean wasStopped() { return stopCalled; }
865 
866     @Override
867     public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
868         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
869         throws IOException {
870       preSnapshotCalled = true;
871     }
872 
873     @Override
874     public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
875         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
876         throws IOException {
877       postSnapshotCalled = true;
878     }
879 
880     public boolean wasSnapshotCalled() {
881       return preSnapshotCalled && postSnapshotCalled;
882     }
883 
884     @Override
885     public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
886         final SnapshotDescription snapshot) throws IOException {
887       preListSnapshotCalled = true;
888     }
889 
890     @Override
891     public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
892         final SnapshotDescription snapshot) throws IOException {
893       postListSnapshotCalled = true;
894     }
895 
896     public boolean wasListSnapshotCalled() {
897       return preListSnapshotCalled && postListSnapshotCalled;
898     }
899 
900     @Override
901     public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
902         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
903         throws IOException {
904       preCloneSnapshotCalled = true;
905     }
906 
907     @Override
908     public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
909         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
910         throws IOException {
911       postCloneSnapshotCalled = true;
912     }
913 
914     public boolean wasCloneSnapshotCalled() {
915       return preCloneSnapshotCalled && postCloneSnapshotCalled;
916     }
917 
918     @Override
919     public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
920         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
921         throws IOException {
922       preRestoreSnapshotCalled = true;
923     }
924 
925     @Override
926     public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
927         final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
928         throws IOException {
929       postRestoreSnapshotCalled = true;
930     }
931 
932     public boolean wasRestoreSnapshotCalled() {
933       return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
934     }
935 
936     @Override
937     public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
938         final SnapshotDescription snapshot) throws IOException {
939       preDeleteSnapshotCalled = true;
940     }
941 
942     @Override
943     public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
944         final SnapshotDescription snapshot) throws IOException {
945       postDeleteSnapshotCalled = true;
946     }
947 
948     public boolean wasDeleteSnapshotCalled() {
949       return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
950     }
951 
952     @Override
953     public void preCreateTableHandler(
954         ObserverContext<MasterCoprocessorEnvironment> env,
955         HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
956       if (bypass) {
957         env.bypass();
958       }
959       preCreateTableHandlerCalled = true;
960     }
961 
962     @Override
963     public void postCreateTableHandler(
964         ObserverContext<MasterCoprocessorEnvironment> ctx,
965         HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
966       postCreateTableHandlerCalled = true;
967       tableCreationLatch.countDown();
968     }
969 
970     public boolean wasPreCreateTableHandlerCalled(){
971       return preCreateTableHandlerCalled;
972     }
973     public boolean wasCreateTableHandlerCalled() {
974       return preCreateTableHandlerCalled && postCreateTableHandlerCalled;
975     }
976 
977     public boolean wasCreateTableHandlerCalledOnly() {
978       return preCreateTableHandlerCalled && !postCreateTableHandlerCalled;
979     }
980 
981     @Override
982     public void preDeleteTableHandler(
983         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
984         throws IOException {
985       if (bypass) {
986         env.bypass();
987       }
988       preDeleteTableHandlerCalled = true;
989     }
990 
991     @Override
992     public void postDeleteTableHandler(
993         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
994         throws IOException {
995       postDeleteTableHandlerCalled = true;
996       tableDeletionLatch.countDown();
997     }
998 
999     public boolean wasDeleteTableHandlerCalled() {
1000       return preDeleteTableHandlerCalled && postDeleteTableHandlerCalled;
1001     }
1002 
1003     public boolean wasDeleteTableHandlerCalledOnly() {
1004       return preDeleteTableHandlerCalled && !postDeleteTableHandlerCalled;
1005     }
1006 
1007     @Override
1008     public void preTruncateTableHandler(
1009         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
1010         throws IOException {
1011       if (bypass) {
1012         env.bypass();
1013       }
1014       preTruncateTableHandlerCalled = true;
1015     }
1016 
1017     @Override
1018     public void postTruncateTableHandler(
1019         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
1020         throws IOException {
1021       postTruncateTableHandlerCalled = true;
1022     }
1023 
1024     public boolean wasTruncateTableHandlerCalled() {
1025       return preTruncateTableHandlerCalled && postTruncateTableHandlerCalled;
1026     }
1027 
1028     public boolean wasTruncateTableHandlerCalledOnly() {
1029       return preTruncateTableHandlerCalled && !postTruncateTableHandlerCalled;
1030     }
1031 
1032     @Override
1033     public void preModifyTableHandler(
1034         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
1035         HTableDescriptor htd) throws IOException {
1036       if (bypass) {
1037         env.bypass();
1038       }
1039       preModifyTableHandlerCalled = true;
1040     }
1041 
1042     @Override
1043     public void postModifyTableHandler(
1044         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
1045         HTableDescriptor htd) throws IOException {
1046       postModifyTableHandlerCalled = true;
1047     }
1048 
1049     public boolean wasModifyTableHandlerCalled() {
1050       return preModifyTableHandlerCalled && postModifyTableHandlerCalled;
1051     }
1052 
1053     public boolean wasModifyTableHandlerCalledOnly() {
1054       return preModifyTableHandlerCalled && !postModifyTableHandlerCalled;
1055     }
1056 
1057     @Override
1058     public void preAddColumnHandler(
1059         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
1060         HColumnDescriptor column) throws IOException {
1061       if (bypass) {
1062         env.bypass();
1063       }
1064       preAddColumnHandlerCalled = true;
1065     }
1066 
1067     @Override
1068     public void postAddColumnHandler(
1069         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
1070         HColumnDescriptor column) throws IOException {
1071       postAddColumnHandlerCalled = true;
1072     }
1073     public boolean wasAddColumnHandlerCalled() {
1074       return preAddColumnHandlerCalled && postAddColumnHandlerCalled;
1075     }
1076 
1077     public boolean preAddColumnHandlerCalledOnly() {
1078       return preAddColumnHandlerCalled && !postAddColumnHandlerCalled;
1079     }
1080 
1081     @Override
1082     public void preModifyColumnHandler(
1083         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
1084         HColumnDescriptor descriptor) throws IOException {
1085       if (bypass) {
1086         env.bypass();
1087       }
1088       preModifyColumnHandlerCalled = true;
1089     }
1090 
1091     @Override
1092     public void postModifyColumnHandler(
1093         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
1094         HColumnDescriptor descriptor) throws IOException {
1095       postModifyColumnHandlerCalled = true;
1096     }
1097 
1098     public boolean wasModifyColumnHandlerCalled() {
1099       return preModifyColumnHandlerCalled && postModifyColumnHandlerCalled;
1100     }
1101 
1102     public boolean preModifyColumnHandlerCalledOnly() {
1103       return preModifyColumnHandlerCalled && !postModifyColumnHandlerCalled;
1104     }
1105     @Override
1106     public void preDeleteColumnHandler(
1107         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName,
1108         byte[] c) throws IOException {
1109       if (bypass) {
1110         env.bypass();
1111       }
1112       preDeleteColumnHandlerCalled = true;
1113     }
1114 
1115     @Override
1116     public void postDeleteColumnHandler(
1117         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName,
1118         byte[] c) throws IOException {
1119       postDeleteColumnHandlerCalled = true;
1120     }
1121 
1122     public boolean wasDeleteColumnHandlerCalled() {
1123       return preDeleteColumnHandlerCalled && postDeleteColumnHandlerCalled;
1124     }
1125 
1126     public boolean preDeleteColumnHandlerCalledOnly() {
1127       return preDeleteColumnHandlerCalled && !postDeleteColumnHandlerCalled;
1128     }
1129 
1130     @Override
1131     public void preEnableTableHandler(
1132         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
1133         throws IOException {
1134       if (bypass) {
1135         env.bypass();
1136       }
1137       preEnableTableHandlerCalled = true;
1138     }
1139 
1140     @Override
1141     public void postEnableTableHandler(
1142         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
1143         throws IOException {
1144       postEnableTableHandlerCalled = true;
1145     }
1146 
1147     public boolean wasEnableTableHandlerCalled() {
1148       return preEnableTableHandlerCalled && postEnableTableHandlerCalled;
1149     }
1150 
1151     public boolean preEnableTableHandlerCalledOnly() {
1152       return preEnableTableHandlerCalled && !postEnableTableHandlerCalled;
1153     }
1154 
1155     @Override
1156     public void preDisableTableHandler(
1157         ObserverContext<MasterCoprocessorEnvironment> env, TableName tableName)
1158         throws IOException {
1159       if (bypass) {
1160         env.bypass();
1161       }
1162       preDisableTableHandlerCalled = true;
1163     }
1164 
1165     @Override
1166     public void postDisableTableHandler(
1167         ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName)
1168         throws IOException {
1169       postDisableTableHandlerCalled = true;
1170     }
1171 
1172     public boolean wasDisableTableHandlerCalled() {
1173       return preDisableTableHandlerCalled && postDisableTableHandlerCalled;
1174     }
1175 
1176     public boolean preDisableTableHandlerCalledOnly() {
1177       return preDisableTableHandlerCalled && !postDisableTableHandlerCalled;
1178     }
1179 
1180     @Override
1181     public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1182         List<TableName> tableNamesList, List<HTableDescriptor> descriptors) throws IOException {
1183     }
1184 
1185     @Override
1186     public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1187         List<HTableDescriptor> descriptors) throws IOException {
1188     }
1189 
1190     @Override
1191     public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1192         List<TableName> tableNamesList, List<HTableDescriptor> descriptors,
1193         String regex) throws IOException {
1194       preGetTableDescriptorsCalled = true;
1195     }
1196 
1197     @Override
1198     public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1199         List<TableName> tableNamesList, List<HTableDescriptor> descriptors,
1200         String regex) throws IOException {
1201       postGetTableDescriptorsCalled = true;
1202     }
1203 
1204     public boolean wasGetTableDescriptorsCalled() {
1205       return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
1206     }
1207 
1208     @Override
1209     public void preGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1210         List<HTableDescriptor> descriptors, String regex) throws IOException {
1211       preGetTableNamesCalled = true;
1212     }
1213 
1214     @Override
1215     public void postGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1216         List<HTableDescriptor> descriptors, String regex) throws IOException {
1217       postGetTableNamesCalled = true;
1218     }
1219 
1220     public boolean wasGetTableNamesCalled() {
1221       return preGetTableNamesCalled && postGetTableNamesCalled;
1222     }
1223 
1224     @Override
1225     public void preTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1226         TableName tableName) throws IOException {
1227     }
1228 
1229     @Override
1230     public void postTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1231         TableName tableName) throws IOException {
1232     }
1233 
1234     @Override
1235     public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1236         final String userName, final Quotas quotas) throws IOException {
1237     }
1238 
1239     @Override
1240     public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1241         final String userName, final Quotas quotas) throws IOException {
1242     }
1243 
1244     @Override
1245     public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1246         final String userName, final TableName tableName, final Quotas quotas) throws IOException {
1247     }
1248 
1249     @Override
1250     public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1251         final String userName, final TableName tableName, final Quotas quotas) throws IOException {
1252     }
1253 
1254     @Override
1255     public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1256         final String userName, final String namespace, final Quotas quotas) throws IOException {
1257     }
1258 
1259     @Override
1260     public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1261         final String userName, final String namespace, final Quotas quotas) throws IOException {
1262     }
1263 
1264     @Override
1265     public void preSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1266         final TableName tableName, final Quotas quotas) throws IOException {
1267     }
1268 
1269     @Override
1270     public void postSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1271         final TableName tableName, final Quotas quotas) throws IOException {
1272     }
1273 
1274     @Override
1275     public void preSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1276         final String namespace, final Quotas quotas) throws IOException {
1277     }
1278 
1279     @Override
1280     public void postSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1281         final String namespace, final Quotas quotas) throws IOException {
1282     }
1283 
1284     @Override
1285     public void preMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1286         Set<Address> servers, String targetGroup) throws IOException {
1287     }
1288 
1289     @Override
1290     public void postMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1291         Set<Address> servers, String targetGroup) throws IOException {
1292     }
1293 
1294     @Override
1295     public void preMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1296         Set<TableName> tables, String targetGroup) throws IOException {
1297     }
1298 
1299     @Override
1300     public void postMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1301         Set<TableName> tables, String targetGroup) throws IOException {
1302     }
1303 
1304     @Override
1305     public void preMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1306         Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
1307     }
1308 
1309     @Override
1310     public void postMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1311         Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
1312     }
1313 
1314     @Override
1315     public void preAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1316         throws IOException {
1317     }
1318 
1319     @Override
1320     public void postAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1321         throws IOException {
1322     }
1323 
1324     @Override
1325     public void preRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1326         throws IOException {
1327     }
1328 
1329     @Override
1330     public void postRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1331         throws IOException {
1332     }
1333 
1334     @Override
1335     public void preRemoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1336         Set<Address> servers) throws IOException {
1337     }
1338 
1339     @Override
1340     public void postRemoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1341         Set<Address> servers) throws IOException {
1342     }
1343 
1344     @Override
1345     public void preBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1346         String groupName) throws IOException {
1347     }
1348 
1349     @Override
1350     public void postBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1351         String groupName, boolean balancerRan) throws IOException {
1352     }
1353   }
1354 
1355   private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
1356   private static byte[] TEST_SNAPSHOT = Bytes.toBytes("observed_snapshot");
1357   private static TableName TEST_CLONE = TableName.valueOf("observed_clone");
1358   private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
1359   private static byte[] TEST_FAMILY2 = Bytes.toBytes("fam2");
1360   @Rule public TestName name = new TestName();
1361 
1362   @BeforeClass
1363   public static void setupBeforeClass() throws Exception {
1364     Configuration conf = UTIL.getConfiguration();
1365     conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
1366         CPMasterObserver.class.getName());
1367     // We need more than one data server on this test
1368     UTIL.startMiniCluster(2);
1369   }
1370 
1371   @AfterClass
1372   public static void tearDownAfterClass() throws Exception {
1373     UTIL.shutdownMiniCluster();
1374   }
1375 
1376   @Test (timeout=180000)
1377   public void testStarted() throws Exception {
1378     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1379 
1380     HMaster master = cluster.getMaster();
1381     assertTrue("Master should be active", master.isActiveMaster());
1382     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1383     assertNotNull("CoprocessorHost should not be null", host);
1384     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1385         CPMasterObserver.class.getName());
1386     assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
1387 
1388     // check basic lifecycle
1389     assertTrue("MasterObserver should have been started", cp.wasStarted());
1390     assertTrue("preMasterInitialization() hook should have been called",
1391         cp.wasMasterInitializationCalled());
1392     assertTrue("postStartMaster() hook should have been called",
1393         cp.wasStartMasterCalled());
1394   }
1395 
1396   @Test (timeout=180000)
1397   public void testTableOperations() throws Exception {
1398     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1399     final TableName tableName = TableName.valueOf(name.getMethodName());
1400     HMaster master = cluster.getMaster();
1401     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1402     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1403         CPMasterObserver.class.getName());
1404     cp.enableBypass(true);
1405     cp.resetStates();
1406     assertFalse("No table created yet", cp.wasCreateTableCalled());
1407 
1408     // create a table
1409     HTableDescriptor htd = new HTableDescriptor(tableName);
1410     htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1411     try(Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
1412         Admin admin = connection.getAdmin()) {
1413       tableCreationLatch = new CountDownLatch(1);
1414       admin.createTable(htd, Arrays.copyOfRange(HBaseTestingUtility.KEYS,
1415         1, HBaseTestingUtility.KEYS.length));
1416 
1417       // preCreateTable can't bypass default action.
1418       assertTrue("Test table should be created", cp.wasCreateTableCalled());
1419       tableCreationLatch.await();
1420       assertTrue("Table pre create handler called.", cp
1421         .wasPreCreateTableHandlerCalled());
1422       assertTrue("Table create handler should be called.",
1423         cp.wasCreateTableHandlerCalled());
1424 
1425       RegionLocator regionLocator = connection.getRegionLocator(htd.getTableName());
1426       List<HRegionLocation> regions = regionLocator.getAllRegionLocations();
1427 
1428       admin.mergeRegions(regions.get(0).getRegionInfo().getEncodedNameAsBytes(),
1429         regions.get(1).getRegionInfo().getEncodedNameAsBytes(), true);
1430       assertTrue("Coprocessor should have been called on region merge",
1431         cp.wasDispatchMergeCalled());
1432 
1433       tableCreationLatch = new CountDownLatch(1);
1434       admin.disableTable(tableName);
1435       assertTrue(admin.isTableDisabled(tableName));
1436       // preDisableTable can't bypass default action.
1437       assertTrue("Coprocessor should have been called on table disable",
1438         cp.wasDisableTableCalled());
1439       assertTrue("Disable table handler should be called.",
1440         cp.wasDisableTableHandlerCalled());
1441 
1442       // enable
1443       assertFalse(cp.wasEnableTableCalled());
1444       admin.enableTable(tableName);
1445       assertTrue(admin.isTableEnabled(tableName));
1446       // preEnableTable can't bypass default action.
1447       assertTrue("Coprocessor should have been called on table enable",
1448         cp.wasEnableTableCalled());
1449       assertTrue("Enable table handler should be called.",
1450         cp.wasEnableTableHandlerCalled());
1451 
1452       admin.disableTable(tableName);
1453       assertTrue(admin.isTableDisabled(tableName));
1454 
1455       // modify table
1456       htd.setMaxFileSize(512 * 1024 * 1024);
1457       modifyTableSync(admin, tableName, htd);
1458       // preModifyTable can't bypass default action.
1459       assertTrue("Test table should have been modified",
1460         cp.wasModifyTableCalled());
1461 
1462       // add a column family
1463       admin.addColumn(tableName, new HColumnDescriptor(TEST_FAMILY2));
1464       assertTrue("New column family shouldn't have been added to test table",
1465         cp.preAddColumnCalledOnly());
1466 
1467       // modify a column family
1468       HColumnDescriptor hcd1 = new HColumnDescriptor(TEST_FAMILY2);
1469       hcd1.setMaxVersions(25);
1470       admin.modifyColumn(tableName, hcd1);
1471       assertTrue("Second column family should be modified",
1472         cp.preModifyColumnCalledOnly());
1473 
1474       // truncate table
1475       admin.truncateTable(tableName, false);
1476 
1477       // delete table
1478       admin.disableTable(tableName);
1479       assertTrue(admin.isTableDisabled(tableName));
1480       deleteTable(admin, tableName);
1481       assertFalse("Test table should have been deleted",
1482         admin.tableExists(tableName));
1483       // preDeleteTable can't bypass default action.
1484       assertTrue("Coprocessor should have been called on table delete",
1485         cp.wasDeleteTableCalled());
1486       assertTrue("Delete table handler should be called.",
1487         cp.wasDeleteTableHandlerCalled());
1488 
1489       // turn off bypass, run the tests again
1490       cp.enableBypass(false);
1491       cp.resetStates();
1492 
1493       admin.createTable(htd);
1494       assertTrue("Test table should be created", cp.wasCreateTableCalled());
1495       tableCreationLatch.await();
1496       assertTrue("Table pre create handler called.", cp
1497         .wasPreCreateTableHandlerCalled());
1498       assertTrue("Table create handler should be called.",
1499         cp.wasCreateTableHandlerCalled());
1500 
1501       // disable
1502       assertFalse(cp.wasDisableTableCalled());
1503       assertFalse(cp.wasDisableTableHandlerCalled());
1504       admin.disableTable(tableName);
1505       assertTrue(admin.isTableDisabled(tableName));
1506       assertTrue("Coprocessor should have been called on table disable",
1507         cp.wasDisableTableCalled());
1508       assertTrue("Disable table handler should be called.",
1509         cp.wasDisableTableHandlerCalled());
1510 
1511       // modify table
1512       htd.setMaxFileSize(512 * 1024 * 1024);
1513       modifyTableSync(admin, tableName, htd);
1514       assertTrue("Test table should have been modified",
1515         cp.wasModifyTableCalled());
1516       // add a column family
1517       admin.addColumn(tableName, new HColumnDescriptor(TEST_FAMILY2));
1518       assertTrue("New column family should have been added to test table",
1519         cp.wasAddColumnCalled());
1520       assertTrue("Add column handler should be called.",
1521         cp.wasAddColumnHandlerCalled());
1522 
1523       // modify a column family
1524       HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
1525       hcd.setMaxVersions(25);
1526       admin.modifyColumn(tableName, hcd);
1527       assertTrue("Second column family should be modified",
1528         cp.wasModifyColumnCalled());
1529       assertTrue("Modify table handler should be called.",
1530         cp.wasModifyColumnHandlerCalled());
1531 
1532       // enable
1533       assertFalse(cp.wasEnableTableCalled());
1534       assertFalse(cp.wasEnableTableHandlerCalled());
1535       admin.enableTable(tableName);
1536       assertTrue(admin.isTableEnabled(tableName));
1537       assertTrue("Coprocessor should have been called on table enable",
1538         cp.wasEnableTableCalled());
1539       assertTrue("Enable table handler should be called.",
1540         cp.wasEnableTableHandlerCalled());
1541 
1542       // disable again
1543       admin.disableTable(tableName);
1544       assertTrue(admin.isTableDisabled(tableName));
1545 
1546       // delete column
1547       assertFalse("No column family deleted yet", cp.wasDeleteColumnCalled());
1548       assertFalse("Delete table column handler should not be called.",
1549         cp.wasDeleteColumnHandlerCalled());
1550       admin.deleteColumn(tableName, TEST_FAMILY2);
1551       HTableDescriptor tableDesc = admin.getTableDescriptor(tableName);
1552       assertNull("'"+Bytes.toString(TEST_FAMILY2)+"' should have been removed",
1553         tableDesc.getFamily(TEST_FAMILY2));
1554       assertTrue("Coprocessor should have been called on column delete",
1555         cp.wasDeleteColumnCalled());
1556       assertTrue("Delete table column handler should be called.",
1557         cp.wasDeleteColumnHandlerCalled());
1558 
1559       // delete table
1560       assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
1561       assertFalse("Delete table handler should not be called.",
1562         cp.wasDeleteTableHandlerCalled());
1563       deleteTable(admin, tableName);
1564       assertFalse("Test table should have been deleted",
1565         admin.tableExists(tableName));
1566       assertTrue("Coprocessor should have been called on table delete",
1567         cp.wasDeleteTableCalled());
1568       assertTrue("Delete table handler should be called.",
1569         cp.wasDeleteTableHandlerCalled());
1570     }
1571   }
1572 
1573   @Test (timeout=180000)
1574   public void testSnapshotOperations() throws Exception {
1575     final TableName tableName = TableName.valueOf(name.getMethodName());
1576     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1577     HMaster master = cluster.getMaster();
1578     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1579     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1580         CPMasterObserver.class.getName());
1581     cp.resetStates();
1582 
1583     // create a table
1584     HTableDescriptor htd = new HTableDescriptor(tableName);
1585     htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1586     Admin admin = UTIL.getHBaseAdmin();
1587 
1588     tableCreationLatch = new CountDownLatch(1);
1589     admin.createTable(htd);
1590     tableCreationLatch.await();
1591     tableCreationLatch = new CountDownLatch(1);
1592 
1593     admin.disableTable(tableName);
1594     assertTrue(admin.isTableDisabled(tableName));
1595 
1596     try {
1597       // Test snapshot operation
1598       assertFalse("Coprocessor should not have been called yet",
1599         cp.wasSnapshotCalled());
1600       admin.snapshot(TEST_SNAPSHOT, tableName);
1601       assertTrue("Coprocessor should have been called on snapshot",
1602         cp.wasSnapshotCalled());
1603 
1604       //Test list operation
1605       admin.listSnapshots();
1606       assertTrue("Coprocessor should have been called on snapshot list",
1607         cp.wasListSnapshotCalled());
1608 
1609       // Test clone operation
1610       admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
1611       assertTrue("Coprocessor should have been called on snapshot clone",
1612         cp.wasCloneSnapshotCalled());
1613       assertFalse("Coprocessor restore should not have been called on snapshot clone",
1614         cp.wasRestoreSnapshotCalled());
1615       admin.disableTable(TEST_CLONE);
1616       assertTrue(admin.isTableDisabled(tableName));
1617       deleteTable(admin, TEST_CLONE);
1618 
1619       // Test restore operation
1620       cp.resetStates();
1621       admin.restoreSnapshot(TEST_SNAPSHOT);
1622       assertTrue("Coprocessor should have been called on snapshot restore",
1623         cp.wasRestoreSnapshotCalled());
1624       assertFalse("Coprocessor clone should not have been called on snapshot restore",
1625         cp.wasCloneSnapshotCalled());
1626 
1627       admin.deleteSnapshot(TEST_SNAPSHOT);
1628       assertTrue("Coprocessor should have been called on snapshot delete",
1629         cp.wasDeleteSnapshotCalled());
1630     } finally {
1631       deleteTable(admin, tableName);
1632     }
1633   }
1634 
1635   @Test (timeout=180000)
1636   public void testNamespaceOperations() throws Exception {
1637     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1638     String testNamespace = "observed_ns";
1639     HMaster master = cluster.getMaster();
1640     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1641     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1642         CPMasterObserver.class.getName());
1643 
1644     cp.enableBypass(false);
1645     cp.resetStates();
1646 
1647 
1648     // create a table
1649     Admin admin = UTIL.getHBaseAdmin();
1650     admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1651     assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
1652 
1653     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1654     assertTrue("Test namespace descriptor should have been called",
1655         cp.wasGetNamespaceDescriptorCalled());
1656 
1657     // turn off bypass, run the tests again
1658     cp.enableBypass(true);
1659     cp.resetStates();
1660 
1661     admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
1662     assertTrue("Test namespace should not have been modified",
1663         cp.preModifyNamespaceCalledOnly());
1664 
1665     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1666     assertTrue("Test namespace descriptor should have been called",
1667         cp.wasGetNamespaceDescriptorCalled());
1668 
1669     admin.deleteNamespace(testNamespace);
1670     assertTrue("Test namespace should not have been deleted", cp.preDeleteNamespaceCalledOnly());
1671 
1672     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1673     assertTrue("Test namespace descriptor should have been called",
1674         cp.wasGetNamespaceDescriptorCalled());
1675 
1676     cp.enableBypass(false);
1677     cp.resetStates();
1678 
1679     // delete table
1680     admin.modifyNamespace(NamespaceDescriptor.create(testNamespace).build());
1681     assertTrue("Test namespace should have been modified", cp.wasModifyNamespaceCalled());
1682 
1683     admin.deleteNamespace(testNamespace);
1684     assertTrue("Test namespace should have been deleted", cp.wasDeleteNamespaceCalled());
1685 
1686     cp.enableBypass(true);
1687     cp.resetStates();
1688 
1689     admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1690     assertTrue("Test namespace should not be created", cp.preCreateNamespaceCalledOnly());
1691 
1692     // turn on bypass, run the test
1693     cp.enableBypass(true);
1694     cp.resetStates();
1695 
1696     admin.listNamespaceDescriptors();
1697     assertTrue("post listNamespace should not have been called",
1698                cp.preListNamespaceDescriptorsCalledOnly());
1699 
1700     // turn off bypass, run the tests again
1701     cp.enableBypass(false);
1702     cp.resetStates();
1703 
1704     admin.listNamespaceDescriptors();
1705     assertTrue("post listNamespace should have been called",
1706                cp.wasListNamespaceDescriptorsCalled());
1707   }
1708 
1709   private void modifyTableSync(Admin admin, TableName tableName, HTableDescriptor htd)
1710       throws IOException {
1711     admin.modifyTable(tableName, htd);
1712     //wait until modify table finishes
1713     for (int t = 0; t < 100; t++) { //10 sec timeout
1714       HTableDescriptor td = admin.getTableDescriptor(htd.getTableName());
1715       if (td.equals(htd)) {
1716         break;
1717       }
1718       Threads.sleep(100);
1719     }
1720   }
1721 
1722   @Test (timeout=180000)
1723   public void testRegionTransitionOperations() throws Exception {
1724     final TableName tableName = TableName.valueOf(name.getMethodName());
1725     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1726 
1727     HMaster master = cluster.getMaster();
1728     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1729     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1730         CPMasterObserver.class.getName());
1731     cp.enableBypass(false);
1732     cp.resetStates();
1733 
1734     HTable table = UTIL.createMultiRegionTable(tableName, TEST_FAMILY);
1735 
1736     try {
1737       UTIL.waitUntilAllRegionsAssigned(tableName);
1738 
1739       NavigableMap<HRegionInfo, ServerName> regions = table.getRegionLocations();
1740       Map.Entry<HRegionInfo, ServerName> firstGoodPair = null;
1741       for (Map.Entry<HRegionInfo, ServerName> e: regions.entrySet()) {
1742         if (e.getValue() != null) {
1743           firstGoodPair = e;
1744           break;
1745         }
1746       }
1747       assertNotNull("Found a non-null entry", firstGoodPair);
1748       LOG.info("Found " + firstGoodPair.toString());
1749       // Try to force a move
1750       Collection<ServerName> servers = master.getClusterStatus().getServers();
1751       String destName = null;
1752       String serverNameForFirstRegion = firstGoodPair.getValue().toString();
1753       LOG.info("serverNameForFirstRegion=" + serverNameForFirstRegion);
1754       ServerName masterServerName = master.getServerName();
1755       boolean found = false;
1756       // Find server that is NOT carrying the first region
1757       for (ServerName info : servers) {
1758         LOG.info("ServerName=" + info);
1759         if (!serverNameForFirstRegion.equals(info.getServerName())
1760             && !masterServerName.equals(info)) {
1761           destName = info.toString();
1762           found = true;
1763           break;
1764         }
1765       }
1766       assertTrue("Found server", found);
1767       LOG.info("Found " + destName);
1768       master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1769           firstGoodPair.getKey().getEncodedNameAsBytes(),Bytes.toBytes(destName)));
1770       assertTrue("Coprocessor should have been called on region move",
1771         cp.wasMoveCalled());
1772 
1773       // make sure balancer is on
1774       master.balanceSwitch(true);
1775       assertTrue("Coprocessor should have been called on balance switch",
1776           cp.wasBalanceSwitchCalled());
1777 
1778       // turn balancer off
1779       master.balanceSwitch(false);
1780 
1781       // wait for assignments to finish, if any
1782       UTIL.waitUntilNoRegionsInTransition();
1783 
1784       // move half the open regions from RS 0 to RS 1
1785       HRegionServer rs = cluster.getRegionServer(0);
1786       byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
1787       //Make sure no regions are in transition now
1788       UTIL.waitUntilNoRegionsInTransition();
1789       List<HRegionInfo> openRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
1790       int moveCnt = openRegions.size()/2;
1791       for (int i=0; i<moveCnt; i++) {
1792         HRegionInfo info = openRegions.get(i);
1793         if (!info.isMetaTable()) {
1794           master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1795               openRegions.get(i).getEncodedNameAsBytes(), destRS));
1796         }
1797       }
1798       //Make sure no regions are in transition now
1799       UTIL.waitUntilNoRegionsInTransition();
1800       // now trigger a balance
1801       master.balanceSwitch(true);
1802       boolean balanceRun = master.balance();
1803       assertTrue("Coprocessor should be called on region rebalancing",
1804           cp.wasBalanceCalled());
1805     } finally {
1806       Admin admin = UTIL.getHBaseAdmin();
1807       admin.disableTable(tableName);
1808       deleteTable(admin, tableName);
1809     }
1810   }
1811 
1812   @Test (timeout=180000)
1813   public void testTableDescriptorsEnumeration() throws Exception {
1814     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1815 
1816     HMaster master = cluster.getMaster();
1817     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1818     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1819         CPMasterObserver.class.getName());
1820     cp.resetStates();
1821 
1822     GetTableDescriptorsRequest req =
1823         RequestConverter.buildGetTableDescriptorsRequest((List<TableName>)null);
1824     master.getMasterRpcServices().getTableDescriptors(null, req);
1825 
1826     assertTrue("Coprocessor should be called on table descriptors request",
1827       cp.wasGetTableDescriptorsCalled());
1828   }
1829 
1830   @Test (timeout=180000)
1831   public void testTableNamesEnumeration() throws Exception {
1832     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1833 
1834     HMaster master = cluster.getMaster();
1835     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1836     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1837         CPMasterObserver.class.getName());
1838     cp.resetStates();
1839 
1840     master.getMasterRpcServices().getTableNames(null,
1841         GetTableNamesRequest.newBuilder().build());
1842     assertTrue("Coprocessor should be called on table names request",
1843       cp.wasGetTableNamesCalled());
1844   }
1845 
1846   @Test (timeout=180000)
1847   public void testAbortProcedureOperation() throws Exception {
1848     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1849 
1850     HMaster master = cluster.getMaster();
1851     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1852     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1853         CPMasterObserver.class.getName());
1854     cp.resetStates();
1855 
1856     master.abortProcedure(1, true);
1857     assertTrue(
1858       "Coprocessor should be called on abort procedure request",
1859       cp.wasAbortProcedureCalled());
1860   }
1861 
1862   @Test (timeout=180000)
1863   public void testListProceduresOperation() throws Exception {
1864     MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1865 
1866     HMaster master = cluster.getMaster();
1867     MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1868     CPMasterObserver cp = (CPMasterObserver)host.findCoprocessor(
1869         CPMasterObserver.class.getName());
1870     cp.resetStates();
1871 
1872     master.listProcedures();
1873     assertTrue(
1874       "Coprocessor should be called on list procedures request",
1875       cp.wasListProceduresCalled());
1876   }
1877 
1878   private void deleteTable(Admin admin, TableName tableName) throws Exception {
1879     // NOTE: We need a latch because admin is not sync,
1880     // so the postOp coprocessor method may be called after the admin operation returned.
1881     tableDeletionLatch = new CountDownLatch(1);
1882     admin.deleteTable(tableName);
1883     tableDeletionLatch.await();
1884     tableDeletionLatch = new CountDownLatch(1);
1885   }
1886 }