001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.coprocessor;
019
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertTrue;
023
024import java.io.IOException;
025import java.util.Arrays;
026import java.util.Collection;
027import java.util.List;
028import java.util.Optional;
029import java.util.Set;
030import java.util.concurrent.CountDownLatch;
031import org.apache.hadoop.conf.Configuration;
032import org.apache.hadoop.hbase.CoprocessorEnvironment;
033import org.apache.hadoop.hbase.HBaseClassTestRule;
034import org.apache.hadoop.hbase.HBaseTestingUtility;
035import org.apache.hadoop.hbase.HColumnDescriptor;
036import org.apache.hadoop.hbase.HRegionLocation;
037import org.apache.hadoop.hbase.HTableDescriptor;
038import org.apache.hadoop.hbase.MiniHBaseCluster;
039import org.apache.hadoop.hbase.NamespaceDescriptor;
040import org.apache.hadoop.hbase.ServerName;
041import org.apache.hadoop.hbase.TableName;
042import org.apache.hadoop.hbase.client.Admin;
043import org.apache.hadoop.hbase.client.Connection;
044import org.apache.hadoop.hbase.client.ConnectionFactory;
045import org.apache.hadoop.hbase.client.MasterSwitchType;
046import org.apache.hadoop.hbase.client.Mutation;
047import org.apache.hadoop.hbase.client.RegionInfo;
048import org.apache.hadoop.hbase.client.RegionLocator;
049import org.apache.hadoop.hbase.client.SnapshotDescription;
050import org.apache.hadoop.hbase.client.Table;
051import org.apache.hadoop.hbase.client.TableDescriptor;
052import org.apache.hadoop.hbase.master.HMaster;
053import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
054import org.apache.hadoop.hbase.master.RegionPlan;
055import org.apache.hadoop.hbase.net.Address;
056import org.apache.hadoop.hbase.procedure2.LockType;
057import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
058import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings;
059import org.apache.hadoop.hbase.regionserver.HRegionServer;
060import org.apache.hadoop.hbase.testclassification.CoprocessorTests;
061import org.apache.hadoop.hbase.testclassification.MediumTests;
062import org.apache.hadoop.hbase.util.Bytes;
063import org.apache.hadoop.hbase.util.Threads;
064import org.junit.AfterClass;
065import org.junit.BeforeClass;
066import org.junit.ClassRule;
067import org.junit.Rule;
068import org.junit.Test;
069import org.junit.experimental.categories.Category;
070import org.junit.rules.TestName;
071import org.slf4j.Logger;
072import org.slf4j.LoggerFactory;
073
074import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
075import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
076import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
077import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest;
078
079/**
080 * Tests invocation of the {@link org.apache.hadoop.hbase.coprocessor.MasterObserver}
081 * interface hooks at all appropriate times during normal HMaster operations.
082 */
083@Category({CoprocessorTests.class, MediumTests.class})
084public class TestMasterObserver {
085
086  @ClassRule
087  public static final HBaseClassTestRule CLASS_RULE =
088      HBaseClassTestRule.forClass(TestMasterObserver.class);
089
090  private static final Logger LOG = LoggerFactory.getLogger(TestMasterObserver.class);
091
092  public static CountDownLatch tableCreationLatch = new CountDownLatch(1);
093  public static CountDownLatch tableDeletionLatch = new CountDownLatch(1);
094
095  public static class CPMasterObserver implements MasterCoprocessor, MasterObserver {
096
097    private boolean preCreateTableRegionInfosCalled;
098    private boolean preCreateTableCalled;
099    private boolean postCreateTableCalled;
100    private boolean preDeleteTableCalled;
101    private boolean postDeleteTableCalled;
102    private boolean preTruncateTableCalled;
103    private boolean postTruncateTableCalled;
104    private boolean preModifyTableCalled;
105    private boolean postModifyTableCalled;
106    private boolean preCreateNamespaceCalled;
107    private boolean postCreateNamespaceCalled;
108    private boolean preDeleteNamespaceCalled;
109    private boolean postDeleteNamespaceCalled;
110    private boolean preModifyNamespaceCalled;
111    private boolean postModifyNamespaceCalled;
112    private boolean preGetNamespaceDescriptorCalled;
113    private boolean postGetNamespaceDescriptorCalled;
114    private boolean preListNamespacesCalled;
115    private boolean postListNamespacesCalled;
116    private boolean preListNamespaceDescriptorsCalled;
117    private boolean postListNamespaceDescriptorsCalled;
118    private boolean preAddColumnCalled;
119    private boolean postAddColumnCalled;
120    private boolean preModifyColumnCalled;
121    private boolean postModifyColumnCalled;
122    private boolean preDeleteColumnCalled;
123    private boolean postDeleteColumnCalled;
124    private boolean preEnableTableCalled;
125    private boolean postEnableTableCalled;
126    private boolean preDisableTableCalled;
127    private boolean postDisableTableCalled;
128    private boolean preAbortProcedureCalled;
129    private boolean postAbortProcedureCalled;
130    private boolean preGetProceduresCalled;
131    private boolean postGetProceduresCalled;
132    private boolean preGetLocksCalled;
133    private boolean postGetLocksCalled;
134    private boolean preMoveCalled;
135    private boolean postMoveCalled;
136    private boolean preAssignCalled;
137    private boolean postAssignCalled;
138    private boolean preUnassignCalled;
139    private boolean postUnassignCalled;
140    private boolean preRegionOfflineCalled;
141    private boolean postRegionOfflineCalled;
142    private boolean preBalanceCalled;
143    private boolean postBalanceCalled;
144    private boolean preBalanceSwitchCalled;
145    private boolean postBalanceSwitchCalled;
146    private boolean preShutdownCalled;
147    private boolean preStopMasterCalled;
148    private boolean preMasterInitializationCalled;
149    private boolean postStartMasterCalled;
150    private boolean startCalled;
151    private boolean stopCalled;
152    private boolean preSnapshotCalled;
153    private boolean postSnapshotCalled;
154    private boolean preListSnapshotCalled;
155    private boolean postListSnapshotCalled;
156    private boolean preCloneSnapshotCalled;
157    private boolean postCloneSnapshotCalled;
158    private boolean preRestoreSnapshotCalled;
159    private boolean postRestoreSnapshotCalled;
160    private boolean preDeleteSnapshotCalled;
161    private boolean postDeleteSnapshotCalled;
162    private boolean preCreateTableActionCalled;
163    private boolean postCompletedCreateTableActionCalled;
164    private boolean preDeleteTableActionCalled;
165    private boolean postCompletedDeleteTableActionCalled;
166    private boolean preTruncateTableActionCalled;
167    private boolean postCompletedTruncateTableActionCalled;
168    private boolean preAddColumnFamilyActionCalled;
169    private boolean postCompletedAddColumnFamilyActionCalled;
170    private boolean preModifyColumnFamilyActionCalled;
171    private boolean postCompletedModifyColumnFamilyActionCalled;
172    private boolean preDeleteColumnFamilyActionCalled;
173    private boolean postCompletedDeleteColumnFamilyActionCalled;
174    private boolean preEnableTableActionCalled;
175    private boolean postCompletedEnableTableActionCalled;
176    private boolean preDisableTableActionCalled;
177    private boolean postCompletedDisableTableActionCalled;
178    private boolean preModifyTableActionCalled;
179    private boolean postCompletedModifyTableActionCalled;
180    private boolean preGetTableDescriptorsCalled;
181    private boolean postGetTableDescriptorsCalled;
182    private boolean postGetTableNamesCalled;
183    private boolean preGetTableNamesCalled;
184    private boolean preMergeRegionsCalled;
185    private boolean postMergeRegionsCalled;
186    private boolean preRequestLockCalled;
187    private boolean postRequestLockCalled;
188    private boolean preLockHeartbeatCalled;
189    private boolean postLockHeartbeatCalled;
190
191    public void resetStates() {
192      preCreateTableRegionInfosCalled = false;
193      preCreateTableCalled = false;
194      postCreateTableCalled = false;
195      preDeleteTableCalled = false;
196      postDeleteTableCalled = false;
197      preTruncateTableCalled = false;
198      postTruncateTableCalled = false;
199      preModifyTableCalled = false;
200      postModifyTableCalled = false;
201      preCreateNamespaceCalled = false;
202      postCreateNamespaceCalled = false;
203      preDeleteNamespaceCalled = false;
204      postDeleteNamespaceCalled = false;
205      preModifyNamespaceCalled = false;
206      postModifyNamespaceCalled = false;
207      preGetNamespaceDescriptorCalled = false;
208      postGetNamespaceDescriptorCalled = false;
209      preListNamespacesCalled = false;
210      postListNamespacesCalled = false;
211      preListNamespaceDescriptorsCalled = false;
212      postListNamespaceDescriptorsCalled = false;
213      preAddColumnCalled = false;
214      postAddColumnCalled = false;
215      preModifyColumnCalled = false;
216      postModifyColumnCalled = false;
217      preDeleteColumnCalled = false;
218      postDeleteColumnCalled = false;
219      preEnableTableCalled = false;
220      postEnableTableCalled = false;
221      preDisableTableCalled = false;
222      postDisableTableCalled = false;
223      preAbortProcedureCalled = false;
224      postAbortProcedureCalled = false;
225      preGetProceduresCalled = false;
226      postGetProceduresCalled = false;
227      preGetLocksCalled = false;
228      postGetLocksCalled = false;
229      preMoveCalled= false;
230      postMoveCalled = false;
231      preAssignCalled = false;
232      postAssignCalled = false;
233      preUnassignCalled = false;
234      postUnassignCalled = false;
235      preRegionOfflineCalled = false;
236      postRegionOfflineCalled = false;
237      preBalanceCalled = false;
238      postBalanceCalled = false;
239      preBalanceSwitchCalled = false;
240      postBalanceSwitchCalled = false;
241      preShutdownCalled = false;
242      preStopMasterCalled = false;
243      preSnapshotCalled = false;
244      postSnapshotCalled = false;
245      preListSnapshotCalled = false;
246      postListSnapshotCalled = false;
247      preCloneSnapshotCalled = false;
248      postCloneSnapshotCalled = false;
249      preRestoreSnapshotCalled = false;
250      postRestoreSnapshotCalled = false;
251      preDeleteSnapshotCalled = false;
252      postDeleteSnapshotCalled = false;
253      preCreateTableActionCalled = false;
254      postCompletedCreateTableActionCalled = false;
255      preDeleteTableActionCalled = false;
256      postCompletedDeleteTableActionCalled = false;
257      preTruncateTableActionCalled = false;
258      postCompletedTruncateTableActionCalled = false;
259      preModifyTableActionCalled = false;
260      postCompletedModifyTableActionCalled = false;
261      preAddColumnFamilyActionCalled = false;
262      postCompletedAddColumnFamilyActionCalled = false;
263      preModifyColumnFamilyActionCalled = false;
264      postCompletedModifyColumnFamilyActionCalled = false;
265      preDeleteColumnFamilyActionCalled = false;
266      postCompletedDeleteColumnFamilyActionCalled = false;
267      preEnableTableActionCalled = false;
268      postCompletedEnableTableActionCalled = false;
269      preDisableTableActionCalled = false;
270      postCompletedDisableTableActionCalled = false;
271      preGetTableDescriptorsCalled = false;
272      postGetTableDescriptorsCalled = false;
273      postGetTableNamesCalled = false;
274      preGetTableNamesCalled = false;
275      preMergeRegionsCalled = false;
276      postMergeRegionsCalled = false;
277      preRequestLockCalled = false;
278      postRequestLockCalled = false;
279      preLockHeartbeatCalled = false;
280      postLockHeartbeatCalled = false;
281    }
282
283    @Override
284    public Optional<MasterObserver> getMasterObserver() {
285      return Optional.of(this);
286    }
287
288    @Override
289    public void preMergeRegions(
290        final ObserverContext<MasterCoprocessorEnvironment> ctx,
291        final RegionInfo[] regionsToMerge) throws IOException {
292      preMergeRegionsCalled = true;
293    }
294
295    @Override
296    public void postMergeRegions(
297        final ObserverContext<MasterCoprocessorEnvironment> ctx,
298        final RegionInfo[] regionsToMerge) throws IOException {
299      postMergeRegionsCalled = true;
300    }
301
302    public boolean wasMergeRegionsCalled() {
303      return preMergeRegionsCalled && postMergeRegionsCalled;
304    }
305
306    @Override
307    public TableDescriptor preCreateTableRegionsInfos(
308        ObserverContext<MasterCoprocessorEnvironment> ctx, TableDescriptor desc)
309        throws IOException {
310      preCreateTableRegionInfosCalled = true;
311      return desc;
312    }
313
314    @Override
315    public void preCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
316        TableDescriptor desc, RegionInfo[] regions) throws IOException {
317      preCreateTableCalled = true;
318    }
319
320    @Override
321    public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env,
322        TableDescriptor desc, RegionInfo[] regions) throws IOException {
323      postCreateTableCalled = true;
324    }
325
326    public boolean wasCreateTableCalled() {
327      return preCreateTableRegionInfosCalled && preCreateTableCalled && postCreateTableCalled;
328    }
329
330    public boolean preCreateTableCalledOnly() {
331      return preCreateTableRegionInfosCalled && preCreateTableCalled && !postCreateTableCalled;
332    }
333
334    @Override
335    public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
336        TableName tableName) throws IOException {
337      preDeleteTableCalled = true;
338    }
339
340    @Override
341    public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> env,
342        TableName tableName) throws IOException {
343      postDeleteTableCalled = true;
344    }
345
346    public boolean wasDeleteTableCalled() {
347      return preDeleteTableCalled && postDeleteTableCalled;
348    }
349
350    public boolean preDeleteTableCalledOnly() {
351      return preDeleteTableCalled && !postDeleteTableCalled;
352    }
353
354    @Override
355    public void preTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
356        TableName tableName) throws IOException {
357      preTruncateTableCalled = true;
358    }
359
360    @Override
361    public void postTruncateTable(ObserverContext<MasterCoprocessorEnvironment> env,
362        TableName tableName) throws IOException {
363      postTruncateTableCalled = true;
364    }
365
366    public boolean wasTruncateTableCalled() {
367      return preTruncateTableCalled && postTruncateTableCalled;
368    }
369
370    public boolean preTruncateTableCalledOnly() {
371      return preTruncateTableCalled && !postTruncateTableCalled;
372    }
373
374    @Override
375    public void postSetSplitOrMergeEnabled(final ObserverContext<MasterCoprocessorEnvironment> ctx,
376        final boolean newValue, final MasterSwitchType switchType) throws IOException {
377    }
378
379    @Override
380    public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
381        TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor)
382        throws IOException {
383      preModifyTableCalled = true;
384      return newDescriptor;
385    }
386
387    @Override
388    public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
389        TableName tableName, TableDescriptor htd) throws IOException {
390      postModifyTableCalled = true;
391    }
392
393    public boolean wasModifyTableCalled() {
394      return preModifyTableCalled && postModifyTableCalled;
395    }
396
397    public boolean preModifyTableCalledOnly() {
398      return preModifyTableCalled && !postModifyTableCalled;
399    }
400
401    @Override
402    public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
403        NamespaceDescriptor ns) throws IOException {
404      preCreateNamespaceCalled = true;
405    }
406
407    @Override
408    public void postCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
409        NamespaceDescriptor ns) throws IOException {
410      postCreateNamespaceCalled = true;
411    }
412
413    public boolean wasCreateNamespaceCalled() {
414      return preCreateNamespaceCalled && postCreateNamespaceCalled;
415    }
416
417    public boolean preCreateNamespaceCalledOnly() {
418      return preCreateNamespaceCalled && !postCreateNamespaceCalled;
419    }
420
421    @Override
422    public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
423        String name) throws IOException {
424      preDeleteNamespaceCalled = true;
425    }
426
427    @Override
428    public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
429        String name) throws IOException {
430      postDeleteNamespaceCalled = true;
431    }
432
433    public boolean wasDeleteNamespaceCalled() {
434      return preDeleteNamespaceCalled && postDeleteNamespaceCalled;
435    }
436
437    public boolean preDeleteNamespaceCalledOnly() {
438      return preDeleteNamespaceCalled && !postDeleteNamespaceCalled;
439    }
440
441    @Override
442    public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
443        NamespaceDescriptor ns) throws IOException {
444      preModifyNamespaceCalled = true;
445    }
446
447    @Override
448    public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
449        NamespaceDescriptor ns) throws IOException {
450      postModifyNamespaceCalled = true;
451    }
452
453    public boolean wasModifyNamespaceCalled() {
454      return preModifyNamespaceCalled && postModifyNamespaceCalled;
455    }
456
457    public boolean preModifyNamespaceCalledOnly() {
458      return preModifyNamespaceCalled && !postModifyNamespaceCalled;
459    }
460
461
462    @Override
463    public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
464        String namespace) throws IOException {
465      preGetNamespaceDescriptorCalled = true;
466    }
467
468    @Override
469    public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
470        NamespaceDescriptor ns) throws IOException {
471      postGetNamespaceDescriptorCalled = true;
472    }
473
474    public boolean wasGetNamespaceDescriptorCalled() {
475      return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
476    }
477
478    @Override
479    public void preListNamespaces(ObserverContext<MasterCoprocessorEnvironment> ctx,
480        List<String> namespaces) {
481      preListNamespacesCalled = true;
482    }
483
484    @Override
485    public void postListNamespaces(ObserverContext<MasterCoprocessorEnvironment> ctx,
486        List<String> namespaces) {
487      postListNamespacesCalled = true;
488    }
489
490    @Override
491    public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
492        List<NamespaceDescriptor> descriptors) throws IOException {
493      preListNamespaceDescriptorsCalled = true;
494    }
495
496    @Override
497    public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
498        List<NamespaceDescriptor> descriptors) throws IOException {
499      postListNamespaceDescriptorsCalled = true;
500    }
501
502    public boolean wasListNamespaceDescriptorsCalled() {
503      return preListNamespaceDescriptorsCalled && postListNamespaceDescriptorsCalled;
504    }
505
506    public boolean preListNamespaceDescriptorsCalledOnly() {
507      return preListNamespaceDescriptorsCalled && !postListNamespaceDescriptorsCalled;
508    }
509
510    @Override
511    public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
512        TableName tableName) throws IOException {
513      preEnableTableCalled = true;
514    }
515
516    @Override
517    public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
518        TableName tableName) throws IOException {
519      postEnableTableCalled = true;
520    }
521
522    public boolean wasEnableTableCalled() {
523      return preEnableTableCalled && postEnableTableCalled;
524    }
525
526    public boolean preEnableTableCalledOnly() {
527      return preEnableTableCalled && !postEnableTableCalled;
528    }
529
530    @Override
531    public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
532        TableName tableName) throws IOException {
533      preDisableTableCalled = true;
534    }
535
536    @Override
537    public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
538        TableName tableName) throws IOException {
539      postDisableTableCalled = true;
540    }
541
542    public boolean wasDisableTableCalled() {
543      return preDisableTableCalled && postDisableTableCalled;
544    }
545
546    public boolean preDisableTableCalledOnly() {
547      return preDisableTableCalled && !postDisableTableCalled;
548    }
549
550    @Override
551    public void preAbortProcedure(
552        ObserverContext<MasterCoprocessorEnvironment> ctx, final long procId) throws IOException {
553      preAbortProcedureCalled = true;
554    }
555
556    @Override
557    public void postAbortProcedure(
558        ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
559      postAbortProcedureCalled = true;
560    }
561
562    public boolean wasAbortProcedureCalled() {
563      return preAbortProcedureCalled && postAbortProcedureCalled;
564    }
565
566    public boolean wasPreAbortProcedureCalledOnly() {
567      return preAbortProcedureCalled && !postAbortProcedureCalled;
568    }
569
570    @Override
571    public void preGetProcedures(
572        ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
573      preGetProceduresCalled = true;
574    }
575
576    @Override
577    public void postGetProcedures(
578        ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
579      postGetProceduresCalled = true;
580    }
581
582    public boolean wasGetProceduresCalled() {
583      return preGetProceduresCalled && postGetProceduresCalled;
584    }
585
586    public boolean wasPreGetProceduresCalledOnly() {
587      return preGetProceduresCalled && !postGetProceduresCalled;
588    }
589
590    @Override
591    public void preGetLocks(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
592      preGetLocksCalled = true;
593    }
594
595    @Override
596    public void postGetLocks(ObserverContext<MasterCoprocessorEnvironment> ctx)
597        throws IOException {
598      postGetLocksCalled = true;
599    }
600
601    public boolean wasGetLocksCalled() {
602      return preGetLocksCalled && postGetLocksCalled;
603    }
604
605    public boolean wasPreGetLocksCalledOnly() {
606      return preGetLocksCalled && !postGetLocksCalled;
607    }
608
609    @Override
610    public void preMove(ObserverContext<MasterCoprocessorEnvironment> env,
611        RegionInfo region, ServerName srcServer, ServerName destServer)
612    throws IOException {
613      preMoveCalled = true;
614    }
615
616    @Override
617    public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, RegionInfo region,
618        ServerName srcServer, ServerName destServer)
619    throws IOException {
620      postMoveCalled = true;
621    }
622
623    public boolean wasMoveCalled() {
624      return preMoveCalled && postMoveCalled;
625    }
626
627    public boolean preMoveCalledOnly() {
628      return preMoveCalled && !postMoveCalled;
629    }
630
631    @Override
632    public void preAssign(ObserverContext<MasterCoprocessorEnvironment> env,
633        final RegionInfo regionInfo) throws IOException {
634      preAssignCalled = true;
635    }
636
637    @Override
638    public void postAssign(ObserverContext<MasterCoprocessorEnvironment> env,
639        final RegionInfo regionInfo) throws IOException {
640      postAssignCalled = true;
641    }
642
643    public boolean wasAssignCalled() {
644      return preAssignCalled && postAssignCalled;
645    }
646
647    public boolean preAssignCalledOnly() {
648      return preAssignCalled && !postAssignCalled;
649    }
650
651    @Override
652    public void preUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
653        final RegionInfo regionInfo) throws IOException {
654      preUnassignCalled = true;
655    }
656
657    @Override
658    public void postUnassign(ObserverContext<MasterCoprocessorEnvironment> env,
659        final RegionInfo regionInfo) throws IOException {
660      postUnassignCalled = true;
661    }
662
663    public boolean wasUnassignCalled() {
664      return preUnassignCalled && postUnassignCalled;
665    }
666
667    public boolean preUnassignCalledOnly() {
668      return preUnassignCalled && !postUnassignCalled;
669    }
670
671    @Override
672    public void preRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
673        final RegionInfo regionInfo) throws IOException {
674      preRegionOfflineCalled = true;
675    }
676
677    @Override
678    public void postRegionOffline(ObserverContext<MasterCoprocessorEnvironment> env,
679        final RegionInfo regionInfo) throws IOException {
680      postRegionOfflineCalled = true;
681    }
682
683    public boolean wasRegionOfflineCalled() {
684      return preRegionOfflineCalled && postRegionOfflineCalled;
685    }
686
687    public boolean preRegionOfflineCalledOnly() {
688      return preRegionOfflineCalled && !postRegionOfflineCalled;
689    }
690
691    @Override
692    public void preBalance(ObserverContext<MasterCoprocessorEnvironment> env)
693        throws IOException {
694      preBalanceCalled = true;
695    }
696
697    @Override
698    public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env,
699        List<RegionPlan> plans) throws IOException {
700      postBalanceCalled = true;
701    }
702
703    public boolean wasBalanceCalled() {
704      return preBalanceCalled && postBalanceCalled;
705    }
706
707    public boolean preBalanceCalledOnly() {
708      return preBalanceCalled && !postBalanceCalled;
709    }
710
711    @Override
712    public void preBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env, boolean b)
713        throws IOException {
714      preBalanceSwitchCalled = true;
715    }
716
717    @Override
718    public void postBalanceSwitch(ObserverContext<MasterCoprocessorEnvironment> env,
719        boolean oldValue, boolean newValue) throws IOException {
720      postBalanceSwitchCalled = true;
721    }
722
723    public boolean wasBalanceSwitchCalled() {
724      return preBalanceSwitchCalled && postBalanceSwitchCalled;
725    }
726
727    public boolean preBalanceSwitchCalledOnly() {
728      return preBalanceSwitchCalled && !postBalanceSwitchCalled;
729    }
730
731    @Override
732    public void preShutdown(ObserverContext<MasterCoprocessorEnvironment> env)
733        throws IOException {
734      preShutdownCalled = true;
735    }
736
737    public boolean wasShutdownCalled() {
738      return preShutdownCalled;
739    }
740
741    @Override
742    public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
743        throws IOException {
744      preStopMasterCalled = true;
745    }
746
747    public boolean wasStopMasterCalled() {
748      return preStopMasterCalled;
749    }
750
751    @Override
752    public void preMasterInitialization(
753        ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
754      preMasterInitializationCalled = true;
755    }
756
757    public boolean wasMasterInitializationCalled(){
758      return preMasterInitializationCalled;
759    }
760
761    @Override
762    public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
763        throws IOException {
764      postStartMasterCalled = true;
765    }
766
767    public boolean wasStartMasterCalled() {
768      return postStartMasterCalled;
769    }
770
771    @Override
772    public void start(CoprocessorEnvironment env) throws IOException {
773      startCalled = true;
774    }
775
776    @Override
777    public void stop(CoprocessorEnvironment env) throws IOException {
778      stopCalled = true;
779    }
780
781    public boolean wasStarted() { return startCalled; }
782
783    public boolean wasStopped() { return stopCalled; }
784
785    @Override
786    public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
787        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
788        throws IOException {
789      preSnapshotCalled = true;
790    }
791
792    @Override
793    public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
794        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
795        throws IOException {
796      postSnapshotCalled = true;
797    }
798
799    public boolean wasSnapshotCalled() {
800      return preSnapshotCalled && postSnapshotCalled;
801    }
802
803    @Override
804    public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
805        final SnapshotDescription snapshot) throws IOException {
806      preListSnapshotCalled = true;
807    }
808
809    @Override
810    public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
811        final SnapshotDescription snapshot) throws IOException {
812      postListSnapshotCalled = true;
813    }
814
815    public boolean wasListSnapshotCalled() {
816      return preListSnapshotCalled && postListSnapshotCalled;
817    }
818
819    @Override
820    public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
821        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
822        throws IOException {
823      preCloneSnapshotCalled = true;
824    }
825
826    @Override
827    public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
828        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
829        throws IOException {
830      postCloneSnapshotCalled = true;
831    }
832
833    public boolean wasCloneSnapshotCalled() {
834      return preCloneSnapshotCalled && postCloneSnapshotCalled;
835    }
836
837    @Override
838    public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
839        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
840        throws IOException {
841      preRestoreSnapshotCalled = true;
842    }
843
844    @Override
845    public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
846        final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
847        throws IOException {
848      postRestoreSnapshotCalled = true;
849    }
850
851    public boolean wasRestoreSnapshotCalled() {
852      return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
853    }
854
855    @Override
856    public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
857        final SnapshotDescription snapshot) throws IOException {
858      preDeleteSnapshotCalled = true;
859    }
860
861    @Override
862    public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
863        final SnapshotDescription snapshot) throws IOException {
864      postDeleteSnapshotCalled = true;
865    }
866
867    public boolean wasDeleteSnapshotCalled() {
868      return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
869    }
870
871    @Override
872    public void preCreateTableAction(
873        final ObserverContext<MasterCoprocessorEnvironment> env,
874        final TableDescriptor desc,
875        final RegionInfo[] regions) throws IOException {
876      preCreateTableActionCalled = true;
877    }
878
879    @Override
880    public void postCompletedCreateTableAction(
881        final ObserverContext<MasterCoprocessorEnvironment> ctx,
882        final TableDescriptor desc,
883        final RegionInfo[] regions) throws IOException {
884      postCompletedCreateTableActionCalled = true;
885      tableCreationLatch.countDown();
886    }
887
888    public boolean wasPreCreateTableActionCalled(){
889      return preCreateTableActionCalled;
890    }
891    public boolean wasCreateTableActionCalled() {
892      return preCreateTableActionCalled && postCompletedCreateTableActionCalled;
893    }
894
895    public boolean wasCreateTableActionCalledOnly() {
896      return preCreateTableActionCalled && !postCompletedCreateTableActionCalled;
897    }
898
899    @Override
900    public void preDeleteTableAction(
901        final ObserverContext<MasterCoprocessorEnvironment> env, final TableName tableName)
902        throws IOException {
903      preDeleteTableActionCalled = true;
904    }
905
906    @Override
907    public void postCompletedDeleteTableAction(
908        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
909        throws IOException {
910      postCompletedDeleteTableActionCalled = true;
911      tableDeletionLatch.countDown();
912    }
913
914    public boolean wasDeleteTableActionCalled() {
915      return preDeleteTableActionCalled && postCompletedDeleteTableActionCalled;
916    }
917
918    public boolean wasDeleteTableActionCalledOnly() {
919      return preDeleteTableActionCalled && !postCompletedDeleteTableActionCalled;
920    }
921
922    @Override
923    public void preTruncateTableAction(
924        final ObserverContext<MasterCoprocessorEnvironment> env, final TableName tableName)
925        throws IOException {
926      preTruncateTableActionCalled = true;
927    }
928
929    @Override
930    public void postCompletedTruncateTableAction(
931        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
932        throws IOException {
933      postCompletedTruncateTableActionCalled = true;
934    }
935
936    public boolean wasTruncateTableActionCalled() {
937      return preTruncateTableActionCalled && postCompletedTruncateTableActionCalled;
938    }
939
940    public boolean wasTruncateTableActionCalledOnly() {
941      return preTruncateTableActionCalled && !postCompletedTruncateTableActionCalled;
942    }
943
944    @Override
945    public void preModifyTableAction(
946        final ObserverContext<MasterCoprocessorEnvironment> env,
947        final TableName tableName,
948        final TableDescriptor htd) throws IOException {
949      preModifyTableActionCalled = true;
950    }
951
952    @Override
953    public void postCompletedModifyTableAction(
954        final ObserverContext<MasterCoprocessorEnvironment> env,
955        final TableName tableName,
956        final TableDescriptor htd) throws IOException {
957      postCompletedModifyTableActionCalled = true;
958    }
959
960    public boolean wasModifyTableActionCalled() {
961      return preModifyTableActionCalled && postCompletedModifyTableActionCalled;
962    }
963
964    public boolean wasModifyTableActionCalledOnly() {
965      return preModifyTableActionCalled && !postCompletedModifyTableActionCalled;
966    }
967
968    @Override
969    public void preEnableTableAction(
970        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
971        throws IOException {
972      preEnableTableActionCalled = true;
973    }
974
975    @Override
976    public void postCompletedEnableTableAction(
977        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
978        throws IOException {
979      postCompletedEnableTableActionCalled = true;
980    }
981
982    public boolean wasEnableTableActionCalled() {
983      return preEnableTableActionCalled && postCompletedEnableTableActionCalled;
984    }
985
986    public boolean preEnableTableActionCalledOnly() {
987      return preEnableTableActionCalled && !postCompletedEnableTableActionCalled;
988    }
989
990    @Override
991    public void preDisableTableAction(
992        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
993        throws IOException {
994      preDisableTableActionCalled = true;
995    }
996
997    @Override
998    public void postCompletedDisableTableAction(
999        final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
1000        throws IOException {
1001      postCompletedDisableTableActionCalled = true;
1002    }
1003
1004    public boolean wasDisableTableActionCalled() {
1005      return preDisableTableActionCalled && postCompletedDisableTableActionCalled;
1006    }
1007
1008    public boolean preDisableTableActionCalledOnly() {
1009      return preDisableTableActionCalled && !postCompletedDisableTableActionCalled;
1010    }
1011
1012    @Override
1013    public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1014        List<TableName> tableNamesList, List<TableDescriptor> descriptors, String regex)
1015        throws IOException {
1016      preGetTableDescriptorsCalled = true;
1017    }
1018
1019    @Override
1020    public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1021        List<TableName> tableNamesList, List<TableDescriptor> descriptors,
1022        String regex) throws IOException {
1023      postGetTableDescriptorsCalled = true;
1024    }
1025
1026    public boolean wasGetTableDescriptorsCalled() {
1027      return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
1028    }
1029
1030    @Override
1031    public void preGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1032        List<TableDescriptor> descriptors, String regex) throws IOException {
1033      preGetTableNamesCalled = true;
1034    }
1035
1036    @Override
1037    public void postGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1038        List<TableDescriptor> descriptors, String regex) throws IOException {
1039      postGetTableNamesCalled = true;
1040    }
1041
1042    public boolean wasGetTableNamesCalled() {
1043      return preGetTableNamesCalled && postGetTableNamesCalled;
1044    }
1045
1046    @Override
1047    public void preTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1048        TableName tableName) throws IOException {
1049    }
1050
1051    @Override
1052    public void postTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1053        TableName tableName) throws IOException {
1054    }
1055
1056    @Override
1057    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1058        final String userName, final GlobalQuotaSettings quotas) throws IOException {
1059    }
1060
1061    @Override
1062    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1063        final String userName, final GlobalQuotaSettings quotas) throws IOException {
1064    }
1065
1066    @Override
1067    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1068        final String userName, final TableName tableName, final GlobalQuotaSettings quotas)
1069            throws IOException {
1070    }
1071
1072    @Override
1073    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1074        final String userName, final TableName tableName, final GlobalQuotaSettings quotas)
1075            throws IOException {
1076    }
1077
1078    @Override
1079    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1080        final String userName, final String namespace, final GlobalQuotaSettings quotas)
1081            throws IOException {
1082    }
1083
1084    @Override
1085    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1086        final String userName, final String namespace, final GlobalQuotaSettings quotas)
1087            throws IOException {
1088    }
1089
1090    @Override
1091    public void preSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1092        final TableName tableName, final GlobalQuotaSettings quotas) throws IOException {
1093    }
1094
1095    @Override
1096    public void postSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1097        final TableName tableName, final GlobalQuotaSettings quotas) throws IOException {
1098    }
1099
1100    @Override
1101    public void preSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1102        final String namespace, final GlobalQuotaSettings quotas) throws IOException {
1103    }
1104
1105    @Override
1106    public void postSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1107        final String namespace, final GlobalQuotaSettings quotas) throws IOException {
1108    }
1109
1110    @Override
1111    public void preMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1112        Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
1113    }
1114
1115    @Override
1116    public void postMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1117        Set<Address> servers, Set<TableName> tables,String targetGroup) throws IOException {
1118    }
1119
1120    @Override
1121    public void preMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1122                               Set<Address> servers, String targetGroup) throws IOException {
1123    }
1124
1125    @Override
1126    public void postMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1127                                Set<Address> servers, String targetGroup) throws IOException {
1128    }
1129
1130    @Override
1131    public void preMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1132                              Set<TableName> tables, String targetGroupGroup) throws IOException {
1133    }
1134
1135    @Override
1136    public void postMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1137                               Set<TableName> tables, String targetGroup) throws IOException {
1138    }
1139
1140    @Override
1141    public void preAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1142                              String name) throws IOException {
1143    }
1144
1145    @Override
1146    public void postAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1147                               String name) throws IOException {
1148    }
1149
1150    @Override
1151    public void preRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1152                                 String name) throws IOException {
1153    }
1154
1155    @Override
1156    public void postRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1157                                  String name) throws IOException {
1158    }
1159
1160    @Override
1161    public void preBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1162                                  String groupName) throws IOException {
1163    }
1164
1165    @Override
1166    public void postBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1167        String groupName, boolean balancerRan) throws IOException {
1168    }
1169
1170    @Override
1171    public void preRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
1172        TableName tableName, RegionInfo[] regionInfos, String description) throws IOException {
1173      preRequestLockCalled = true;
1174    }
1175
1176    @Override
1177    public void postRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
1178        TableName tableName, RegionInfo[] regionInfos, String description) throws IOException {
1179      postRequestLockCalled = true;
1180    }
1181
1182    @Override
1183    public void preLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx,
1184        TableName tn, String description) throws IOException {
1185      preLockHeartbeatCalled = true;
1186    }
1187
1188    @Override
1189    public void postLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx)
1190        throws IOException {
1191      postLockHeartbeatCalled = true;
1192    }
1193
1194    public boolean preAndPostForQueueLockAndHeartbeatLockCalled() {
1195      return preRequestLockCalled && postRequestLockCalled && preLockHeartbeatCalled &&
1196          postLockHeartbeatCalled;
1197    }
1198
1199    @Override
1200    public void preSplitRegion(
1201        final ObserverContext<MasterCoprocessorEnvironment> c,
1202        final TableName tableName,
1203        final byte[] splitRow) throws IOException {
1204    }
1205
1206    @Override
1207    public void preSplitRegionAction(
1208        final ObserverContext<MasterCoprocessorEnvironment> c,
1209        final TableName tableName,
1210        final byte[] splitRow) throws IOException {
1211    }
1212
1213    @Override
1214    public void postCompletedSplitRegionAction(
1215        final ObserverContext<MasterCoprocessorEnvironment> c,
1216        final RegionInfo regionInfoA,
1217        final RegionInfo regionInfoB) throws IOException {
1218    }
1219
1220    @Override
1221    public void preSplitRegionBeforeMETAAction(
1222        final ObserverContext<MasterCoprocessorEnvironment> ctx,
1223        final byte[] splitKey,
1224        final List<Mutation> metaEntries) throws IOException {
1225    }
1226
1227    @Override
1228    public void preSplitRegionAfterMETAAction(
1229        final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
1230    }
1231
1232    @Override
1233    public void postRollBackSplitRegionAction(
1234        final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
1235    }
1236
1237    @Override
1238    public void preMergeRegionsAction(
1239        final ObserverContext<MasterCoprocessorEnvironment> ctx,
1240        final RegionInfo[] regionsToMerge) throws IOException {
1241    }
1242
1243    @Override
1244    public void postCompletedMergeRegionsAction(
1245        final ObserverContext<MasterCoprocessorEnvironment> c,
1246        final RegionInfo[] regionsToMerge,
1247        final RegionInfo mergedRegion) throws IOException {
1248    }
1249
1250    @Override
1251    public void preMergeRegionsCommitAction(
1252        final ObserverContext<MasterCoprocessorEnvironment> ctx,
1253        final RegionInfo[] regionsToMerge,
1254        final List<Mutation> metaEntries) throws IOException {
1255    }
1256
1257    @Override
1258    public void postMergeRegionsCommitAction(
1259        final ObserverContext<MasterCoprocessorEnvironment> ctx,
1260        final RegionInfo[] regionsToMerge,
1261        final RegionInfo mergedRegion) throws IOException {
1262    }
1263
1264    @Override
1265    public void postRollBackMergeRegionsAction(
1266        final ObserverContext<MasterCoprocessorEnvironment> ctx,
1267        final RegionInfo[] regionsToMerge) throws IOException {
1268    }
1269
1270  }
1271
1272  private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
1273  private static byte[] TEST_SNAPSHOT = Bytes.toBytes("observed_snapshot");
1274  private static TableName TEST_CLONE = TableName.valueOf("observed_clone");
1275  private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
1276  private static byte[] TEST_FAMILY2 = Bytes.toBytes("fam2");
1277  @Rule public TestName name = new TestName();
1278
1279  @BeforeClass
1280  public static void setupBeforeClass() throws Exception {
1281    Configuration conf = UTIL.getConfiguration();
1282    conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
1283        CPMasterObserver.class.getName());
1284    // We need more than one data server on this test
1285    UTIL.startMiniCluster(2);
1286  }
1287
1288  @AfterClass
1289  public static void tearDownAfterClass() throws Exception {
1290    UTIL.shutdownMiniCluster();
1291  }
1292
1293  @Test
1294  public void testStarted() throws Exception {
1295    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1296
1297    HMaster master = cluster.getMaster();
1298    assertTrue("Master should be active", master.isActiveMaster());
1299    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1300    assertNotNull("CoprocessorHost should not be null", host);
1301    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1302    assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
1303
1304    // check basic lifecycle
1305    assertTrue("MasterObserver should have been started", cp.wasStarted());
1306    assertTrue("preMasterInitialization() hook should have been called",
1307        cp.wasMasterInitializationCalled());
1308    assertTrue("postStartMaster() hook should have been called",
1309        cp.wasStartMasterCalled());
1310  }
1311
1312  @Test
1313  public void testTableOperations() throws Exception {
1314    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1315    final TableName tableName = TableName.valueOf(name.getMethodName());
1316    HMaster master = cluster.getMaster();
1317    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1318    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1319    cp.resetStates();
1320    assertFalse("No table created yet", cp.wasCreateTableCalled());
1321
1322    // create a table
1323    HTableDescriptor htd = new HTableDescriptor(tableName);
1324    htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1325    try(Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
1326        Admin admin = connection.getAdmin()) {
1327      tableCreationLatch = new CountDownLatch(1);
1328      admin.createTable(htd, Arrays.copyOfRange(HBaseTestingUtility.KEYS,
1329        1, HBaseTestingUtility.KEYS.length));
1330
1331      assertTrue("Test table should be created", cp.wasCreateTableCalled());
1332      tableCreationLatch.await();
1333      assertTrue("Table pre create handler called.", cp
1334        .wasPreCreateTableActionCalled());
1335      assertTrue("Table create handler should be called.",
1336        cp.wasCreateTableActionCalled());
1337
1338      RegionLocator regionLocator = connection.getRegionLocator(htd.getTableName());
1339      List<HRegionLocation> regions = regionLocator.getAllRegionLocations();
1340
1341      admin.mergeRegionsAsync(regions.get(0).getRegionInfo().getEncodedNameAsBytes(),
1342        regions.get(1).getRegionInfo().getEncodedNameAsBytes(), true);
1343      assertTrue("Coprocessor should have been called on region merge",
1344        cp.wasMergeRegionsCalled());
1345
1346      tableCreationLatch = new CountDownLatch(1);
1347      admin.disableTable(tableName);
1348      assertTrue(admin.isTableDisabled(tableName));
1349      assertTrue("Coprocessor should have been called on table disable",
1350        cp.wasDisableTableCalled());
1351      assertTrue("Disable table handler should be called.",
1352        cp.wasDisableTableActionCalled());
1353
1354      // enable
1355      assertFalse(cp.wasEnableTableCalled());
1356      admin.enableTable(tableName);
1357      assertTrue(admin.isTableEnabled(tableName));
1358      assertTrue("Coprocessor should have been called on table enable",
1359        cp.wasEnableTableCalled());
1360      assertTrue("Enable table handler should be called.",
1361        cp.wasEnableTableActionCalled());
1362
1363      admin.disableTable(tableName);
1364      assertTrue(admin.isTableDisabled(tableName));
1365
1366      // modify table
1367      htd.setMaxFileSize(512 * 1024 * 1024);
1368      modifyTableSync(admin, tableName, htd);
1369      assertTrue("Test table should have been modified",
1370        cp.wasModifyTableCalled());
1371
1372      // truncate table
1373      admin.truncateTable(tableName, false);
1374
1375      // delete table
1376      admin.disableTable(tableName);
1377      assertTrue(admin.isTableDisabled(tableName));
1378      deleteTable(admin, tableName);
1379      assertFalse("Test table should have been deleted",
1380        admin.tableExists(tableName));
1381      assertTrue("Coprocessor should have been called on table delete",
1382        cp.wasDeleteTableCalled());
1383      assertTrue("Delete table handler should be called.",
1384        cp.wasDeleteTableActionCalled());
1385
1386      // When bypass was supported, we'd turn off bypass and rerun tests. Leaving rerun in place.
1387      cp.resetStates();
1388
1389      admin.createTable(htd);
1390      assertTrue("Test table should be created", cp.wasCreateTableCalled());
1391      tableCreationLatch.await();
1392      assertTrue("Table pre create handler called.", cp
1393        .wasPreCreateTableActionCalled());
1394      assertTrue("Table create handler should be called.",
1395        cp.wasCreateTableActionCalled());
1396
1397      // disable
1398      assertFalse(cp.wasDisableTableCalled());
1399      assertFalse(cp.wasDisableTableActionCalled());
1400      admin.disableTable(tableName);
1401      assertTrue(admin.isTableDisabled(tableName));
1402      assertTrue("Coprocessor should have been called on table disable",
1403        cp.wasDisableTableCalled());
1404      assertTrue("Disable table handler should be called.",
1405        cp.wasDisableTableActionCalled());
1406
1407      // modify table
1408      htd.setMaxFileSize(512 * 1024 * 1024);
1409      modifyTableSync(admin, tableName, htd);
1410      assertTrue("Test table should have been modified",
1411        cp.wasModifyTableCalled());
1412
1413      // enable
1414      assertFalse(cp.wasEnableTableCalled());
1415      assertFalse(cp.wasEnableTableActionCalled());
1416      admin.enableTable(tableName);
1417      assertTrue(admin.isTableEnabled(tableName));
1418      assertTrue("Coprocessor should have been called on table enable",
1419        cp.wasEnableTableCalled());
1420      assertTrue("Enable table handler should be called.",
1421        cp.wasEnableTableActionCalled());
1422
1423      // disable again
1424      admin.disableTable(tableName);
1425      assertTrue(admin.isTableDisabled(tableName));
1426
1427      // delete table
1428      assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
1429      assertFalse("Delete table handler should not be called.",
1430        cp.wasDeleteTableActionCalled());
1431      deleteTable(admin, tableName);
1432      assertFalse("Test table should have been deleted",
1433        admin.tableExists(tableName));
1434      assertTrue("Coprocessor should have been called on table delete",
1435        cp.wasDeleteTableCalled());
1436      assertTrue("Delete table handler should be called.",
1437        cp.wasDeleteTableActionCalled());
1438    }
1439  }
1440
1441  @Test
1442  public void testSnapshotOperations() throws Exception {
1443    final TableName tableName = TableName.valueOf(name.getMethodName());
1444    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1445    HMaster master = cluster.getMaster();
1446    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1447    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1448    cp.resetStates();
1449
1450    // create a table
1451    HTableDescriptor htd = new HTableDescriptor(tableName);
1452    htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
1453    Admin admin = UTIL.getAdmin();
1454
1455    tableCreationLatch = new CountDownLatch(1);
1456    admin.createTable(htd);
1457    tableCreationLatch.await();
1458    tableCreationLatch = new CountDownLatch(1);
1459
1460    admin.disableTable(tableName);
1461    assertTrue(admin.isTableDisabled(tableName));
1462
1463    try {
1464      // Test snapshot operation
1465      assertFalse("Coprocessor should not have been called yet",
1466        cp.wasSnapshotCalled());
1467      admin.snapshot(TEST_SNAPSHOT, tableName);
1468      assertTrue("Coprocessor should have been called on snapshot",
1469        cp.wasSnapshotCalled());
1470
1471      //Test list operation
1472      admin.listSnapshots();
1473      assertTrue("Coprocessor should have been called on snapshot list",
1474        cp.wasListSnapshotCalled());
1475
1476      // Test clone operation
1477      admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
1478      assertTrue("Coprocessor should have been called on snapshot clone",
1479        cp.wasCloneSnapshotCalled());
1480      assertFalse("Coprocessor restore should not have been called on snapshot clone",
1481        cp.wasRestoreSnapshotCalled());
1482      admin.disableTable(TEST_CLONE);
1483      assertTrue(admin.isTableDisabled(tableName));
1484      deleteTable(admin, TEST_CLONE);
1485
1486      // Test restore operation
1487      cp.resetStates();
1488      admin.restoreSnapshot(TEST_SNAPSHOT);
1489      assertTrue("Coprocessor should have been called on snapshot restore",
1490        cp.wasRestoreSnapshotCalled());
1491      assertFalse("Coprocessor clone should not have been called on snapshot restore",
1492        cp.wasCloneSnapshotCalled());
1493
1494      admin.deleteSnapshot(TEST_SNAPSHOT);
1495      assertTrue("Coprocessor should have been called on snapshot delete",
1496        cp.wasDeleteSnapshotCalled());
1497    } finally {
1498      deleteTable(admin, tableName);
1499    }
1500  }
1501
1502  @Test
1503  public void testNamespaceOperations() throws Exception {
1504    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1505    String testNamespace = "observed_ns";
1506    HMaster master = cluster.getMaster();
1507    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1508    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1509
1510    // create a table
1511    Admin admin = UTIL.getAdmin();
1512
1513    admin.listNamespaces();
1514    assertTrue("preListNamespaces should have been called", cp.preListNamespacesCalled);
1515    assertTrue("postListNamespaces should have been called", cp.postListNamespacesCalled);
1516
1517    admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1518    assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
1519
1520    assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1521    assertTrue("Test namespace descriptor should have been called",
1522        cp.wasGetNamespaceDescriptorCalled());
1523    // This test used to do a bunch w/ bypass but bypass of these table and namespace stuff has
1524    // been removed so the testing code was removed.
1525  }
1526
1527  private void modifyTableSync(Admin admin, TableName tableName, HTableDescriptor htd)
1528      throws IOException {
1529    admin.modifyTable(tableName, htd);
1530    //wait until modify table finishes
1531    for (int t = 0; t < 100; t++) { //10 sec timeout
1532      HTableDescriptor td = admin.getTableDescriptor(htd.getTableName());
1533      if (td.equals(htd)) {
1534        break;
1535      }
1536      Threads.sleep(100);
1537    }
1538  }
1539
1540  @Test
1541  public void testRegionTransitionOperations() throws Exception {
1542    final TableName tableName = TableName.valueOf(name.getMethodName());
1543    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1544
1545    HMaster master = cluster.getMaster();
1546    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1547    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1548    cp.resetStates();
1549
1550    Table table = UTIL.createMultiRegionTable(tableName, TEST_FAMILY);
1551
1552    try (RegionLocator r = UTIL.getConnection().getRegionLocator(tableName)) {
1553      UTIL.waitUntilAllRegionsAssigned(tableName);
1554
1555      List<HRegionLocation> regions = r.getAllRegionLocations();
1556      HRegionLocation firstGoodPair = null;
1557      for (HRegionLocation e: regions) {
1558        if (e.getServerName() != null) {
1559          firstGoodPair = e;
1560          break;
1561        }
1562      }
1563      assertNotNull("Found a non-null entry", firstGoodPair);
1564      LOG.info("Found " + firstGoodPair.toString());
1565      // Try to force a move
1566      Collection<ServerName> servers = master.getClusterMetrics().getLiveServerMetrics().keySet();
1567      String destName = null;
1568      String serverNameForFirstRegion = firstGoodPair.getServerName().toString();
1569      LOG.info("serverNameForFirstRegion=" + serverNameForFirstRegion);
1570      ServerName masterServerName = master.getServerName();
1571      boolean found = false;
1572      // Find server that is NOT carrying the first region
1573      for (ServerName info : servers) {
1574        LOG.info("ServerName=" + info);
1575        if (!serverNameForFirstRegion.equals(info.getServerName())
1576            && !masterServerName.equals(info)) {
1577          destName = info.toString();
1578          found = true;
1579          break;
1580        }
1581      }
1582      assertTrue("Found server", found);
1583      LOG.info("Found " + destName);
1584      master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1585          firstGoodPair.getRegionInfo().getEncodedNameAsBytes(), ServerName.valueOf(destName)));
1586      assertTrue("Coprocessor should have been called on region move",
1587        cp.wasMoveCalled());
1588
1589      // make sure balancer is on
1590      master.balanceSwitch(true);
1591      assertTrue("Coprocessor should have been called on balance switch",
1592          cp.wasBalanceSwitchCalled());
1593
1594      // turn balancer off
1595      master.balanceSwitch(false);
1596
1597      // wait for assignments to finish, if any
1598      UTIL.waitUntilNoRegionsInTransition();
1599
1600      // move half the open regions from RS 0 to RS 1
1601      HRegionServer rs = cluster.getRegionServer(0);
1602      byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
1603      //Make sure no regions are in transition now
1604      UTIL.waitUntilNoRegionsInTransition();
1605      List<RegionInfo> openRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
1606      int moveCnt = openRegions.size()/2;
1607      for (int i = 0; i < moveCnt; i++) {
1608        RegionInfo info = openRegions.get(i);
1609        if (!info.isMetaRegion()) {
1610          master.getMasterRpcServices().moveRegion(null,
1611            RequestConverter.buildMoveRegionRequest(openRegions.get(i).getEncodedNameAsBytes(),
1612              ServerName.valueOf(Bytes.toString(destRS))));
1613        }
1614      }
1615      //Make sure no regions are in transition now
1616      UTIL.waitUntilNoRegionsInTransition();
1617      // now trigger a balance
1618      master.balanceSwitch(true);
1619      boolean balanceRun = master.balance();
1620      assertTrue("Coprocessor should be called on region rebalancing",
1621          cp.wasBalanceCalled());
1622    } finally {
1623      Admin admin = UTIL.getAdmin();
1624      admin.disableTable(tableName);
1625      deleteTable(admin, tableName);
1626    }
1627  }
1628
1629  @Test
1630  public void testTableDescriptorsEnumeration() throws Exception {
1631    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1632
1633    HMaster master = cluster.getMaster();
1634    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1635    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1636    cp.resetStates();
1637
1638    GetTableDescriptorsRequest req =
1639        RequestConverter.buildGetTableDescriptorsRequest((List<TableName>)null);
1640    master.getMasterRpcServices().getTableDescriptors(null, req);
1641
1642    assertTrue("Coprocessor should be called on table descriptors request",
1643      cp.wasGetTableDescriptorsCalled());
1644  }
1645
1646  @Test
1647  public void testTableNamesEnumeration() throws Exception {
1648    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1649
1650    HMaster master = cluster.getMaster();
1651    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1652    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1653    cp.resetStates();
1654
1655    master.getMasterRpcServices().getTableNames(null,
1656        GetTableNamesRequest.newBuilder().build());
1657    assertTrue("Coprocessor should be called on table names request",
1658      cp.wasGetTableNamesCalled());
1659  }
1660
1661  @Test
1662  public void testAbortProcedureOperation() throws Exception {
1663    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1664
1665    HMaster master = cluster.getMaster();
1666    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1667    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1668    cp.resetStates();
1669
1670    master.abortProcedure(1, true);
1671    assertTrue(
1672      "Coprocessor should be called on abort procedure request",
1673      cp.wasAbortProcedureCalled());
1674  }
1675
1676  @Test
1677  public void testGetProceduresOperation() throws Exception {
1678    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1679
1680    HMaster master = cluster.getMaster();
1681    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1682    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1683    cp.resetStates();
1684
1685    master.getProcedures();
1686    assertTrue(
1687      "Coprocessor should be called on get procedures request",
1688      cp.wasGetProceduresCalled());
1689  }
1690
1691  @Test
1692  public void testGetLocksOperation() throws Exception {
1693    MiniHBaseCluster cluster = UTIL.getHBaseCluster();
1694
1695    HMaster master = cluster.getMaster();
1696    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1697    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1698    cp.resetStates();
1699
1700    master.getLocks();
1701    assertTrue(
1702      "Coprocessor should be called on get locks request",
1703      cp.wasGetLocksCalled());
1704  }
1705
1706  private void deleteTable(Admin admin, TableName tableName) throws Exception {
1707    // NOTE: We need a latch because admin is not sync,
1708    // so the postOp coprocessor method may be called after the admin operation returned.
1709    tableDeletionLatch = new CountDownLatch(1);
1710    admin.deleteTable(tableName);
1711    tableDeletionLatch.await();
1712    tableDeletionLatch = new CountDownLatch(1);
1713  }
1714
1715  @Test
1716  public void testQueueLockAndLockHeartbeatOperations() throws Exception {
1717    HMaster master = UTIL.getMiniHBaseCluster().getMaster();
1718    CPMasterObserver cp = master.getMasterCoprocessorHost().findCoprocessor(CPMasterObserver.class);
1719    cp.resetStates();
1720
1721    final TableName tableName = TableName.valueOf("testLockedTable");
1722    long procId = master.getLockManager().remoteLocks().requestTableLock(tableName,
1723          LockType.EXCLUSIVE, "desc", null);
1724    master.getLockManager().remoteLocks().lockHeartbeat(procId, false);
1725
1726    assertTrue(cp.preAndPostForQueueLockAndHeartbeatLockCalled());
1727
1728    ProcedureTestingUtility.waitNoProcedureRunning(master.getMasterProcedureExecutor());
1729    ProcedureTestingUtility.assertProcNotFailed(master.getMasterProcedureExecutor(), procId);
1730  }
1731}