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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.quotas
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertFalse
;
22 import static org
.junit
.Assert
.assertTrue
;
23 import static org
.junit
.Assert
.fail
;
25 import java
.util
.concurrent
.TimeUnit
;
26 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
27 import org
.apache
.hadoop
.hbase
.TableName
;
28 import org
.apache
.hadoop
.hbase
.testclassification
.RegionServerTests
;
29 import org
.apache
.hadoop
.hbase
.testclassification
.SmallTests
;
30 import org
.junit
.ClassRule
;
31 import org
.junit
.Rule
;
32 import org
.junit
.Test
;
33 import org
.junit
.experimental
.categories
.Category
;
34 import org
.junit
.rules
.TestName
;
36 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
37 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.QuotaProtos
.Quotas
;
38 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.QuotaProtos
.Throttle
;
40 @Category({RegionServerTests
.class, SmallTests
.class})
41 public class TestQuotaState
{
44 public static final HBaseClassTestRule CLASS_RULE
=
45 HBaseClassTestRule
.forClass(TestQuotaState
.class);
47 private static final TableName UNKNOWN_TABLE_NAME
= TableName
.valueOf("unknownTable");
50 public TestName name
= new TestName();
53 public void testQuotaStateBypass() {
54 QuotaState quotaInfo
= new QuotaState();
55 assertTrue(quotaInfo
.isBypass());
56 assertNoopLimiter(quotaInfo
.getGlobalLimiter());
58 UserQuotaState userQuotaState
= new UserQuotaState();
59 assertTrue(userQuotaState
.isBypass());
60 assertNoopLimiter(userQuotaState
.getTableLimiter(UNKNOWN_TABLE_NAME
));
64 public void testSimpleQuotaStateOperation() {
65 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
66 final int NUM_GLOBAL_THROTTLE
= 3;
67 final int NUM_TABLE_THROTTLE
= 2;
69 UserQuotaState quotaInfo
= new UserQuotaState();
70 assertTrue(quotaInfo
.isBypass());
73 quotaInfo
.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE
));
74 assertFalse(quotaInfo
.isBypass());
77 quotaInfo
.setQuotas(tableName
, buildReqNumThrottle(NUM_TABLE_THROTTLE
));
78 assertFalse(quotaInfo
.isBypass());
79 assertTrue(quotaInfo
.getGlobalLimiter() == quotaInfo
.getTableLimiter(UNKNOWN_TABLE_NAME
));
80 assertThrottleException(quotaInfo
.getTableLimiter(UNKNOWN_TABLE_NAME
), NUM_GLOBAL_THROTTLE
);
81 assertThrottleException(quotaInfo
.getTableLimiter(tableName
), NUM_TABLE_THROTTLE
);
85 public void testQuotaStateUpdateBypassThrottle() {
86 final long LAST_UPDATE
= 10;
88 UserQuotaState quotaInfo
= new UserQuotaState();
89 assertEquals(0, quotaInfo
.getLastUpdate());
90 assertTrue(quotaInfo
.isBypass());
92 UserQuotaState otherQuotaState
= new UserQuotaState(LAST_UPDATE
);
93 assertEquals(LAST_UPDATE
, otherQuotaState
.getLastUpdate());
94 assertTrue(otherQuotaState
.isBypass());
96 quotaInfo
.update(otherQuotaState
);
97 assertEquals(LAST_UPDATE
, quotaInfo
.getLastUpdate());
98 assertTrue(quotaInfo
.isBypass());
99 assertTrue(quotaInfo
.getGlobalLimiter() == quotaInfo
.getTableLimiter(UNKNOWN_TABLE_NAME
));
100 assertNoopLimiter(quotaInfo
.getTableLimiter(UNKNOWN_TABLE_NAME
));
104 public void testQuotaStateUpdateGlobalThrottle() {
105 final int NUM_GLOBAL_THROTTLE_1
= 3;
106 final int NUM_GLOBAL_THROTTLE_2
= 11;
107 final long LAST_UPDATE_1
= 10;
108 final long LAST_UPDATE_2
= 20;
109 final long LAST_UPDATE_3
= 30;
111 QuotaState quotaInfo
= new QuotaState();
112 assertEquals(0, quotaInfo
.getLastUpdate());
113 assertTrue(quotaInfo
.isBypass());
115 // Add global throttle
116 QuotaState otherQuotaState
= new QuotaState(LAST_UPDATE_1
);
117 otherQuotaState
.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_1
));
118 assertEquals(LAST_UPDATE_1
, otherQuotaState
.getLastUpdate());
119 assertFalse(otherQuotaState
.isBypass());
121 quotaInfo
.update(otherQuotaState
);
122 assertEquals(LAST_UPDATE_1
, quotaInfo
.getLastUpdate());
123 assertFalse(quotaInfo
.isBypass());
124 assertThrottleException(quotaInfo
.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_1
);
126 // Update global Throttle
127 otherQuotaState
= new QuotaState(LAST_UPDATE_2
);
128 otherQuotaState
.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_2
));
129 assertEquals(LAST_UPDATE_2
, otherQuotaState
.getLastUpdate());
130 assertFalse(otherQuotaState
.isBypass());
132 quotaInfo
.update(otherQuotaState
);
133 assertEquals(LAST_UPDATE_2
, quotaInfo
.getLastUpdate());
134 assertFalse(quotaInfo
.isBypass());
135 assertThrottleException(quotaInfo
.getGlobalLimiter(),
136 NUM_GLOBAL_THROTTLE_2
- NUM_GLOBAL_THROTTLE_1
);
138 // Remove global throttle
139 otherQuotaState
= new QuotaState(LAST_UPDATE_3
);
140 assertEquals(LAST_UPDATE_3
, otherQuotaState
.getLastUpdate());
141 assertTrue(otherQuotaState
.isBypass());
143 quotaInfo
.update(otherQuotaState
);
144 assertEquals(LAST_UPDATE_3
, quotaInfo
.getLastUpdate());
145 assertTrue(quotaInfo
.isBypass());
146 assertNoopLimiter(quotaInfo
.getGlobalLimiter());
150 public void testQuotaStateUpdateTableThrottle() {
151 final TableName tableNameA
= TableName
.valueOf(name
.getMethodName() + "A");
152 final TableName tableNameB
= TableName
.valueOf(name
.getMethodName() + "B");
153 final TableName tableNameC
= TableName
.valueOf(name
.getMethodName() + "C");
154 final int TABLE_A_THROTTLE_1
= 3;
155 final int TABLE_A_THROTTLE_2
= 11;
156 final int TABLE_B_THROTTLE
= 4;
157 final int TABLE_C_THROTTLE
= 5;
158 final long LAST_UPDATE_1
= 10;
159 final long LAST_UPDATE_2
= 20;
160 final long LAST_UPDATE_3
= 30;
162 UserQuotaState quotaInfo
= new UserQuotaState();
163 assertEquals(0, quotaInfo
.getLastUpdate());
164 assertTrue(quotaInfo
.isBypass());
166 // Add A B table limiters
167 UserQuotaState otherQuotaState
= new UserQuotaState(LAST_UPDATE_1
);
168 otherQuotaState
.setQuotas(tableNameA
, buildReqNumThrottle(TABLE_A_THROTTLE_1
));
169 otherQuotaState
.setQuotas(tableNameB
, buildReqNumThrottle(TABLE_B_THROTTLE
));
170 assertEquals(LAST_UPDATE_1
, otherQuotaState
.getLastUpdate());
171 assertFalse(otherQuotaState
.isBypass());
173 quotaInfo
.update(otherQuotaState
);
174 assertEquals(LAST_UPDATE_1
, quotaInfo
.getLastUpdate());
175 assertFalse(quotaInfo
.isBypass());
176 assertThrottleException(quotaInfo
.getTableLimiter(tableNameA
), TABLE_A_THROTTLE_1
);
177 assertThrottleException(quotaInfo
.getTableLimiter(tableNameB
), TABLE_B_THROTTLE
);
178 assertNoopLimiter(quotaInfo
.getTableLimiter(tableNameC
));
180 // Add C, Remove B, Update A table limiters
181 otherQuotaState
= new UserQuotaState(LAST_UPDATE_2
);
182 otherQuotaState
.setQuotas(tableNameA
, buildReqNumThrottle(TABLE_A_THROTTLE_2
));
183 otherQuotaState
.setQuotas(tableNameC
, buildReqNumThrottle(TABLE_C_THROTTLE
));
184 assertEquals(LAST_UPDATE_2
, otherQuotaState
.getLastUpdate());
185 assertFalse(otherQuotaState
.isBypass());
187 quotaInfo
.update(otherQuotaState
);
188 assertEquals(LAST_UPDATE_2
, quotaInfo
.getLastUpdate());
189 assertFalse(quotaInfo
.isBypass());
190 assertThrottleException(quotaInfo
.getTableLimiter(tableNameA
),
191 TABLE_A_THROTTLE_2
- TABLE_A_THROTTLE_1
);
192 assertThrottleException(quotaInfo
.getTableLimiter(tableNameC
), TABLE_C_THROTTLE
);
193 assertNoopLimiter(quotaInfo
.getTableLimiter(tableNameB
));
195 // Remove table limiters
196 otherQuotaState
= new UserQuotaState(LAST_UPDATE_3
);
197 assertEquals(LAST_UPDATE_3
, otherQuotaState
.getLastUpdate());
198 assertTrue(otherQuotaState
.isBypass());
200 quotaInfo
.update(otherQuotaState
);
201 assertEquals(LAST_UPDATE_3
, quotaInfo
.getLastUpdate());
202 assertTrue(quotaInfo
.isBypass());
203 assertNoopLimiter(quotaInfo
.getTableLimiter(UNKNOWN_TABLE_NAME
));
207 public void testTableThrottleWithBatch() {
208 final TableName TABLE_A
= TableName
.valueOf("TableA");
209 final int TABLE_A_THROTTLE_1
= 3;
210 final long LAST_UPDATE_1
= 10;
212 UserQuotaState quotaInfo
= new UserQuotaState();
213 assertEquals(0, quotaInfo
.getLastUpdate());
214 assertTrue(quotaInfo
.isBypass());
216 // Add A table limiters
217 UserQuotaState otherQuotaState
= new UserQuotaState(LAST_UPDATE_1
);
218 otherQuotaState
.setQuotas(TABLE_A
, buildReqNumThrottle(TABLE_A_THROTTLE_1
));
219 assertEquals(LAST_UPDATE_1
, otherQuotaState
.getLastUpdate());
220 assertFalse(otherQuotaState
.isBypass());
222 quotaInfo
.update(otherQuotaState
);
223 assertEquals(LAST_UPDATE_1
, quotaInfo
.getLastUpdate());
224 assertFalse(quotaInfo
.isBypass());
225 QuotaLimiter limiter
= quotaInfo
.getTableLimiter(TABLE_A
);
227 limiter
.checkQuota(TABLE_A_THROTTLE_1
+ 1, TABLE_A_THROTTLE_1
+ 1, 0, 0, 1, 0);
228 fail("Should have thrown RpcThrottlingException");
229 } catch (RpcThrottlingException e
) {
234 private Quotas
buildReqNumThrottle(final long limit
) {
235 return Quotas
.newBuilder()
236 .setThrottle(Throttle
.newBuilder()
237 .setReqNum(ProtobufUtil
.toTimedQuota(limit
, TimeUnit
.MINUTES
, QuotaScope
.MACHINE
))
242 private void assertThrottleException(final QuotaLimiter limiter
, final int availReqs
) {
243 assertNoThrottleException(limiter
, availReqs
);
245 limiter
.checkQuota(1, 1, 0, 0, 1, 0);
246 fail("Should have thrown RpcThrottlingException");
247 } catch (RpcThrottlingException e
) {
252 private void assertNoThrottleException(final QuotaLimiter limiter
, final int availReqs
) {
253 for (int i
= 0; i
< availReqs
; ++i
) {
255 limiter
.checkQuota(1, 1, 0, 0, 1, 0);
256 } catch (RpcThrottlingException e
) {
257 fail("Unexpected RpcThrottlingException after " + i
+ " requests. limit=" + availReqs
);
259 limiter
.grabQuota(1, 1, 0, 0, 1, 0);
263 private void assertNoopLimiter(final QuotaLimiter limiter
) {
264 assertTrue(limiter
== NoopQuotaLimiter
.get());
265 assertNoThrottleException(limiter
, 100);