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.HBaseTestingUtil;
035import org.apache.hadoop.hbase.HRegionLocation;
036import org.apache.hadoop.hbase.NamespaceDescriptor;
037import org.apache.hadoop.hbase.ServerName;
038import org.apache.hadoop.hbase.SingleProcessHBaseCluster;
039import org.apache.hadoop.hbase.TableName;
040import org.apache.hadoop.hbase.client.Admin;
041import org.apache.hadoop.hbase.client.BalanceRequest;
042import org.apache.hadoop.hbase.client.BalanceResponse;
043import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
044import org.apache.hadoop.hbase.client.Connection;
045import org.apache.hadoop.hbase.client.ConnectionFactory;
046import org.apache.hadoop.hbase.client.MasterSwitchType;
047import org.apache.hadoop.hbase.client.Mutation;
048import org.apache.hadoop.hbase.client.RegionInfo;
049import org.apache.hadoop.hbase.client.RegionLocator;
050import org.apache.hadoop.hbase.client.SnapshotDescription;
051import org.apache.hadoop.hbase.client.Table;
052import org.apache.hadoop.hbase.client.TableDescriptor;
053import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
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, final TableDescriptor currentDescriptor,
385      final TableDescriptor newDescriptor) throws IOException {
386      preModifyTableCalled = true;
387      return newDescriptor;
388    }
389
390    @Override
391    public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> env,
392      TableName tableName, final TableDescriptor oldDescriptor,
393      final TableDescriptor currentDescriptor) throws IOException {
394      postModifyTableCalled = true;
395    }
396
397    public boolean wasModifyTableCalled() {
398      return preModifyTableCalled && postModifyTableCalled;
399    }
400
401    public boolean preModifyTableCalledOnly() {
402      return preModifyTableCalled && !postModifyTableCalled;
403    }
404
405    @Override
406    public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
407      NamespaceDescriptor ns) throws IOException {
408      preCreateNamespaceCalled = true;
409    }
410
411    @Override
412    public void postCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
413      NamespaceDescriptor ns) throws IOException {
414      postCreateNamespaceCalled = true;
415    }
416
417    public boolean wasCreateNamespaceCalled() {
418      return preCreateNamespaceCalled && postCreateNamespaceCalled;
419    }
420
421    public boolean preCreateNamespaceCalledOnly() {
422      return preCreateNamespaceCalled && !postCreateNamespaceCalled;
423    }
424
425    @Override
426    public void preDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env, String name)
427      throws IOException {
428      preDeleteNamespaceCalled = true;
429    }
430
431    @Override
432    public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> env, String name)
433      throws IOException {
434      postDeleteNamespaceCalled = true;
435    }
436
437    public boolean wasDeleteNamespaceCalled() {
438      return preDeleteNamespaceCalled && postDeleteNamespaceCalled;
439    }
440
441    public boolean preDeleteNamespaceCalledOnly() {
442      return preDeleteNamespaceCalled && !postDeleteNamespaceCalled;
443    }
444
445    @Override
446    public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
447      NamespaceDescriptor currentNsDesc, NamespaceDescriptor newNsDesc) throws IOException {
448      preModifyNamespaceCalled = true;
449    }
450
451    @Override
452    public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> env,
453      NamespaceDescriptor oldNsDesc, NamespaceDescriptor currentNsDesc) throws IOException {
454      postModifyNamespaceCalled = true;
455    }
456
457    public boolean wasModifyNamespaceCalled() {
458      return preModifyNamespaceCalled && postModifyNamespaceCalled;
459    }
460
461    public boolean preModifyNamespaceCalledOnly() {
462      return preModifyNamespaceCalled && !postModifyNamespaceCalled;
463    }
464
465    @Override
466    public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
467      String namespace) throws IOException {
468      preGetNamespaceDescriptorCalled = true;
469    }
470
471    @Override
472    public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
473      NamespaceDescriptor ns) throws IOException {
474      postGetNamespaceDescriptorCalled = true;
475    }
476
477    public boolean wasGetNamespaceDescriptorCalled() {
478      return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
479    }
480
481    @Override
482    public void preListNamespaces(ObserverContext<MasterCoprocessorEnvironment> ctx,
483      List<String> namespaces) {
484      preListNamespacesCalled = true;
485    }
486
487    @Override
488    public void postListNamespaces(ObserverContext<MasterCoprocessorEnvironment> ctx,
489      List<String> namespaces) {
490      postListNamespacesCalled = true;
491    }
492
493    @Override
494    public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
495      List<NamespaceDescriptor> descriptors) throws IOException {
496      preListNamespaceDescriptorsCalled = true;
497    }
498
499    @Override
500    public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
501      List<NamespaceDescriptor> descriptors) throws IOException {
502      postListNamespaceDescriptorsCalled = true;
503    }
504
505    public boolean wasListNamespaceDescriptorsCalled() {
506      return preListNamespaceDescriptorsCalled && postListNamespaceDescriptorsCalled;
507    }
508
509    public boolean preListNamespaceDescriptorsCalledOnly() {
510      return preListNamespaceDescriptorsCalled && !postListNamespaceDescriptorsCalled;
511    }
512
513    @Override
514    public void preEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
515      TableName tableName) throws IOException {
516      preEnableTableCalled = true;
517    }
518
519    @Override
520    public void postEnableTable(ObserverContext<MasterCoprocessorEnvironment> env,
521      TableName tableName) throws IOException {
522      postEnableTableCalled = true;
523    }
524
525    public boolean wasEnableTableCalled() {
526      return preEnableTableCalled && postEnableTableCalled;
527    }
528
529    public boolean preEnableTableCalledOnly() {
530      return preEnableTableCalled && !postEnableTableCalled;
531    }
532
533    @Override
534    public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
535      TableName tableName) throws IOException {
536      preDisableTableCalled = true;
537    }
538
539    @Override
540    public void postDisableTable(ObserverContext<MasterCoprocessorEnvironment> env,
541      TableName tableName) throws IOException {
542      postDisableTableCalled = true;
543    }
544
545    public boolean wasDisableTableCalled() {
546      return preDisableTableCalled && postDisableTableCalled;
547    }
548
549    public boolean preDisableTableCalledOnly() {
550      return preDisableTableCalled && !postDisableTableCalled;
551    }
552
553    @Override
554    public void preAbortProcedure(ObserverContext<MasterCoprocessorEnvironment> ctx,
555      final long procId) throws IOException {
556      preAbortProcedureCalled = true;
557    }
558
559    @Override
560    public void postAbortProcedure(ObserverContext<MasterCoprocessorEnvironment> ctx)
561      throws IOException {
562      postAbortProcedureCalled = true;
563    }
564
565    public boolean wasAbortProcedureCalled() {
566      return preAbortProcedureCalled && postAbortProcedureCalled;
567    }
568
569    public boolean wasPreAbortProcedureCalledOnly() {
570      return preAbortProcedureCalled && !postAbortProcedureCalled;
571    }
572
573    @Override
574    public void preGetProcedures(ObserverContext<MasterCoprocessorEnvironment> ctx)
575      throws IOException {
576      preGetProceduresCalled = true;
577    }
578
579    @Override
580    public void postGetProcedures(ObserverContext<MasterCoprocessorEnvironment> ctx)
581      throws IOException {
582      postGetProceduresCalled = true;
583    }
584
585    public boolean wasGetProceduresCalled() {
586      return preGetProceduresCalled && postGetProceduresCalled;
587    }
588
589    public boolean wasPreGetProceduresCalledOnly() {
590      return preGetProceduresCalled && !postGetProceduresCalled;
591    }
592
593    @Override
594    public void preGetLocks(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
595      preGetLocksCalled = true;
596    }
597
598    @Override
599    public void postGetLocks(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
600      postGetLocksCalled = true;
601    }
602
603    public boolean wasGetLocksCalled() {
604      return preGetLocksCalled && postGetLocksCalled;
605    }
606
607    public boolean wasPreGetLocksCalledOnly() {
608      return preGetLocksCalled && !postGetLocksCalled;
609    }
610
611    @Override
612    public void preMove(ObserverContext<MasterCoprocessorEnvironment> env, RegionInfo region,
613      ServerName srcServer, ServerName destServer) throws IOException {
614      preMoveCalled = true;
615    }
616
617    @Override
618    public void postMove(ObserverContext<MasterCoprocessorEnvironment> env, RegionInfo region,
619      ServerName srcServer, ServerName destServer) 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      BalanceRequest request) throws IOException {
694      preBalanceCalled = true;
695    }
696
697    @Override
698    public void postBalance(ObserverContext<MasterCoprocessorEnvironment> env,
699      BalanceRequest request, 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) throws IOException {
733      preShutdownCalled = true;
734    }
735
736    public boolean wasShutdownCalled() {
737      return preShutdownCalled;
738    }
739
740    @Override
741    public void preStopMaster(ObserverContext<MasterCoprocessorEnvironment> env)
742      throws IOException {
743      preStopMasterCalled = true;
744    }
745
746    public boolean wasStopMasterCalled() {
747      return preStopMasterCalled;
748    }
749
750    @Override
751    public void preMasterInitialization(ObserverContext<MasterCoprocessorEnvironment> ctx)
752      throws IOException {
753      preMasterInitializationCalled = true;
754    }
755
756    public boolean wasMasterInitializationCalled() {
757      return preMasterInitializationCalled;
758    }
759
760    @Override
761    public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx)
762      throws IOException {
763      postStartMasterCalled = true;
764    }
765
766    public boolean wasStartMasterCalled() {
767      return postStartMasterCalled;
768    }
769
770    @Override
771    public void start(CoprocessorEnvironment env) throws IOException {
772      startCalled = true;
773    }
774
775    @Override
776    public void stop(CoprocessorEnvironment env) throws IOException {
777      stopCalled = true;
778    }
779
780    public boolean wasStarted() {
781      return startCalled;
782    }
783
784    public boolean wasStopped() {
785      return stopCalled;
786    }
787
788    @Override
789    public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
790      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
791      throws IOException {
792      preSnapshotCalled = true;
793    }
794
795    @Override
796    public void postSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
797      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
798      throws IOException {
799      postSnapshotCalled = true;
800    }
801
802    public boolean wasSnapshotCalled() {
803      return preSnapshotCalled && postSnapshotCalled;
804    }
805
806    @Override
807    public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
808      final SnapshotDescription snapshot) throws IOException {
809      preListSnapshotCalled = true;
810    }
811
812    @Override
813    public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
814      final SnapshotDescription snapshot) throws IOException {
815      postListSnapshotCalled = true;
816    }
817
818    public boolean wasListSnapshotCalled() {
819      return preListSnapshotCalled && postListSnapshotCalled;
820    }
821
822    @Override
823    public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
824      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
825      throws IOException {
826      preCloneSnapshotCalled = true;
827    }
828
829    @Override
830    public void postCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
831      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
832      throws IOException {
833      postCloneSnapshotCalled = true;
834    }
835
836    public boolean wasCloneSnapshotCalled() {
837      return preCloneSnapshotCalled && postCloneSnapshotCalled;
838    }
839
840    @Override
841    public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
842      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
843      throws IOException {
844      preRestoreSnapshotCalled = true;
845    }
846
847    @Override
848    public void postRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
849      final SnapshotDescription snapshot, final TableDescriptor hTableDescriptor)
850      throws IOException {
851      postRestoreSnapshotCalled = true;
852    }
853
854    public boolean wasRestoreSnapshotCalled() {
855      return preRestoreSnapshotCalled && postRestoreSnapshotCalled;
856    }
857
858    @Override
859    public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
860      final SnapshotDescription snapshot) throws IOException {
861      preDeleteSnapshotCalled = true;
862    }
863
864    @Override
865    public void postDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
866      final SnapshotDescription snapshot) throws IOException {
867      postDeleteSnapshotCalled = true;
868    }
869
870    public boolean wasDeleteSnapshotCalled() {
871      return preDeleteSnapshotCalled && postDeleteSnapshotCalled;
872    }
873
874    @Override
875    public void preCreateTableAction(final ObserverContext<MasterCoprocessorEnvironment> env,
876      final TableDescriptor desc, final RegionInfo[] regions) throws IOException {
877      preCreateTableActionCalled = true;
878    }
879
880    @Override
881    public void postCompletedCreateTableAction(
882      final ObserverContext<MasterCoprocessorEnvironment> ctx, 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
892    public boolean wasCreateTableActionCalled() {
893      return preCreateTableActionCalled && postCompletedCreateTableActionCalled;
894    }
895
896    public boolean wasCreateTableActionCalledOnly() {
897      return preCreateTableActionCalled && !postCompletedCreateTableActionCalled;
898    }
899
900    @Override
901    public void preDeleteTableAction(final ObserverContext<MasterCoprocessorEnvironment> env,
902      final TableName tableName) 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(final ObserverContext<MasterCoprocessorEnvironment> env,
924      final TableName tableName) throws IOException {
925      preTruncateTableActionCalled = true;
926    }
927
928    @Override
929    public void postCompletedTruncateTableAction(
930      final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
931      throws IOException {
932      postCompletedTruncateTableActionCalled = true;
933    }
934
935    public boolean wasTruncateTableActionCalled() {
936      return preTruncateTableActionCalled && postCompletedTruncateTableActionCalled;
937    }
938
939    public boolean wasTruncateTableActionCalledOnly() {
940      return preTruncateTableActionCalled && !postCompletedTruncateTableActionCalled;
941    }
942
943    @Override
944    public void preModifyTableAction(final ObserverContext<MasterCoprocessorEnvironment> env,
945      final TableName tableName, final TableDescriptor currentDescriptor,
946      final TableDescriptor newDescriptor) throws IOException {
947      preModifyTableActionCalled = true;
948    }
949
950    @Override
951    public void postCompletedModifyTableAction(
952      final ObserverContext<MasterCoprocessorEnvironment> env, final TableName tableName,
953      final TableDescriptor oldDescriptor, final TableDescriptor currentDescriptor)
954      throws IOException {
955      postCompletedModifyTableActionCalled = true;
956    }
957
958    public boolean wasModifyTableActionCalled() {
959      return preModifyTableActionCalled && postCompletedModifyTableActionCalled;
960    }
961
962    public boolean wasModifyTableActionCalledOnly() {
963      return preModifyTableActionCalled && !postCompletedModifyTableActionCalled;
964    }
965
966    @Override
967    public void preEnableTableAction(final ObserverContext<MasterCoprocessorEnvironment> ctx,
968      final TableName tableName) throws IOException {
969      preEnableTableActionCalled = true;
970    }
971
972    @Override
973    public void postCompletedEnableTableAction(
974      final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
975      throws IOException {
976      postCompletedEnableTableActionCalled = true;
977    }
978
979    public boolean wasEnableTableActionCalled() {
980      return preEnableTableActionCalled && postCompletedEnableTableActionCalled;
981    }
982
983    public boolean preEnableTableActionCalledOnly() {
984      return preEnableTableActionCalled && !postCompletedEnableTableActionCalled;
985    }
986
987    @Override
988    public void preDisableTableAction(final ObserverContext<MasterCoprocessorEnvironment> ctx,
989      final TableName tableName) throws IOException {
990      preDisableTableActionCalled = true;
991    }
992
993    @Override
994    public void postCompletedDisableTableAction(
995      final ObserverContext<MasterCoprocessorEnvironment> ctx, final TableName tableName)
996      throws IOException {
997      postCompletedDisableTableActionCalled = true;
998    }
999
1000    public boolean wasDisableTableActionCalled() {
1001      return preDisableTableActionCalled && postCompletedDisableTableActionCalled;
1002    }
1003
1004    public boolean preDisableTableActionCalledOnly() {
1005      return preDisableTableActionCalled && !postCompletedDisableTableActionCalled;
1006    }
1007
1008    @Override
1009    public void preGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1010      List<TableName> tableNamesList, List<TableDescriptor> descriptors, String regex)
1011      throws IOException {
1012      preGetTableDescriptorsCalled = true;
1013    }
1014
1015    @Override
1016    public void postGetTableDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
1017      List<TableName> tableNamesList, List<TableDescriptor> descriptors, String regex)
1018      throws IOException {
1019      postGetTableDescriptorsCalled = true;
1020    }
1021
1022    public boolean wasGetTableDescriptorsCalled() {
1023      return preGetTableDescriptorsCalled && postGetTableDescriptorsCalled;
1024    }
1025
1026    @Override
1027    public void preGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1028      List<TableDescriptor> descriptors, String regex) throws IOException {
1029      preGetTableNamesCalled = true;
1030    }
1031
1032    @Override
1033    public void postGetTableNames(ObserverContext<MasterCoprocessorEnvironment> ctx,
1034      List<TableDescriptor> descriptors, String regex) throws IOException {
1035      postGetTableNamesCalled = true;
1036    }
1037
1038    public boolean wasGetTableNamesCalled() {
1039      return preGetTableNamesCalled && postGetTableNamesCalled;
1040    }
1041
1042    @Override
1043    public void preTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1044      TableName tableName) throws IOException {
1045    }
1046
1047    @Override
1048    public void postTableFlush(ObserverContext<MasterCoprocessorEnvironment> ctx,
1049      TableName tableName) throws IOException {
1050    }
1051
1052    @Override
1053    public void preMasterStoreFlush(ObserverContext<MasterCoprocessorEnvironment> ctx)
1054      throws IOException {
1055      preMasterStoreFlushCalled = true;
1056    }
1057
1058    @Override
1059    public void postMasterStoreFlush(ObserverContext<MasterCoprocessorEnvironment> ctx)
1060      throws IOException {
1061      postMasterStoreFlushCalled = true;
1062    }
1063
1064    @Override
1065    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1066      final String userName, final GlobalQuotaSettings quotas) throws IOException {
1067    }
1068
1069    @Override
1070    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1071      final String userName, final GlobalQuotaSettings quotas) throws IOException {
1072    }
1073
1074    @Override
1075    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1076      final String userName, final TableName tableName, final GlobalQuotaSettings quotas)
1077      throws IOException {
1078    }
1079
1080    @Override
1081    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1082      final String userName, final TableName tableName, final GlobalQuotaSettings quotas)
1083      throws IOException {
1084    }
1085
1086    @Override
1087    public void preSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1088      final String userName, final String namespace, final GlobalQuotaSettings quotas)
1089      throws IOException {
1090    }
1091
1092    @Override
1093    public void postSetUserQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1094      final String userName, final String namespace, final GlobalQuotaSettings quotas)
1095      throws IOException {
1096    }
1097
1098    @Override
1099    public void preSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1100      final TableName tableName, final GlobalQuotaSettings quotas) throws IOException {
1101    }
1102
1103    @Override
1104    public void postSetTableQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1105      final TableName tableName, final GlobalQuotaSettings quotas) throws IOException {
1106    }
1107
1108    @Override
1109    public void preSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1110      final String namespace, final GlobalQuotaSettings quotas) throws IOException {
1111    }
1112
1113    @Override
1114    public void postSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1115      final String namespace, final GlobalQuotaSettings quotas) throws IOException {
1116    }
1117
1118    @Override
1119    public void preMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1120      Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
1121    }
1122
1123    @Override
1124    public void postMoveServersAndTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1125      Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
1126    }
1127
1128    @Override
1129    public void preMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1130      Set<Address> servers, String targetGroup) throws IOException {
1131    }
1132
1133    @Override
1134    public void postMoveServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
1135      Set<Address> servers, String targetGroup) throws IOException {
1136    }
1137
1138    @Override
1139    public void preMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1140      Set<TableName> tables, String targetGroupGroup) throws IOException {
1141    }
1142
1143    @Override
1144    public void postMoveTables(ObserverContext<MasterCoprocessorEnvironment> ctx,
1145      Set<TableName> tables, String targetGroup) throws IOException {
1146    }
1147
1148    @Override
1149    public void preAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1150      throws IOException {
1151    }
1152
1153    @Override
1154    public void postAddRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1155      throws IOException {
1156    }
1157
1158    @Override
1159    public void preRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1160      throws IOException {
1161    }
1162
1163    @Override
1164    public void postRemoveRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String name)
1165      throws IOException {
1166    }
1167
1168    @Override
1169    public void preBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1170      String groupName, BalanceRequest request) throws IOException {
1171    }
1172
1173    @Override
1174    public void postBalanceRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
1175      String groupName, BalanceRequest request, BalanceResponse response) throws IOException {
1176    }
1177
1178    @Override
1179    public void preRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
1180      TableName tableName, RegionInfo[] regionInfos, String description) throws IOException {
1181      preRequestLockCalled = true;
1182    }
1183
1184    @Override
1185    public void postRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
1186      TableName tableName, RegionInfo[] regionInfos, String description) throws IOException {
1187      postRequestLockCalled = true;
1188    }
1189
1190    @Override
1191    public void preLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tn,
1192      String description) throws IOException {
1193      preLockHeartbeatCalled = true;
1194    }
1195
1196    @Override
1197    public void postLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx)
1198      throws IOException {
1199      postLockHeartbeatCalled = true;
1200    }
1201
1202    public boolean preAndPostForQueueLockAndHeartbeatLockCalled() {
1203      return preRequestLockCalled && postRequestLockCalled && preLockHeartbeatCalled
1204        && postLockHeartbeatCalled;
1205    }
1206
1207    @Override
1208    public void preSplitRegion(final ObserverContext<MasterCoprocessorEnvironment> c,
1209      final TableName tableName, final byte[] splitRow) throws IOException {
1210    }
1211
1212    @Override
1213    public void preSplitRegionAction(final ObserverContext<MasterCoprocessorEnvironment> c,
1214      final TableName tableName, final byte[] splitRow) throws IOException {
1215    }
1216
1217    @Override
1218    public void postCompletedSplitRegionAction(
1219      final ObserverContext<MasterCoprocessorEnvironment> c, final RegionInfo regionInfoA,
1220      final RegionInfo regionInfoB) throws IOException {
1221    }
1222
1223    @Override
1224    public void preSplitRegionBeforeMETAAction(
1225      final ObserverContext<MasterCoprocessorEnvironment> ctx, final byte[] splitKey,
1226      final List<Mutation> metaEntries) throws IOException {
1227    }
1228
1229    @Override
1230    public void preSplitRegionAfterMETAAction(
1231      final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
1232    }
1233
1234    @Override
1235    public void postRollBackSplitRegionAction(
1236      final ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException {
1237    }
1238
1239    @Override
1240    public void preMergeRegionsAction(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1241      final RegionInfo[] regionsToMerge) throws IOException {
1242    }
1243
1244    @Override
1245    public void postCompletedMergeRegionsAction(
1246      final ObserverContext<MasterCoprocessorEnvironment> c, final RegionInfo[] regionsToMerge,
1247      final RegionInfo mergedRegion) throws IOException {
1248    }
1249
1250    @Override
1251    public void preMergeRegionsCommitAction(final ObserverContext<MasterCoprocessorEnvironment> ctx,
1252      final RegionInfo[] regionsToMerge, final List<Mutation> metaEntries) throws IOException {
1253    }
1254
1255    @Override
1256    public void postMergeRegionsCommitAction(
1257      final ObserverContext<MasterCoprocessorEnvironment> ctx, final RegionInfo[] regionsToMerge,
1258      final RegionInfo mergedRegion) throws IOException {
1259    }
1260
1261    @Override
1262    public void postRollBackMergeRegionsAction(
1263      final ObserverContext<MasterCoprocessorEnvironment> ctx, final RegionInfo[] regionsToMerge)
1264      throws IOException {
1265    }
1266
1267  }
1268
1269  private static HBaseTestingUtil UTIL = new HBaseTestingUtil();
1270  private static String TEST_SNAPSHOT = "observed_snapshot";
1271  private static TableName TEST_CLONE = TableName.valueOf("observed_clone");
1272  private static byte[] TEST_FAMILY = Bytes.toBytes("fam1");
1273  @Rule
1274  public TestName name = new TestName();
1275
1276  @BeforeClass
1277  public static void setupBeforeClass() throws Exception {
1278    Configuration conf = UTIL.getConfiguration();
1279    conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, CPMasterObserver.class.getName());
1280    // We need more than one data server on this test
1281    UTIL.startMiniCluster(2);
1282  }
1283
1284  @AfterClass
1285  public static void tearDownAfterClass() throws Exception {
1286    UTIL.shutdownMiniCluster();
1287  }
1288
1289  @Test
1290  public void testStarted() throws Exception {
1291    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1292
1293    HMaster master = cluster.getMaster();
1294    assertTrue("Master should be active", master.isActiveMaster());
1295    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1296    assertNotNull("CoprocessorHost should not be null", host);
1297    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1298    assertNotNull("CPMasterObserver coprocessor not found or not installed!", cp);
1299
1300    // check basic lifecycle
1301    assertTrue("MasterObserver should have been started", cp.wasStarted());
1302    assertTrue("preMasterInitialization() hook should have been called",
1303      cp.wasMasterInitializationCalled());
1304    assertTrue("postStartMaster() hook should have been called", cp.wasStartMasterCalled());
1305  }
1306
1307  @Test
1308  public void testTableOperations() throws Exception {
1309    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1310    final TableName tableName = TableName.valueOf(name.getMethodName());
1311    HMaster master = cluster.getMaster();
1312    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1313    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1314    cp.resetStates();
1315    assertFalse("No table created yet", cp.wasCreateTableCalled());
1316
1317    // create a table
1318    TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName)
1319      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build();
1320    try (Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
1321      Admin admin = connection.getAdmin()) {
1322      tableCreationLatch = new CountDownLatch(1);
1323      admin.createTable(tableDescriptor,
1324        Arrays.copyOfRange(HBaseTestingUtil.KEYS, 1, HBaseTestingUtil.KEYS.length));
1325
1326      assertTrue("Test table should be created", cp.wasCreateTableCalled());
1327      tableCreationLatch.await();
1328      assertTrue("Table pre create handler called.", cp.wasPreCreateTableActionCalled());
1329      assertTrue("Table create handler should be called.", cp.wasCreateTableActionCalled());
1330
1331      RegionLocator regionLocator = connection.getRegionLocator(tableDescriptor.getTableName());
1332      List<HRegionLocation> regions = regionLocator.getAllRegionLocations();
1333
1334      admin.mergeRegionsAsync(regions.get(0).getRegion().getEncodedNameAsBytes(),
1335        regions.get(1).getRegion().getEncodedNameAsBytes(), true).get();
1336      assertTrue("Coprocessor should have been called on region merge", cp.wasMergeRegionsCalled());
1337
1338      tableCreationLatch = new CountDownLatch(1);
1339      admin.disableTable(tableName);
1340      assertTrue(admin.isTableDisabled(tableName));
1341      assertTrue("Coprocessor should have been called on table disable",
1342        cp.wasDisableTableCalled());
1343      assertTrue("Disable table handler should be called.", cp.wasDisableTableActionCalled());
1344
1345      // enable
1346      assertFalse(cp.wasEnableTableCalled());
1347      admin.enableTable(tableName);
1348      assertTrue(admin.isTableEnabled(tableName));
1349      assertTrue("Coprocessor should have been called on table enable", cp.wasEnableTableCalled());
1350      assertTrue("Enable table handler should be called.", cp.wasEnableTableActionCalled());
1351
1352      admin.disableTable(tableName);
1353      assertTrue(admin.isTableDisabled(tableName));
1354
1355      // modify table
1356      tableDescriptor = TableDescriptorBuilder.newBuilder(tableDescriptor)
1357        .setMaxFileSize(512 * 1024 * 1024).build();
1358      modifyTableSync(admin, tableName, tableDescriptor);
1359      assertTrue("Test table should have been modified", cp.wasModifyTableCalled());
1360
1361      // truncate table
1362      admin.truncateTable(tableName, false);
1363
1364      // delete table
1365      admin.disableTable(tableName);
1366      assertTrue(admin.isTableDisabled(tableName));
1367      deleteTable(admin, tableName);
1368      assertFalse("Test table should have been deleted", admin.tableExists(tableName));
1369      assertTrue("Coprocessor should have been called on table delete", cp.wasDeleteTableCalled());
1370      assertTrue("Delete table handler should be called.", cp.wasDeleteTableActionCalled());
1371
1372      // When bypass was supported, we'd turn off bypass and rerun tests. Leaving rerun in place.
1373      cp.resetStates();
1374
1375      admin.createTable(tableDescriptor);
1376      assertTrue("Test table should be created", cp.wasCreateTableCalled());
1377      tableCreationLatch.await();
1378      assertTrue("Table pre create handler called.", cp.wasPreCreateTableActionCalled());
1379      assertTrue("Table create handler should be called.", cp.wasCreateTableActionCalled());
1380
1381      // disable
1382      assertFalse(cp.wasDisableTableCalled());
1383      assertFalse(cp.wasDisableTableActionCalled());
1384      admin.disableTable(tableName);
1385      assertTrue(admin.isTableDisabled(tableName));
1386      assertTrue("Coprocessor should have been called on table disable",
1387        cp.wasDisableTableCalled());
1388      assertTrue("Disable table handler should be called.", cp.wasDisableTableActionCalled());
1389
1390      // modify table
1391      tableDescriptor = TableDescriptorBuilder.newBuilder(tableDescriptor)
1392        .setMaxFileSize(512 * 1024 * 1024).build();
1393      modifyTableSync(admin, tableName, tableDescriptor);
1394      assertTrue("Test table should have been modified", cp.wasModifyTableCalled());
1395
1396      // enable
1397      assertFalse(cp.wasEnableTableCalled());
1398      assertFalse(cp.wasEnableTableActionCalled());
1399      admin.enableTable(tableName);
1400      assertTrue(admin.isTableEnabled(tableName));
1401      assertTrue("Coprocessor should have been called on table enable", cp.wasEnableTableCalled());
1402      assertTrue("Enable table handler should be called.", cp.wasEnableTableActionCalled());
1403
1404      // disable again
1405      admin.disableTable(tableName);
1406      assertTrue(admin.isTableDisabled(tableName));
1407
1408      // delete table
1409      assertFalse("No table deleted yet", cp.wasDeleteTableCalled());
1410      assertFalse("Delete table handler should not be called.", cp.wasDeleteTableActionCalled());
1411      deleteTable(admin, tableName);
1412      assertFalse("Test table should have been deleted", admin.tableExists(tableName));
1413      assertTrue("Coprocessor should have been called on table delete", cp.wasDeleteTableCalled());
1414      assertTrue("Delete table handler should be called.", cp.wasDeleteTableActionCalled());
1415    }
1416  }
1417
1418  @Test
1419  public void testSnapshotOperations() throws Exception {
1420    final TableName tableName = TableName.valueOf(name.getMethodName());
1421    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1422    HMaster master = cluster.getMaster();
1423    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1424    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1425    cp.resetStates();
1426
1427    // create a table
1428    TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName)
1429      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build();
1430    Admin admin = UTIL.getAdmin();
1431
1432    tableCreationLatch = new CountDownLatch(1);
1433    admin.createTable(tableDescriptor);
1434    tableCreationLatch.await();
1435    tableCreationLatch = new CountDownLatch(1);
1436
1437    admin.disableTable(tableName);
1438    assertTrue(admin.isTableDisabled(tableName));
1439
1440    try {
1441      // Test snapshot operation
1442      assertFalse("Coprocessor should not have been called yet", cp.wasSnapshotCalled());
1443      admin.snapshot(TEST_SNAPSHOT, tableName);
1444      assertTrue("Coprocessor should have been called on snapshot", cp.wasSnapshotCalled());
1445
1446      // Test list operation
1447      admin.listSnapshots();
1448      assertTrue("Coprocessor should have been called on snapshot list",
1449        cp.wasListSnapshotCalled());
1450
1451      // Test clone operation
1452      admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
1453      assertTrue("Coprocessor should have been called on snapshot clone",
1454        cp.wasCloneSnapshotCalled());
1455      assertFalse("Coprocessor restore should not have been called on snapshot clone",
1456        cp.wasRestoreSnapshotCalled());
1457      admin.disableTable(TEST_CLONE);
1458      assertTrue(admin.isTableDisabled(tableName));
1459      deleteTable(admin, TEST_CLONE);
1460
1461      // Test restore operation
1462      cp.resetStates();
1463      admin.restoreSnapshot(TEST_SNAPSHOT);
1464      assertTrue("Coprocessor should have been called on snapshot restore",
1465        cp.wasRestoreSnapshotCalled());
1466      assertFalse("Coprocessor clone should not have been called on snapshot restore",
1467        cp.wasCloneSnapshotCalled());
1468
1469      admin.deleteSnapshot(TEST_SNAPSHOT);
1470      assertTrue("Coprocessor should have been called on snapshot delete",
1471        cp.wasDeleteSnapshotCalled());
1472    } finally {
1473      deleteTable(admin, tableName);
1474    }
1475  }
1476
1477  @Test
1478  public void testNamespaceOperations() throws Exception {
1479    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1480    String testNamespace = "observed_ns";
1481    HMaster master = cluster.getMaster();
1482    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1483    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1484
1485    // create a table
1486    Admin admin = UTIL.getAdmin();
1487
1488    admin.listNamespaces();
1489    assertTrue("preListNamespaces should have been called", cp.preListNamespacesCalled);
1490    assertTrue("postListNamespaces should have been called", cp.postListNamespacesCalled);
1491
1492    admin.createNamespace(NamespaceDescriptor.create(testNamespace).build());
1493    assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
1494
1495    assertNotNull(admin.getNamespaceDescriptor(testNamespace));
1496    assertTrue("Test namespace descriptor should have been called",
1497      cp.wasGetNamespaceDescriptorCalled());
1498    // This test used to do a bunch w/ bypass but bypass of these table and namespace stuff has
1499    // been removed so the testing code was removed.
1500  }
1501
1502  private void modifyTableSync(Admin admin, TableName tableName, TableDescriptor tableDescriptor)
1503    throws IOException {
1504    admin.modifyTable(tableDescriptor);
1505    // wait until modify table finishes
1506    for (int t = 0; t < 100; t++) { // 10 sec timeout
1507      TableDescriptor td = admin.getDescriptor(tableDescriptor.getTableName());
1508      if (td.equals(tableDescriptor)) {
1509        break;
1510      }
1511      Threads.sleep(100);
1512    }
1513  }
1514
1515  @Test
1516  public void testRegionTransitionOperations() throws Exception {
1517    final TableName tableName = TableName.valueOf(name.getMethodName());
1518    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1519
1520    HMaster master = cluster.getMaster();
1521    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1522    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1523    cp.resetStates();
1524
1525    Table table = UTIL.createMultiRegionTable(tableName, TEST_FAMILY);
1526
1527    try (RegionLocator r = UTIL.getConnection().getRegionLocator(tableName)) {
1528      UTIL.waitUntilAllRegionsAssigned(tableName);
1529
1530      List<HRegionLocation> regions = r.getAllRegionLocations();
1531      HRegionLocation firstGoodPair = null;
1532      for (HRegionLocation e : regions) {
1533        if (e.getServerName() != null) {
1534          firstGoodPair = e;
1535          break;
1536        }
1537      }
1538      assertNotNull("Found a non-null entry", firstGoodPair);
1539      LOG.info("Found " + firstGoodPair.toString());
1540      // Try to force a move
1541      Collection<ServerName> servers = master.getClusterMetrics().getLiveServerMetrics().keySet();
1542      String destName = null;
1543      String serverNameForFirstRegion = firstGoodPair.getServerName().toString();
1544      LOG.info("serverNameForFirstRegion=" + serverNameForFirstRegion);
1545      ServerName masterServerName = master.getServerName();
1546      boolean found = false;
1547      // Find server that is NOT carrying the first region
1548      for (ServerName info : servers) {
1549        LOG.info("ServerName=" + info);
1550        if (
1551          !serverNameForFirstRegion.equals(info.getServerName()) && !masterServerName.equals(info)
1552        ) {
1553          destName = info.toString();
1554          found = true;
1555          break;
1556        }
1557      }
1558      assertTrue("Found server", found);
1559      LOG.info("Found " + destName);
1560      master.getMasterRpcServices().moveRegion(null, RequestConverter.buildMoveRegionRequest(
1561        firstGoodPair.getRegion().getEncodedNameAsBytes(), ServerName.valueOf(destName)));
1562      assertTrue("Coprocessor should have been called on region move", cp.wasMoveCalled());
1563
1564      // make sure balancer is on
1565      master.balanceSwitch(true);
1566      assertTrue("Coprocessor should have been called on balance switch",
1567        cp.wasBalanceSwitchCalled());
1568
1569      // turn balancer off
1570      master.balanceSwitch(false);
1571
1572      // wait for assignments to finish, if any
1573      UTIL.waitUntilNoRegionsInTransition();
1574
1575      // move half the open regions from RS 0 to RS 1
1576      HRegionServer rs = cluster.getRegionServer(0);
1577      byte[] destRS = Bytes.toBytes(cluster.getRegionServer(1).getServerName().toString());
1578      // Make sure no regions are in transition now
1579      UTIL.waitUntilNoRegionsInTransition();
1580      List<RegionInfo> openRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices());
1581      int moveCnt = openRegions.size() / 2;
1582      for (int i = 0; i < moveCnt; i++) {
1583        RegionInfo info = openRegions.get(i);
1584        if (!info.isMetaRegion()) {
1585          master.getMasterRpcServices().moveRegion(null,
1586            RequestConverter.buildMoveRegionRequest(openRegions.get(i).getEncodedNameAsBytes(),
1587              ServerName.valueOf(Bytes.toString(destRS))));
1588        }
1589      }
1590      // Make sure no regions are in transition now
1591      UTIL.waitUntilNoRegionsInTransition();
1592      // now trigger a balance
1593      master.balanceSwitch(true);
1594      master.balance();
1595      assertTrue("Coprocessor should be called on region rebalancing", cp.wasBalanceCalled());
1596    } finally {
1597      Admin admin = UTIL.getAdmin();
1598      admin.disableTable(tableName);
1599      deleteTable(admin, tableName);
1600    }
1601  }
1602
1603  @Test
1604  public void testTableDescriptorsEnumeration() throws Exception {
1605    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1606
1607    HMaster master = cluster.getMaster();
1608    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1609    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1610    cp.resetStates();
1611
1612    GetTableDescriptorsRequest req =
1613      RequestConverter.buildGetTableDescriptorsRequest((List<TableName>) null);
1614    master.getMasterRpcServices().getTableDescriptors(null, req);
1615
1616    assertTrue("Coprocessor should be called on table descriptors request",
1617      cp.wasGetTableDescriptorsCalled());
1618  }
1619
1620  @Test
1621  public void testTableNamesEnumeration() throws Exception {
1622    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1623
1624    HMaster master = cluster.getMaster();
1625    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1626    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1627    cp.resetStates();
1628
1629    master.getMasterRpcServices().getTableNames(null, GetTableNamesRequest.newBuilder().build());
1630    assertTrue("Coprocessor should be called on table names request", cp.wasGetTableNamesCalled());
1631  }
1632
1633  @Test
1634  public void testAbortProcedureOperation() throws Exception {
1635    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1636
1637    HMaster master = cluster.getMaster();
1638    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1639    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1640    cp.resetStates();
1641
1642    master.abortProcedure(1, true);
1643    assertTrue("Coprocessor should be called on abort procedure request",
1644      cp.wasAbortProcedureCalled());
1645  }
1646
1647  @Test
1648  public void testGetProceduresOperation() throws Exception {
1649    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1650
1651    HMaster master = cluster.getMaster();
1652    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1653    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1654    cp.resetStates();
1655
1656    master.getProcedures();
1657    assertTrue("Coprocessor should be called on get procedures request",
1658      cp.wasGetProceduresCalled());
1659  }
1660
1661  @Test
1662  public void testGetLocksOperation() throws Exception {
1663    SingleProcessHBaseCluster 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.getLocks();
1671    assertTrue("Coprocessor should be called on get locks request", cp.wasGetLocksCalled());
1672  }
1673
1674  private void deleteTable(Admin admin, TableName tableName) throws Exception {
1675    // NOTE: We need a latch because admin is not sync,
1676    // so the postOp coprocessor method may be called after the admin operation returned.
1677    tableDeletionLatch = new CountDownLatch(1);
1678    admin.deleteTable(tableName);
1679    tableDeletionLatch.await();
1680    tableDeletionLatch = new CountDownLatch(1);
1681  }
1682
1683  @Test
1684  public void testQueueLockAndLockHeartbeatOperations() throws Exception {
1685    HMaster master = UTIL.getMiniHBaseCluster().getMaster();
1686    CPMasterObserver cp = master.getMasterCoprocessorHost().findCoprocessor(CPMasterObserver.class);
1687    cp.resetStates();
1688
1689    final TableName tableName = TableName.valueOf("testLockedTable");
1690    long procId = master.getLockManager().remoteLocks().requestTableLock(tableName,
1691      LockType.EXCLUSIVE, "desc", null);
1692    master.getLockManager().remoteLocks().lockHeartbeat(procId, false);
1693
1694    assertTrue(cp.preAndPostForQueueLockAndHeartbeatLockCalled());
1695
1696    ProcedureTestingUtility.waitNoProcedureRunning(master.getMasterProcedureExecutor());
1697    ProcedureTestingUtility.assertProcNotFailed(master.getMasterProcedureExecutor(), procId);
1698  }
1699
1700  @Test
1701  public void testMasterStoreOperations() throws Exception {
1702    SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
1703    HMaster master = cluster.getMaster();
1704    MasterCoprocessorHost host = master.getMasterCoprocessorHost();
1705    CPMasterObserver cp = host.findCoprocessor(CPMasterObserver.class);
1706    cp.resetStates();
1707    assertFalse("No master store flush call", cp.preMasterStoreFlushCalled);
1708    assertFalse("No master store flush call", cp.postMasterStoreFlushCalled);
1709
1710    try (Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
1711      Admin admin = connection.getAdmin()) {
1712      admin.flushMasterStore();
1713
1714      assertTrue("Master store flush called", cp.preMasterStoreFlushCalled);
1715      assertTrue("Master store flush called", cp.postMasterStoreFlushCalled);
1716    }
1717  }
1718}