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