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