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