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