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