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    User user = UserProvider.instantiate(CONF).getCurrent();
146    conn = new AsyncConnectionImpl(CONF, new DoNothingConnectionRegistry(CONF, user), "test", null,
147      user) {
148
149      @Override
150      CompletableFuture<MasterService.Interface> getMasterStub() {
151        return CompletableFuture.completedFuture(masterStub);
152      }
153
154      @Override
155      Interface getAdminStub(ServerName serverName) throws IOException {
156        return adminStub;
157      }
158    };
159  }
160
161  private HBaseRpcController assertPriority(int priority) {
162    return argThat(new ArgumentMatcher<HBaseRpcController>() {
163
164      @Override
165      public boolean matches(HBaseRpcController controller) {
166        return controller.getPriority() == priority;
167      }
168    });
169  }
170
171  @Test
172  public void testCreateNormalTable() {
173    conn.getAdmin()
174      .createTable(TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName()))
175        .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build())
176      .join();
177    verify(masterStub, times(1)).createTable(assertPriority(NORMAL_QOS),
178      any(CreateTableRequest.class), any());
179  }
180
181  // a bit strange as we can not do this in production but anyway, just a client mock to confirm
182  // that we pass the correct priority
183  @Test
184  public void testCreateSystemTable() {
185    conn.getAdmin()
186      .createTable(TableDescriptorBuilder
187        .newBuilder(TableName.valueOf(SYSTEM_NAMESPACE_NAME_STR, name.getMethodName()))
188        .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build())
189      .join();
190    verify(masterStub, times(1)).createTable(assertPriority(SYSTEMTABLE_QOS),
191      any(CreateTableRequest.class), any());
192  }
193
194  // a bit strange as we can not do this in production but anyway, just a client mock to confirm
195  // that we pass the correct priority
196  @Test
197  public void testCreateMetaTable() {
198    conn.getAdmin().createTable(TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME)
199      .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build()).join();
200    verify(masterStub, times(1)).createTable(assertPriority(SYSTEMTABLE_QOS),
201      any(CreateTableRequest.class), any());
202  }
203
204  @Test
205  public void testShutdown() {
206    conn.getAdmin().shutdown().join();
207    verify(masterStub, times(1)).shutdown(assertPriority(HIGH_QOS), any(ShutdownRequest.class),
208      any());
209  }
210
211  @Test
212  public void testStopMaster() {
213    conn.getAdmin().stopMaster().join();
214    verify(masterStub, times(1)).stopMaster(assertPriority(HIGH_QOS), any(StopMasterRequest.class),
215      any());
216  }
217
218  @Test
219  public void testStopRegionServer() {
220    conn.getAdmin().stopRegionServer(ServerName.valueOf("rs", 16010, 12345)).join();
221    verify(adminStub, times(1)).stopServer(assertPriority(HIGH_QOS), any(StopServerRequest.class),
222      any());
223  }
224}