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