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 java.net.SocketTimeoutException;
26 import java.util.Random;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.HBaseConfiguration;
33 import org.apache.hadoop.hbase.HBaseTestingUtility;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.MasterNotRunningException;
36 import org.apache.hadoop.hbase.testclassification.MediumTests;
37 import org.apache.hadoop.hbase.ServerName;
38 import org.apache.hadoop.hbase.ipc.RpcClient;
39 import org.apache.hadoop.hbase.security.User;
40 import org.junit.AfterClass;
41 import org.junit.BeforeClass;
42 import org.junit.Test;
43 import org.junit.experimental.categories.Category;
44
45 import com.google.protobuf.BlockingRpcChannel;
46 import com.google.protobuf.Descriptors.MethodDescriptor;
47 import com.google.protobuf.Message;
48 import com.google.protobuf.RpcController;
49 import com.google.protobuf.ServiceException;
50
51 @Category(MediumTests.class)
52 public class TestClientTimeouts {
53 final Log LOG = LogFactory.getLog(getClass());
54 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
55 protected static int SLAVES = 1;
56
57
58
59
60 @BeforeClass
61 public static void setUpBeforeClass() throws Exception {
62 TEST_UTIL.startMiniCluster(SLAVES);
63 }
64
65
66
67
68 @AfterClass
69 public static void tearDownAfterClass() throws Exception {
70 TEST_UTIL.shutdownMiniCluster();
71 }
72
73
74
75
76
77
78 @Test
79 public void testAdminTimeout() throws Exception {
80 long lastLimit = HConstants.DEFAULT_HBASE_CLIENT_PREFETCH_LIMIT;
81 HConnection lastConnection = null;
82 boolean lastFailed = false;
83 int initialInvocations = RandomTimeoutBlockingRpcChannel.invokations.get();
84 RpcClient rpcClient = newRandomTimeoutRpcClient();
85 try {
86 for (int i = 0; i < 5 || (lastFailed && i < 100); ++i) {
87 lastFailed = false;
88
89 Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
90 conf.setLong(HConstants.HBASE_CLIENT_PREFETCH_LIMIT, ++lastLimit);
91 HBaseAdmin admin = null;
92 try {
93 admin = new HBaseAdmin(conf);
94 HConnection connection = admin.getConnection();
95 assertFalse(connection == lastConnection);
96 lastConnection = connection;
97
98 RpcClient oldRpcClient =
99 ((HConnectionManager.HConnectionImplementation)connection).setRpcClient(
100 rpcClient);
101 if (oldRpcClient != null) {
102 oldRpcClient.stop();
103 }
104
105 HBaseAdmin.checkHBaseAvailable(conf);
106 admin.setBalancerRunning(false, false);
107 } catch (MasterNotRunningException ex) {
108
109
110 lastFailed = true;
111 } finally {
112 admin.close();
113 if (admin.getConnection().isClosed()) {
114 rpcClient = newRandomTimeoutRpcClient();
115 }
116 }
117 }
118
119 assertFalse(lastFailed);
120 assertTrue(RandomTimeoutBlockingRpcChannel.invokations.get() > initialInvocations);
121 } finally {
122 rpcClient.stop();
123 }
124 }
125
126 private static RpcClient newRandomTimeoutRpcClient() {
127 return new RpcClient(
128 TEST_UTIL.getConfiguration(), TEST_UTIL.getClusterKey()) {
129
130 @Override
131 public BlockingRpcChannel createBlockingRpcChannel(ServerName sn,
132 User ticket, int rpcTimeout) {
133 return new RandomTimeoutBlockingRpcChannel(this, sn, ticket, rpcTimeout);
134 }
135 };
136 }
137
138
139
140
141 static class RandomTimeoutBlockingRpcChannel extends RpcClient.BlockingRpcChannelImplementation {
142 private static final Random RANDOM = new Random(System.currentTimeMillis());
143 public static final double CHANCE_OF_TIMEOUT = 0.3;
144 private static AtomicInteger invokations = new AtomicInteger();
145
146 RandomTimeoutBlockingRpcChannel(final RpcClient rpcClient, final ServerName sn,
147 final User ticket, final int rpcTimeout) {
148 super(rpcClient, sn, ticket, rpcTimeout);
149 }
150
151 @Override
152 public Message callBlockingMethod(MethodDescriptor md,
153 RpcController controller, Message param, Message returnType)
154 throws ServiceException {
155 invokations.getAndIncrement();
156 if (RANDOM.nextFloat() < CHANCE_OF_TIMEOUT) {
157
158
159
160 throw new ServiceException(new SocketTimeoutException("fake timeout"));
161 }
162 return super.callBlockingMethod(md, controller, param, returnType);
163 }
164 }
165 }