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.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.hadoop.conf.Configuration;
30  import org.apache.hadoop.hbase.HBaseConfiguration;
31  import org.apache.hadoop.hbase.HBaseTestingUtility;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.HTableDescriptor;
34  import org.apache.hadoop.hbase.testclassification.SmallTests;
35  import org.apache.hadoop.hbase.MasterNotRunningException;
36  import org.apache.hadoop.hbase.PleaseHoldException;
37  import org.apache.hadoop.hbase.TableName;
38  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
39  import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
40  import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
41  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceRequest;
42  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
43  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
44  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
45  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
46  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
47  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
48  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
49  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionRequest;
50  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
51  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
52  import org.junit.Ignore;
53  import org.junit.Test;
54  import org.junit.experimental.categories.Category;
55  import org.mockito.Matchers;
56  import org.mockito.Mockito;
57  import org.mockito.invocation.InvocationOnMock;
58  import org.mockito.stubbing.Answer;
59  
60  import com.google.protobuf.RpcController;
61  import com.google.protobuf.ServiceException;
62  
63  @Category(SmallTests.class)
64  public class TestHBaseAdminNoCluster {
65  
66    private static final Log LOG = LogFactory.getLog(TestHBaseAdminNoCluster.class);
67  
68    /**
69     * Verify that PleaseHoldException gets retried.
70     * HBASE-8764
71     * @throws IOException
72     * @throws ZooKeeperConnectionException
73     * @throws MasterNotRunningException
74     * @throws ServiceException
75     */
76    //TODO: Clean up, with Procedure V2 and nonce to prevent the same procedure to call mulitple
77    // time, this test is invalid anymore. Just keep the test around for some time before
78    // fully removing it.
79    @Ignore
80    @Test
81    public void testMasterMonitorCallableRetries()
82    throws MasterNotRunningException, ZooKeeperConnectionException, IOException, ServiceException {
83      Configuration configuration = HBaseConfiguration.create();
84      // Set the pause and retry count way down.
85      configuration.setLong(HConstants.HBASE_CLIENT_PAUSE, 1);
86      final int count = 10;
87      configuration.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, count);
88      // Get mocked connection.   Getting the connection will register it so when HBaseAdmin is
89      // constructed with same configuration, it will find this mocked connection.
90      ClusterConnection connection = HConnectionTestingUtility.getMockedConnection(configuration);
91      // Mock so we get back the master interface.  Make it so when createTable is called, we throw
92      // the PleaseHoldException.
93      MasterKeepAliveConnection masterAdmin = Mockito.mock(MasterKeepAliveConnection.class);
94      Mockito.when(masterAdmin.createTable((RpcController)Mockito.any(),
95        (CreateTableRequest)Mockito.any())).
96          thenThrow(new ServiceException("Test fail").initCause(new PleaseHoldException("test")));
97      Mockito.when(connection.getKeepAliveMasterService()).thenReturn(masterAdmin);
98      Admin admin = new HBaseAdmin(connection);
99      try {
100       HTableDescriptor htd =
101         new HTableDescriptor(TableName.valueOf("testMasterMonitorCollableRetries"));
102       // Pass any old htable descriptor; not important
103       try {
104         admin.createTable(htd, HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE);
105         fail();
106       } catch (RetriesExhaustedException e) {
107         LOG.info("Expected fail", e);
108       }
109       // Assert we were called 'count' times.
110       Mockito.verify(masterAdmin, Mockito.atLeast(count)).createTable((RpcController)Mockito.any(),
111         (CreateTableRequest)Mockito.any());
112     } finally {
113       admin.close();
114       if (connection != null) connection.close();
115     }
116   }
117 
118   @Test
119   public void testMasterOperationsRetries() throws Exception {
120 
121     // Admin.listTables()
122     testMasterOperationIsRetried(new MethodCaller() {
123       @Override
124       public void call(Admin admin) throws Exception {
125         admin.listTables();
126       }
127       @Override
128       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
129         Mockito.verify(masterAdmin, Mockito.atLeast(count))
130           .getTableDescriptors((RpcController)Mockito.any(),
131             (GetTableDescriptorsRequest)Mockito.any());
132       }
133     });
134 
135     // Admin.listTableNames()
136     testMasterOperationIsRetried(new MethodCaller() {
137       @Override
138       public void call(Admin admin) throws Exception {
139         admin.listTableNames();
140       }
141       @Override
142       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
143         Mockito.verify(masterAdmin, Mockito.atLeast(count))
144           .getTableNames((RpcController)Mockito.any(),
145             (GetTableNamesRequest)Mockito.any());
146       }
147     });
148 
149     // Admin.getTableDescriptor()
150     testMasterOperationIsRetried(new MethodCaller() {
151       @Override
152       public void call(Admin admin) throws Exception {
153         admin.getTableDescriptor(TableName.valueOf("getTableDescriptor"));
154       }
155       @Override
156       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
157         Mockito.verify(masterAdmin, Mockito.atLeast(count))
158           .getTableDescriptors((RpcController)Mockito.any(),
159             (GetTableDescriptorsRequest)Mockito.any());
160       }
161     });
162 
163     // Admin.getTableDescriptorsByTableName()
164     testMasterOperationIsRetried(new MethodCaller() {
165       @Override
166       public void call(Admin admin) throws Exception {
167         admin.getTableDescriptorsByTableName(new ArrayList<TableName>());
168       }
169       @Override
170       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
171         Mockito.verify(masterAdmin, Mockito.atLeast(count))
172           .getTableDescriptors((RpcController)Mockito.any(),
173             (GetTableDescriptorsRequest)Mockito.any());
174       }
175     });
176 
177     // Admin.move()
178     testMasterOperationIsRetried(new MethodCaller() {
179       @Override
180       public void call(Admin admin) throws Exception {
181         admin.move(new byte[0], null);
182       }
183       @Override
184       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
185         Mockito.verify(masterAdmin, Mockito.atLeast(count))
186           .moveRegion((RpcController)Mockito.any(),
187             (MoveRegionRequest)Mockito.any());
188       }
189     });
190 
191     // Admin.offline()
192     testMasterOperationIsRetried(new MethodCaller() {
193       @Override
194       public void call(Admin admin) throws Exception {
195         admin.offline(new byte[0]);
196       }
197       @Override
198       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
199         Mockito.verify(masterAdmin, Mockito.atLeast(count))
200           .offlineRegion((RpcController)Mockito.any(),
201             (OfflineRegionRequest)Mockito.any());
202       }
203     });
204 
205     // Admin.setBalancerRunning()
206     testMasterOperationIsRetried(new MethodCaller() {
207       @Override
208       public void call(Admin admin) throws Exception {
209         admin.setBalancerRunning(true, true);
210       }
211       @Override
212       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
213         Mockito.verify(masterAdmin, Mockito.atLeast(count))
214           .setBalancerRunning((RpcController)Mockito.any(),
215             (SetBalancerRunningRequest)Mockito.any());
216       }
217     });
218 
219     // Admin.balancer()
220     testMasterOperationIsRetried(new MethodCaller() {
221       @Override
222       public void call(Admin admin) throws Exception {
223         admin.balancer();
224       }
225       @Override
226       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
227         Mockito.verify(masterAdmin, Mockito.atLeast(count))
228           .balance((RpcController)Mockito.any(),
229             (BalanceRequest)Mockito.any());
230       }
231     });
232 
233     // Admin.enabledCatalogJanitor()
234     testMasterOperationIsRetried(new MethodCaller() {
235       @Override
236       public void call(Admin admin) throws Exception {
237         admin.enableCatalogJanitor(true);
238       }
239       @Override
240       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
241         Mockito.verify(masterAdmin, Mockito.atLeast(count))
242           .enableCatalogJanitor((RpcController)Mockito.any(),
243             (EnableCatalogJanitorRequest)Mockito.any());
244       }
245     });
246 
247     // Admin.runCatalogScan()
248     testMasterOperationIsRetried(new MethodCaller() {
249       @Override
250       public void call(Admin admin) throws Exception {
251         admin.runCatalogScan();
252       }
253       @Override
254       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
255         Mockito.verify(masterAdmin, Mockito.atLeast(count))
256           .runCatalogScan((RpcController)Mockito.any(),
257             (RunCatalogScanRequest)Mockito.any());
258       }
259     });
260 
261     // Admin.isCatalogJanitorEnabled()
262     testMasterOperationIsRetried(new MethodCaller() {
263       @Override
264       public void call(Admin admin) throws Exception {
265         admin.isCatalogJanitorEnabled();
266       }
267       @Override
268       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
269         Mockito.verify(masterAdmin, Mockito.atLeast(count))
270           .isCatalogJanitorEnabled((RpcController)Mockito.any(),
271             (IsCatalogJanitorEnabledRequest)Mockito.any());
272       }
273     });
274     // Admin.mergeRegions()
275     testMasterOperationIsRetried(new MethodCaller() {
276       @Override
277       public void call(Admin admin) throws Exception {
278         admin.mergeRegions(new byte[0], new byte[0], true);
279       }
280       @Override
281       public void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception {
282         Mockito.verify(masterAdmin, Mockito.atLeast(count))
283           .dispatchMergingRegions((RpcController)Mockito.any(),
284             (DispatchMergingRegionsRequest)Mockito.any());
285       }
286     });
287   }
288 
289   private static interface MethodCaller {
290     void call(Admin admin) throws Exception;
291     void verify(MasterKeepAliveConnection masterAdmin, int count) throws Exception;
292   }
293 
294   private void testMasterOperationIsRetried(MethodCaller caller) throws Exception {
295     Configuration configuration = HBaseConfiguration.create();
296     // Set the pause and retry count way down.
297     configuration.setLong(HConstants.HBASE_CLIENT_PAUSE, 1);
298     final int count = 10;
299     configuration.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, count);
300 
301     ClusterConnection connection = mock(ClusterConnection.class);
302     when(connection.getConfiguration()).thenReturn(configuration);
303     MasterKeepAliveConnection masterAdmin =
304         Mockito.mock(MasterKeepAliveConnection.class, new Answer() {
305           @Override
306           public Object answer(InvocationOnMock invocation) throws Throwable {
307             if (invocation.getMethod().getName().equals("close")) {
308               return null;
309             }
310             throw new MasterNotRunningException(); // all methods will throw an exception
311           }
312         });
313     Mockito.when(connection.getKeepAliveMasterService()).thenReturn(masterAdmin);
314     RpcControllerFactory rpcControllerFactory = Mockito.mock(RpcControllerFactory.class);
315     Mockito.when(connection.getRpcControllerFactory()).thenReturn(rpcControllerFactory);
316     Mockito.when(rpcControllerFactory.newController()).thenReturn(
317       Mockito.mock(PayloadCarryingRpcController.class));
318 
319     // we need a real retrying caller
320     RpcRetryingCallerFactory callerFactory = new RpcRetryingCallerFactory(configuration);
321     Mockito.when(connection.getRpcRetryingCallerFactory()).thenReturn(callerFactory);
322 
323     Admin admin = null;
324     try {
325       admin = Mockito.spy(new HBaseAdmin(connection));
326       // mock the call to getRegion since in the absence of a cluster (which means the meta
327       // is not assigned), getRegion can't function
328       Mockito.doReturn(null).when(((HBaseAdmin)admin)).getRegion(Matchers.<byte[]>any());
329       try {
330         caller.call(admin); // invoke the HBaseAdmin method
331         fail();
332       } catch (RetriesExhaustedException e) {
333         LOG.info("Expected fail", e);
334       }
335       // Assert we were called 'count' times.
336       caller.verify(masterAdmin, count);
337     } finally {
338       if (admin != null) {admin.close();}
339     }
340   }
341 }