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.client;
019
020import static org.apache.hadoop.hbase.HConstants.HIGH_QOS;
021import static org.apache.hadoop.hbase.HConstants.NORMAL_QOS;
022import static org.apache.hadoop.hbase.HConstants.SYSTEMTABLE_QOS;
023import static org.apache.hadoop.hbase.NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR;
024import static org.mockito.ArgumentMatchers.any;
025import static org.mockito.ArgumentMatchers.argThat;
026import static org.mockito.Mockito.doAnswer;
027import static org.mockito.Mockito.mock;
028import static org.mockito.Mockito.times;
029import static org.mockito.Mockito.verify;
030
031import java.io.IOException;
032import java.util.concurrent.CompletableFuture;
033import org.apache.hadoop.conf.Configuration;
034import org.apache.hadoop.hbase.HBaseClassTestRule;
035import org.apache.hadoop.hbase.HBaseConfiguration;
036import org.apache.hadoop.hbase.ServerName;
037import org.apache.hadoop.hbase.TableName;
038import org.apache.hadoop.hbase.ipc.HBaseRpcController;
039import org.apache.hadoop.hbase.security.User;
040import org.apache.hadoop.hbase.security.UserProvider;
041import org.apache.hadoop.hbase.testclassification.ClientTests;
042import org.apache.hadoop.hbase.testclassification.SmallTests;
043import org.junit.Before;
044import org.junit.ClassRule;
045import org.junit.Rule;
046import org.junit.Test;
047import org.junit.experimental.categories.Category;
048import org.junit.rules.TestName;
049import org.mockito.ArgumentMatcher;
050import org.mockito.invocation.InvocationOnMock;
051import org.mockito.stubbing.Answer;
052
053import org.apache.hbase.thirdparty.com.google.protobuf.RpcCallback;
054
055import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService;
056import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService.Interface;
057import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerRequest;
058import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerResponse;
059import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest;
060import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableResponse;
061import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultRequest;
062import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse;
063import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MasterService;
064import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownRequest;
065import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownResponse;
066import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterRequest;
067import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterResponse;
068
069/**
070 * Confirm that we will set the priority in {@link HBaseRpcController} for several admin operations.
071 */
072@Category({ ClientTests.class, SmallTests.class })
073public class TestAsyncAdminRpcPriority {
074
075  @ClassRule
076  public static final HBaseClassTestRule CLASS_RULE =
077    HBaseClassTestRule.forClass(TestAsyncAdminRpcPriority.class);
078
079  private static Configuration CONF = HBaseConfiguration.create();
080
081  private MasterService.Interface masterStub;
082
083  private AdminService.Interface adminStub;
084
085  private AsyncConnection conn;
086
087  @Rule
088  public TestName name = new TestName();
089
090  @Before
091  public void setUp() throws IOException {
092    masterStub = mock(MasterService.Interface.class);
093    adminStub = mock(AdminService.Interface.class);
094    doAnswer(new Answer<Void>() {
095
096      @Override
097      public Void answer(InvocationOnMock invocation) throws Throwable {
098        RpcCallback<GetProcedureResultResponse> done = invocation.getArgument(2);
099        done.run(GetProcedureResultResponse.newBuilder()
100          .setState(GetProcedureResultResponse.State.FINISHED).build());
101        return null;
102      }
103    }).when(masterStub).getProcedureResult(any(HBaseRpcController.class),
104      any(GetProcedureResultRequest.class), any());
105    doAnswer(new Answer<Void>() {
106
107      @Override
108      public Void answer(InvocationOnMock invocation) throws Throwable {
109        RpcCallback<CreateTableResponse> done = invocation.getArgument(2);
110        done.run(CreateTableResponse.newBuilder().setProcId(1L).build());
111        return null;
112      }
113    }).when(masterStub).createTable(any(HBaseRpcController.class), any(CreateTableRequest.class),
114      any());
115    doAnswer(new Answer<Void>() {
116
117      @Override
118      public Void answer(InvocationOnMock invocation) throws Throwable {
119        RpcCallback<ShutdownResponse> done = invocation.getArgument(2);
120        done.run(ShutdownResponse.getDefaultInstance());
121        return null;
122      }
123    }).when(masterStub).shutdown(any(HBaseRpcController.class), any(ShutdownRequest.class), any());
124    doAnswer(new Answer<Void>() {
125
126      @Override
127      public Void answer(InvocationOnMock invocation) throws Throwable {
128        RpcCallback<StopMasterResponse> done = invocation.getArgument(2);
129        done.run(StopMasterResponse.getDefaultInstance());
130        return null;
131      }
132    }).when(masterStub).stopMaster(any(HBaseRpcController.class), any(StopMasterRequest.class),
133      any());
134
135    doAnswer(new Answer<Void>() {
136
137      @Override
138      public Void answer(InvocationOnMock invocation) throws Throwable {
139        RpcCallback<StopServerResponse> done = invocation.getArgument(2);
140        done.run(StopServerResponse.getDefaultInstance());
141        return null;
142      }
143    }).when(adminStub).stopServer(any(HBaseRpcController.class), any(StopServerRequest.class),
144      any());
145
146    User user = UserProvider.instantiate(CONF).getCurrent();
147    conn =
148      new AsyncConnectionImpl(CONF, new DoNothingConnectionRegistry(CONF, user), "test", user) {
149
150        @Override
151        CompletableFuture<MasterService.Interface> getMasterStub() {
152          return CompletableFuture.completedFuture(masterStub);
153        }
154
155        @Override
156        Interface getAdminStub(ServerName serverName) throws IOException {
157          return adminStub;
158        }
159      };
160  }
161
162  private HBaseRpcController assertPriority(int priority) {
163    return argThat(new ArgumentMatcher<HBaseRpcController>() {
164
165      @Override
166      public boolean matches(HBaseRpcController controller) {
167        return controller.getPriority() == priority;
168      }
169    });
170  }
171
172  @Test
173  public void testCreateNormalTable() {
174    conn.getAdmin()
175      .createTable(TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName()))
176        .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build())
177      .join();
178    verify(masterStub, times(1)).createTable(assertPriority(NORMAL_QOS),
179      any(CreateTableRequest.class), any());
180  }
181
182  // a bit strange as we can not do this in production but anyway, just a client mock to confirm
183  // that we pass the correct priority
184  @Test
185  public void testCreateSystemTable() {
186    conn.getAdmin()
187      .createTable(TableDescriptorBuilder
188        .newBuilder(TableName.valueOf(SYSTEM_NAMESPACE_NAME_STR, name.getMethodName()))
189        .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build())
190      .join();
191    verify(masterStub, times(1)).createTable(assertPriority(SYSTEMTABLE_QOS),
192      any(CreateTableRequest.class), any());
193  }
194
195  // a bit strange as we can not do this in production but anyway, just a client mock to confirm
196  // that we pass the correct priority
197  @Test
198  public void testCreateMetaTable() {
199    conn.getAdmin().createTable(TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME)
200      .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build()).join();
201    verify(masterStub, times(1)).createTable(assertPriority(SYSTEMTABLE_QOS),
202      any(CreateTableRequest.class), any());
203  }
204
205  @Test
206  public void testShutdown() {
207    conn.getAdmin().shutdown().join();
208    verify(masterStub, times(1)).shutdown(assertPriority(HIGH_QOS), any(ShutdownRequest.class),
209      any());
210  }
211
212  @Test
213  public void testStopMaster() {
214    conn.getAdmin().stopMaster().join();
215    verify(masterStub, times(1)).stopMaster(assertPriority(HIGH_QOS), any(StopMasterRequest.class),
216      any());
217  }
218
219  @Test
220  public void testStopRegionServer() {
221    conn.getAdmin().stopRegionServer(ServerName.valueOf("rs", 16010, 12345)).join();
222    verify(adminStub, times(1)).stopServer(assertPriority(HIGH_QOS), any(StopServerRequest.class),
223      any());
224  }
225}