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