1
2
3
4
5
6
7
8
9
10
11
12 package org.apache.hadoop.hbase.quotas;
13
14 import static org.junit.Assert.assertEquals;
15 import static org.junit.Assert.assertFalse;
16 import static org.junit.Assert.assertTrue;
17 import static org.junit.Assert.fail;
18
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.hadoop.hbase.HBaseIOException;
22 import org.apache.hadoop.hbase.TableName;
23 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
24 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
25 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Throttle;
26 import org.apache.hadoop.hbase.testclassification.SmallTests;
27 import org.junit.Test;
28 import org.junit.experimental.categories.Category;
29
30 @Category({ SmallTests.class })
31 public class TestQuotaState {
32 private static final TableName UNKNOWN_TABLE_NAME = TableName.valueOf("unknownTable");
33
34 @Test(timeout = 60000)
35 public void testQuotaStateBypass() {
36 QuotaState quotaInfo = new QuotaState();
37 assertTrue(quotaInfo.isBypass());
38 assertNoopLimiter(quotaInfo.getGlobalLimiter());
39
40 UserQuotaState userQuotaState = new UserQuotaState();
41 assertTrue(userQuotaState.isBypass());
42 assertNoopLimiter(userQuotaState.getTableLimiter(UNKNOWN_TABLE_NAME));
43 }
44
45 @Test(timeout = 60000)
46 public void testSimpleQuotaStateOperation() {
47 final TableName table = TableName.valueOf("testSimpleQuotaStateOperationTable");
48 final int NUM_GLOBAL_THROTTLE = 3;
49 final int NUM_TABLE_THROTTLE = 2;
50
51 UserQuotaState quotaInfo = new UserQuotaState();
52 assertTrue(quotaInfo.isBypass());
53
54
55 quotaInfo.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE));
56 assertFalse(quotaInfo.isBypass());
57
58
59 quotaInfo.setQuotas(table, buildReqNumThrottle(NUM_TABLE_THROTTLE));
60 assertFalse(quotaInfo.isBypass());
61 assertTrue(quotaInfo.getGlobalLimiter() == quotaInfo.getTableLimiter(UNKNOWN_TABLE_NAME));
62 assertThrottleException(quotaInfo.getTableLimiter(UNKNOWN_TABLE_NAME), NUM_GLOBAL_THROTTLE);
63 assertThrottleException(quotaInfo.getTableLimiter(table), NUM_TABLE_THROTTLE);
64 }
65
66 @Test(timeout = 60000)
67 public void testQuotaStateUpdateBypassThrottle() {
68 final long LAST_UPDATE = 10;
69
70 UserQuotaState quotaInfo = new UserQuotaState();
71 assertEquals(0, quotaInfo.getLastUpdate());
72 assertTrue(quotaInfo.isBypass());
73
74 UserQuotaState otherQuotaState = new UserQuotaState(LAST_UPDATE);
75 assertEquals(LAST_UPDATE, otherQuotaState.getLastUpdate());
76 assertTrue(otherQuotaState.isBypass());
77
78 quotaInfo.update(otherQuotaState);
79 assertEquals(LAST_UPDATE, quotaInfo.getLastUpdate());
80 assertTrue(quotaInfo.isBypass());
81 assertTrue(quotaInfo.getGlobalLimiter() == quotaInfo.getTableLimiter(UNKNOWN_TABLE_NAME));
82 assertNoopLimiter(quotaInfo.getTableLimiter(UNKNOWN_TABLE_NAME));
83 }
84
85 @Test(timeout = 60000)
86 public void testQuotaStateUpdateGlobalThrottle() {
87 final int NUM_GLOBAL_THROTTLE_1 = 3;
88 final int NUM_GLOBAL_THROTTLE_2 = 11;
89 final long LAST_UPDATE_1 = 10;
90 final long LAST_UPDATE_2 = 20;
91 final long LAST_UPDATE_3 = 30;
92
93 QuotaState quotaInfo = new QuotaState();
94 assertEquals(0, quotaInfo.getLastUpdate());
95 assertTrue(quotaInfo.isBypass());
96
97
98 QuotaState otherQuotaState = new QuotaState(LAST_UPDATE_1);
99 otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_1));
100 assertEquals(LAST_UPDATE_1, otherQuotaState.getLastUpdate());
101 assertFalse(otherQuotaState.isBypass());
102
103 quotaInfo.update(otherQuotaState);
104 assertEquals(LAST_UPDATE_1, quotaInfo.getLastUpdate());
105 assertFalse(quotaInfo.isBypass());
106 assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_1);
107
108
109 otherQuotaState = new QuotaState(LAST_UPDATE_2);
110 otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_2));
111 assertEquals(LAST_UPDATE_2, otherQuotaState.getLastUpdate());
112 assertFalse(otherQuotaState.isBypass());
113
114 quotaInfo.update(otherQuotaState);
115 assertEquals(LAST_UPDATE_2, quotaInfo.getLastUpdate());
116 assertFalse(quotaInfo.isBypass());
117 assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_2
118 - NUM_GLOBAL_THROTTLE_1);
119
120
121 otherQuotaState = new QuotaState(LAST_UPDATE_3);
122 assertEquals(LAST_UPDATE_3, otherQuotaState.getLastUpdate());
123 assertTrue(otherQuotaState.isBypass());
124
125 quotaInfo.update(otherQuotaState);
126 assertEquals(LAST_UPDATE_3, quotaInfo.getLastUpdate());
127 assertTrue(quotaInfo.isBypass());
128 assertNoopLimiter(quotaInfo.getGlobalLimiter());
129 }
130
131 @Test(timeout = 60000)
132 public void testQuotaStateUpdateTableThrottle() {
133 final TableName TABLE_A = TableName.valueOf("TableA");
134 final TableName TABLE_B = TableName.valueOf("TableB");
135 final TableName TABLE_C = TableName.valueOf("TableC");
136 final int TABLE_A_THROTTLE_1 = 3;
137 final int TABLE_A_THROTTLE_2 = 11;
138 final int TABLE_B_THROTTLE = 4;
139 final int TABLE_C_THROTTLE = 5;
140 final long LAST_UPDATE_1 = 10;
141 final long LAST_UPDATE_2 = 20;
142 final long LAST_UPDATE_3 = 30;
143
144 UserQuotaState quotaInfo = new UserQuotaState();
145 assertEquals(0, quotaInfo.getLastUpdate());
146 assertTrue(quotaInfo.isBypass());
147
148
149 UserQuotaState otherQuotaState = new UserQuotaState(LAST_UPDATE_1);
150 otherQuotaState.setQuotas(TABLE_A, buildReqNumThrottle(TABLE_A_THROTTLE_1));
151 otherQuotaState.setQuotas(TABLE_B, buildReqNumThrottle(TABLE_B_THROTTLE));
152 assertEquals(LAST_UPDATE_1, otherQuotaState.getLastUpdate());
153 assertFalse(otherQuotaState.isBypass());
154
155 quotaInfo.update(otherQuotaState);
156 assertEquals(LAST_UPDATE_1, quotaInfo.getLastUpdate());
157 assertFalse(quotaInfo.isBypass());
158 assertThrottleException(quotaInfo.getTableLimiter(TABLE_A), TABLE_A_THROTTLE_1);
159 assertThrottleException(quotaInfo.getTableLimiter(TABLE_B), TABLE_B_THROTTLE);
160 assertNoopLimiter(quotaInfo.getTableLimiter(TABLE_C));
161
162
163 otherQuotaState = new UserQuotaState(LAST_UPDATE_2);
164 otherQuotaState.setQuotas(TABLE_A, buildReqNumThrottle(TABLE_A_THROTTLE_2));
165 otherQuotaState.setQuotas(TABLE_C, buildReqNumThrottle(TABLE_C_THROTTLE));
166 assertEquals(LAST_UPDATE_2, otherQuotaState.getLastUpdate());
167 assertFalse(otherQuotaState.isBypass());
168
169 quotaInfo.update(otherQuotaState);
170 assertEquals(LAST_UPDATE_2, quotaInfo.getLastUpdate());
171 assertFalse(quotaInfo.isBypass());
172 assertThrottleException(quotaInfo.getTableLimiter(TABLE_A), TABLE_A_THROTTLE_2
173 - TABLE_A_THROTTLE_1);
174 assertThrottleException(quotaInfo.getTableLimiter(TABLE_C), TABLE_C_THROTTLE);
175 assertNoopLimiter(quotaInfo.getTableLimiter(TABLE_B));
176
177
178 otherQuotaState = new UserQuotaState(LAST_UPDATE_3);
179 assertEquals(LAST_UPDATE_3, otherQuotaState.getLastUpdate());
180 assertTrue(otherQuotaState.isBypass());
181
182 quotaInfo.update(otherQuotaState);
183 assertEquals(LAST_UPDATE_3, quotaInfo.getLastUpdate());
184 assertTrue(quotaInfo.isBypass());
185 assertNoopLimiter(quotaInfo.getTableLimiter(UNKNOWN_TABLE_NAME));
186 }
187
188 @Test(timeout = 60000)
189 public void testTableThrottleWithBatch() {
190 final TableName TABLE_A = TableName.valueOf("TableA");
191 final int TABLE_A_THROTTLE_1 = 3;
192 final long LAST_UPDATE_1 = 10;
193
194 UserQuotaState quotaInfo = new UserQuotaState();
195 assertEquals(0, quotaInfo.getLastUpdate());
196 assertTrue(quotaInfo.isBypass());
197
198
199 UserQuotaState otherQuotaState = new UserQuotaState(LAST_UPDATE_1);
200 otherQuotaState.setQuotas(TABLE_A, buildReqNumThrottle(TABLE_A_THROTTLE_1));
201 assertEquals(LAST_UPDATE_1, otherQuotaState.getLastUpdate());
202 assertFalse(otherQuotaState.isBypass());
203
204 quotaInfo.update(otherQuotaState);
205 assertEquals(LAST_UPDATE_1, quotaInfo.getLastUpdate());
206 assertFalse(quotaInfo.isBypass());
207 QuotaLimiter limiter = quotaInfo.getTableLimiter(TABLE_A);
208 try {
209 limiter.checkQuota(TABLE_A_THROTTLE_1 + 1, TABLE_A_THROTTLE_1 + 1, 0, 0, 1, 0);
210 fail("Should have thrown RpcThrottlingException");
211 } catch (HBaseIOException e) {
212
213 }
214 }
215
216 private Quotas buildReqNumThrottle(final long limit) {
217 return Quotas
218 .newBuilder()
219 .setThrottle(
220 Throttle.newBuilder()
221 .setReqNum(ProtobufUtil.toTimedQuota(limit, TimeUnit.MINUTES, QuotaScope.MACHINE))
222 .build()).build();
223 }
224
225 private void assertThrottleException(final QuotaLimiter limiter, final int availReqs) {
226 assertNoThrottleException(limiter, availReqs);
227 try {
228 limiter.checkQuota(1, 1, 0, 0, 1, 0);
229 fail("Should have thrown RpcThrottlingException");
230 } catch (HBaseIOException e) {
231
232 }
233 }
234
235 private void assertNoThrottleException(final QuotaLimiter limiter, final int availReqs) {
236 for (int i = 0; i < availReqs; ++i) {
237 try {
238 limiter.checkQuota(1, 1, 0, 0, 1, 0);
239 } catch (HBaseIOException e) {
240 fail("Unexpected RpcThrottlingException after " + i + " requests. limit=" + availReqs);
241 }
242 limiter.grabQuota(1, 1, 0, 0, 1, 0);
243 }
244 }
245
246 private void assertNoopLimiter(final QuotaLimiter limiter) {
247 assertTrue(limiter == NoopQuotaLimiter.get());
248 assertNoThrottleException(limiter, 100);
249 }
250 }