1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertTrue;
24
25 import com.google.protobuf.BlockingRpcChannel;
26 import com.google.protobuf.Descriptors.MethodDescriptor;
27 import com.google.protobuf.Message;
28 import com.google.protobuf.RpcController;
29 import com.google.protobuf.ServiceException;
30
31 import java.net.InetSocketAddress;
32 import java.net.SocketAddress;
33 import java.net.SocketTimeoutException;
34 import java.net.UnknownHostException;
35 import java.util.Random;
36 import java.util.concurrent.atomic.AtomicInteger;
37
38 import org.apache.hadoop.conf.Configuration;
39 import org.apache.hadoop.hbase.HBaseConfiguration;
40 import org.apache.hadoop.hbase.HBaseTestingUtility;
41 import org.apache.hadoop.hbase.HConstants;
42 import org.apache.hadoop.hbase.MasterNotRunningException;
43 import org.apache.hadoop.hbase.ServerName;
44 import org.apache.hadoop.hbase.ipc.AbstractRpcClient;
45 import org.apache.hadoop.hbase.ipc.BlockingRpcClient;
46 import org.apache.hadoop.hbase.ipc.RpcClientFactory;
47 import org.apache.hadoop.hbase.security.User;
48 import org.apache.hadoop.hbase.testclassification.ClientTests;
49 import org.apache.hadoop.hbase.testclassification.MediumTests;
50 import org.junit.AfterClass;
51 import org.junit.BeforeClass;
52 import org.junit.Test;
53 import org.junit.experimental.categories.Category;
54
55 @Category({MediumTests.class, ClientTests.class})
56 public class TestClientTimeouts {
57 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58 protected static int SLAVES = 1;
59
60
61
62
63 @BeforeClass
64 public static void setUpBeforeClass() throws Exception {
65 TEST_UTIL.startMiniCluster(SLAVES);
66
67 TEST_UTIL.getConfiguration().set(
68 RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY,
69 RandomTimeoutRpcClient.class.getName());
70 }
71
72
73
74
75 @AfterClass
76 public static void tearDownAfterClass() throws Exception {
77 TEST_UTIL.shutdownMiniCluster();
78 }
79
80
81
82
83
84
85 @Test
86 public void testAdminTimeout() throws Exception {
87 boolean lastFailed = false;
88 int initialInvocations = RandomTimeoutBlockingRpcChannel.invokations.get();
89 RandomTimeoutRpcClient rpcClient = (RandomTimeoutRpcClient) RpcClientFactory
90 .createClient(TEST_UTIL.getConfiguration(), TEST_UTIL.getClusterKey());
91
92 try {
93 for (int i = 0; i < 5 || (lastFailed && i < 100); ++i) {
94 lastFailed = false;
95
96 Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
97 conf.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1));
98 Admin admin = null;
99 Connection connection = null;
100 try {
101 connection = ConnectionFactory.createConnection(conf);
102 admin = connection.getAdmin();
103
104 HBaseAdmin.checkHBaseAvailable(conf);
105 admin.setBalancerRunning(false, false);
106 } catch (MasterNotRunningException ex) {
107
108
109 lastFailed = true;
110 } finally {
111 if(admin != null) {
112 admin.close();
113 if (admin.getConnection().isClosed()) {
114 rpcClient = (RandomTimeoutRpcClient) RpcClientFactory
115 .createClient(TEST_UTIL.getConfiguration(), TEST_UTIL.getClusterKey());
116 }
117 }
118 if(connection != null) {
119 connection.close();
120 }
121 }
122 }
123
124 assertFalse(lastFailed);
125 assertTrue(RandomTimeoutBlockingRpcChannel.invokations.get() > initialInvocations);
126 } finally {
127 rpcClient.close();
128 }
129 }
130
131
132
133
134 public static class RandomTimeoutRpcClient extends BlockingRpcClient {
135 public RandomTimeoutRpcClient(Configuration conf, String clusterId, SocketAddress localAddr,
136 MetricsConnection metrics) {
137 super(conf, clusterId, localAddr, metrics);
138 }
139
140
141 @Override
142 public BlockingRpcChannel createBlockingRpcChannel(ServerName sn,
143 User ticket, int rpcTimeout) throws UnknownHostException {
144 return new RandomTimeoutBlockingRpcChannel(this, sn, ticket, rpcTimeout);
145 }
146 }
147
148
149
150
151 static class RandomTimeoutBlockingRpcChannel
152 extends AbstractRpcClient.BlockingRpcChannelImplementation {
153 private static final Random RANDOM = new Random(System.currentTimeMillis());
154 public static final double CHANCE_OF_TIMEOUT = 0.3;
155 private static AtomicInteger invokations = new AtomicInteger();
156
157 RandomTimeoutBlockingRpcChannel(final BlockingRpcClient rpcClient, final ServerName sn,
158 final User ticket, final int rpcTimeout) {
159 super(rpcClient, new InetSocketAddress(sn.getHostname(), sn.getPort()), ticket, rpcTimeout);
160 }
161
162 @Override
163 public Message callBlockingMethod(MethodDescriptor md,
164 RpcController controller, Message param, Message returnType)
165 throws ServiceException {
166 invokations.getAndIncrement();
167 if (RANDOM.nextFloat() < CHANCE_OF_TIMEOUT) {
168
169
170
171 throw new ServiceException(new SocketTimeoutException("fake timeout"));
172 }
173 return super.callBlockingMethod(md, controller, param, returnType);
174 }
175 }
176 }