View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import static org.junit.Assert.fail;
21  import static org.mockito.Mockito.mock;
22  import static org.mockito.Mockito.when;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HBaseConfiguration;
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.apache.hadoop.hbase.MasterNotRunningException;
34  import org.apache.hadoop.hbase.PleaseHoldException;
35  import org.apache.hadoop.hbase.TableName;
36  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
37  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceRequest;
38  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
39  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
40  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
41  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
42  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
43  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
44  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
45  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionRequest;
46  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
47  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
48  import org.junit.Test;
49  import org.junit.experimental.categories.Category;
50  import org.mockito.Mockito;
51  import org.mockito.invocation.InvocationOnMock;
52  import org.mockito.stubbing.Answer;
53  import org.mortbay.log.Log;
54  
55  import com.google.protobuf.RpcController;
56  import com.google.protobuf.ServiceException;
57  
58  @Category(SmallTests.class)
59  public class TestHBaseAdminNoCluster {
60    /**
61     * Verify that PleaseHoldException gets retried.
62     * HBASE-8764
63     * @throws IOException
64     * @throws ZooKeeperConnectionException
65     * @throws MasterNotRunningException
66     * @throws ServiceException
67     */
68    @Test
69    public void testMasterMonitorCallableRetries()
70    throws MasterNotRunningException, ZooKeeperConnectionException, IOException, ServiceException {
71      Configuration configuration = HBaseConfiguration.create();
72      // Set the pause and retry count way down.
73      configuration.setLong(HConstants.HBASE_CLIENT_PAUSE, 1);
74      final int count = 10;
75      configuration.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, count);
76      // Get mocked connection.   Getting the connection will register it so when HBaseAdmin is
77      // constructed with same configuration, it will find this mocked connection.
78      ClusterConnection connection = HConnectionTestingUtility.getMockedConnection(configuration);
79      // Mock so we get back the master interface.  Make it so when createTable is called, we throw
80      // the PleaseHoldException.
81      MasterKeepAliveConnection masterAdmin = Mockito.mock(MasterKeepAliveConnection.class);
82      Mockito.when(masterAdmin.createTable((RpcController)Mockito.any(),
83        (CreateTableRequest)Mockito.any())).
84          thenThrow(new ServiceException("Test fail").initCause(new PleaseHoldException("test")));
85      Mockito.when(connection.getKeepAliveMasterService()).thenReturn(masterAdmin);
86      Admin admin = new HBaseAdmin(connection);
87      try {
88        HTableDescriptor htd =
89          new HTableDescriptor(TableName.valueOf("testMasterMonitorCollableRetries"));
90        // Pass any old htable descriptor; not important
91        try {
92          admin.createTable(htd, HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE);
93          fail();
94        } catch (RetriesExhaustedException e) {
95          Log.info("Expected fail", e);
96        }
97        // Assert we were called 'count' times.
98        Mockito.verify(masterAdmin, Mockito.atLeast(count)).createTable((RpcController)Mockito.any(),
99          (CreateTableRequest)Mockito.any());
100     } finally {
101       admin.close();
102       if (connection != null) connection.close();
103     }
104   }
105 
106   @Test
107   public void testMasterOperationsRetries() throws Exception {
108 
109     // Admin.listTables()
110     testMasterOperationIsRetried(new MethodCaller() {
111       @Override
112       public void call(Admin admin) throws Exception {
113         admin.listTables();
114       }
115       @Override
116       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
117         Mockito.verify(masterAdmin, Mockito.atLeast(count))
118           .getTableDescriptors((RpcController)Mockito.any(),
119             (GetTableDescriptorsRequest)Mockito.any());
120       }
121     });
122 
123     // Admin.listTableNames()
124     testMasterOperationIsRetried(new MethodCaller() {
125       @Override
126       public void call(Admin admin) throws Exception {
127         admin.listTableNames();
128       }
129       @Override
130       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
131         Mockito.verify(masterAdmin, Mockito.atLeast(count))
132           .getTableNames((RpcController)Mockito.any(),
133             (GetTableNamesRequest)Mockito.any());
134       }
135     });
136 
137     // Admin.getTableDescriptor()
138     testMasterOperationIsRetried(new MethodCaller() {
139       @Override
140       public void call(Admin admin) throws Exception {
141         admin.getTableDescriptor(TableName.valueOf("getTableDescriptor"));
142       }
143       @Override
144       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
145         Mockito.verify(masterAdmin, Mockito.atLeast(count))
146           .getTableDescriptors((RpcController)Mockito.any(),
147             (GetTableDescriptorsRequest)Mockito.any());
148       }
149     });
150 
151     // Admin.getTableDescriptorsByTableName()
152     testMasterOperationIsRetried(new MethodCaller() {
153       @Override
154       public void call(Admin admin) throws Exception {
155         admin.getTableDescriptorsByTableName(new ArrayList<TableName>());
156       }
157       @Override
158       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
159         Mockito.verify(masterAdmin, Mockito.atLeast(count))
160           .getTableDescriptors((RpcController)Mockito.any(),
161             (GetTableDescriptorsRequest)Mockito.any());
162       }
163     });
164 
165     // Admin.move()
166     testMasterOperationIsRetried(new MethodCaller() {
167       @Override
168       public void call(Admin admin) throws Exception {
169         admin.move(new byte[0], null);
170       }
171       @Override
172       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
173         Mockito.verify(masterAdmin, Mockito.atLeast(count))
174           .moveRegion((RpcController)Mockito.any(),
175             (MoveRegionRequest)Mockito.any());
176       }
177     });
178 
179     // Admin.offline()
180     testMasterOperationIsRetried(new MethodCaller() {
181       @Override
182       public void call(Admin admin) throws Exception {
183         admin.offline(new byte[0]);
184       }
185       @Override
186       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
187         Mockito.verify(masterAdmin, Mockito.atLeast(count))
188           .offlineRegion((RpcController)Mockito.any(),
189             (OfflineRegionRequest)Mockito.any());
190       }
191     });
192 
193     // Admin.setBalancerRunning()
194     testMasterOperationIsRetried(new MethodCaller() {
195       @Override
196       public void call(Admin admin) throws Exception {
197         admin.setBalancerRunning(true, true);
198       }
199       @Override
200       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
201         Mockito.verify(masterAdmin, Mockito.atLeast(count))
202           .setBalancerRunning((RpcController)Mockito.any(),
203             (SetBalancerRunningRequest)Mockito.any());
204       }
205     });
206 
207     // Admin.balancer()
208     testMasterOperationIsRetried(new MethodCaller() {
209       @Override
210       public void call(Admin admin) throws Exception {
211         admin.balancer();
212       }
213       @Override
214       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
215         Mockito.verify(masterAdmin, Mockito.atLeast(count))
216           .balance((RpcController)Mockito.any(),
217             (BalanceRequest)Mockito.any());
218       }
219     });
220 
221     // Admin.enabledCatalogJanitor()
222     testMasterOperationIsRetried(new MethodCaller() {
223       @Override
224       public void call(Admin admin) throws Exception {
225         admin.enableCatalogJanitor(true);
226       }
227       @Override
228       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
229         Mockito.verify(masterAdmin, Mockito.atLeast(count))
230           .enableCatalogJanitor((RpcController)Mockito.any(),
231             (EnableCatalogJanitorRequest)Mockito.any());
232       }
233     });
234 
235     // Admin.runCatalogScan()
236     testMasterOperationIsRetried(new MethodCaller() {
237       @Override
238       public void call(Admin admin) throws Exception {
239         admin.runCatalogScan();
240       }
241       @Override
242       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
243         Mockito.verify(masterAdmin, Mockito.atLeast(count))
244           .runCatalogScan((RpcController)Mockito.any(),
245             (RunCatalogScanRequest)Mockito.any());
246       }
247     });
248 
249     // Admin.isCatalogJanitorEnabled()
250     testMasterOperationIsRetried(new MethodCaller() {
251       @Override
252       public void call(Admin admin) throws Exception {
253         admin.isCatalogJanitorEnabled();
254       }
255       @Override
256       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
257         Mockito.verify(masterAdmin, Mockito.atLeast(count))
258           .isCatalogJanitorEnabled((RpcController)Mockito.any(),
259             (IsCatalogJanitorEnabledRequest)Mockito.any());
260       }
261     });
262 
263     // Admin.mergeRegions()
264     testMasterOperationIsRetried(new MethodCaller() {
265       @Override
266       public void call(Admin admin) throws Exception {
267         admin.mergeRegions(new byte[0], new byte[0], true);
268       }
269       @Override
270       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
271         Mockito.verify(masterAdmin, Mockito.atLeast(count))
272           .dispatchMergingRegions((RpcController)Mockito.any(),
273             (DispatchMergingRegionsRequest)Mockito.any());
274       }
275     });
276   }
277 
278   private static interface MethodCaller {
279     void call(Admin admin) throws Exception;
280     void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception;
281   }
282 
283   private void testMasterOperationIsRetried(MethodCaller caller) throws Exception {
284     Configuration configuration = HBaseConfiguration.create();
285     // Set the pause and retry count way down.
286     configuration.setLong(HConstants.HBASE_CLIENT_PAUSE, 1);
287     final int count = 10;
288     configuration.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, count);
289 
290     ClusterConnection connection = mock(ClusterConnection.class);
291     when(connection.getConfiguration()).thenReturn(configuration);
292     MasterKeepAliveConnection masterAdmin =
293         Mockito.mock(MasterKeepAliveConnection.class, new Answer() {
294           @Override
295           public Object answer(InvocationOnMock invocation) throws Throwable {
296             if (invocation.getMethod().getName().equals("close")) {
297               return null;
298             }
299             throw new MasterNotRunningException(); // all methods will throw an exception
300           }
301         });
302     Mockito.when(connection.getKeepAliveMasterService()).thenReturn(masterAdmin);
303 
304     Admin admin = null;
305     try {
306       admin = new HBaseAdmin(connection);
307 
308       try {
309         caller.call(admin); // invoke the HBaseAdmin method
310         fail();
311       } catch (RetriesExhaustedException e) {
312         Log.info("Expected fail", e);
313       }
314       // Assert we were called 'count' times.
315       caller.verify(masterAdmin, count);
316     } finally {
317       if (admin != null) {admin.close();}
318     }
319   }
320 }