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