001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.quotas;
019
020import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doGets;
021import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.doPuts;
022import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerExceedThrottleQuotaCacheRefresh;
023import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerNamespaceCacheRefresh;
024import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerRegionServerCacheRefresh;
025import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerTableCacheRefresh;
026import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.triggerUserCacheRefresh;
027import static org.apache.hadoop.hbase.quotas.ThrottleQuotaTestUtil.waitMinuteQuota;
028import static org.junit.jupiter.api.Assertions.assertEquals;
029import static org.junit.jupiter.api.Assertions.assertTrue;
030
031import java.io.IOException;
032import java.util.List;
033import java.util.concurrent.TimeUnit;
034import org.apache.hadoop.hbase.HBaseTestingUtil;
035import org.apache.hadoop.hbase.HConstants;
036import org.apache.hadoop.hbase.TableName;
037import org.apache.hadoop.hbase.client.Admin;
038import org.apache.hadoop.hbase.client.Get;
039import org.apache.hadoop.hbase.client.Table;
040import org.apache.hadoop.hbase.security.User;
041import org.apache.hadoop.hbase.testclassification.MediumTests;
042import org.apache.hadoop.hbase.testclassification.RegionServerTests;
043import org.apache.hadoop.hbase.util.Bytes;
044import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
045import org.junit.jupiter.api.AfterAll;
046import org.junit.jupiter.api.AfterEach;
047import org.junit.jupiter.api.BeforeAll;
048import org.junit.jupiter.api.Disabled;
049import org.junit.jupiter.api.Tag;
050import org.junit.jupiter.api.Test;
051import org.slf4j.Logger;
052import org.slf4j.LoggerFactory;
053
054// This tests breaks monotonic WAL numbering after HBASE-20746 because of how it
055// manipulates the EnvironmentEdge.
056@Disabled("See HBASE-27243")
057@Tag(RegionServerTests.TAG)
058@Tag(MediumTests.TAG)
059public class TestQuotaThrottle {
060
061  private final static Logger LOG = LoggerFactory.getLogger(TestQuotaThrottle.class);
062
063  private final static int REFRESH_TIME = 30 * 60000;
064
065  private final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
066  private final static byte[] FAMILY = Bytes.toBytes("cf");
067  private final static byte[] QUALIFIER = Bytes.toBytes("q");
068
069  private final static TableName[] TABLE_NAMES =
070    new TableName[] { TableName.valueOf("TestQuotaAdmin0"), TableName.valueOf("TestQuotaAdmin1"),
071      TableName.valueOf("TestQuotaAdmin2") };
072
073  private static Table[] tables;
074
075  @BeforeAll
076  public static void setUpBeforeClass() throws Exception {
077    TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
078    TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, REFRESH_TIME);
079    TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
080    TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
081    TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
082    TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
083    TEST_UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true);
084    TEST_UTIL.startMiniCluster(1);
085    TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
086
087    tables = new Table[TABLE_NAMES.length];
088    for (int i = 0; i < TABLE_NAMES.length; ++i) {
089      tables[i] = TEST_UTIL.createTable(TABLE_NAMES[i], FAMILY);
090    }
091  }
092
093  @AfterAll
094  public static void tearDownAfterClass() throws Exception {
095    EnvironmentEdgeManager.reset();
096    for (int i = 0; i < tables.length; ++i) {
097      if (tables[i] != null) {
098        tables[i].close();
099        TEST_UTIL.deleteTable(TABLE_NAMES[i]);
100      }
101    }
102
103    TEST_UTIL.shutdownMiniCluster();
104  }
105
106  @AfterEach
107  public void tearDown() throws Exception {
108    ThrottleQuotaTestUtil.clearQuotaCache(TEST_UTIL);
109  }
110
111  @Test
112  public void testUserGlobalThrottle() throws Exception {
113    final Admin admin = TEST_UTIL.getAdmin();
114    final String userName = User.getCurrent().getShortName();
115
116    // Add 6req/min limit
117    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6,
118      TimeUnit.MINUTES));
119    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
120
121    // should execute at max 6 requests
122    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables));
123
124    // wait a minute and you should get other 6 requests executed
125    waitMinuteQuota();
126    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables));
127
128    // Remove all the limits
129    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
130    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
131    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
132    assertEquals(60, doGets(60, tables));
133  }
134
135  @Test
136  public void testUserGlobalReadAndWriteThrottle() throws Exception {
137    final Admin admin = TEST_UTIL.getAdmin();
138    final String userName = User.getCurrent().getShortName();
139
140    // Add 6req/min limit for read request
141    admin.setQuota(
142      QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
143    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
144
145    // not limit for write request and should execute at max 6 read requests
146    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
147    assertEquals(6, doGets(100, tables));
148
149    waitMinuteQuota();
150
151    // Add 6req/min limit for write request
152    admin.setQuota(
153      QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
154    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES);
155
156    // should execute at max 6 read requests and at max 6 write write requests
157    assertEquals(6, doGets(100, tables));
158    assertEquals(6, doPuts(60, FAMILY, QUALIFIER, tables));
159
160    // Remove all the limits
161    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
162    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
163    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
164    assertEquals(60, doGets(60, tables));
165  }
166
167  @Test
168  public void testUserTableThrottle() throws Exception {
169    final Admin admin = TEST_UTIL.getAdmin();
170    final String userName = User.getCurrent().getShortName();
171
172    // Add 6req/min limit
173    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
174      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
175    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
176
177    // should execute at max 6 requests on tables[0] and have no limit on tables[1]
178    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
179    assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
180
181    // wait a minute and you should get other 6 requests executed
182    waitMinuteQuota();
183    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
184
185    // Remove all the limits
186    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
187    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
188    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
189    assertEquals(60, doGets(60, tables));
190  }
191
192  @Test
193  public void testUserTableReadAndWriteThrottle() throws Exception {
194    final Admin admin = TEST_UTIL.getAdmin();
195    final String userName = User.getCurrent().getShortName();
196
197    // Add 6req/min limit for write request on tables[0]
198    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
199      ThrottleType.WRITE_NUMBER, 6, TimeUnit.MINUTES));
200    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
201
202    // should execute at max 6 write requests and have no limit for read request
203    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
204    assertEquals(60, doGets(60, tables[0]));
205
206    // no limit on tables[1]
207    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables[1]));
208    assertEquals(60, doGets(60, tables[1]));
209
210    // wait a minute and you should get other 6 write requests executed
211    waitMinuteQuota();
212
213    // Add 6req/min limit for read request on tables[0]
214    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
215      ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
216    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
217
218    // should execute at max 6 read requests and at max 6 write requests
219    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
220    assertEquals(6, doGets(60, tables[0]));
221
222    // no limit on tables[1]
223    assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
224    assertEquals(30, doGets(30, tables[1]));
225
226    // Remove all the limits
227    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
228    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
229    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
230    assertEquals(60, doGets(60, tables));
231  }
232
233  @Test
234  public void testUserNamespaceThrottle() throws Exception {
235    final Admin admin = TEST_UTIL.getAdmin();
236    final String userName = User.getCurrent().getShortName();
237    final String NAMESPACE = "default";
238
239    // Add 6req/min limit
240    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE,
241      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
242    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
243
244    // should execute at max 6 requests on tables[0] and have no limit on tables[1]
245    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
246
247    // wait a minute and you should get other 6 requests executed
248    waitMinuteQuota();
249    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[1]));
250
251    // Remove all the limits
252    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
253    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
254    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
255    assertEquals(60, doGets(60, tables));
256  }
257
258  @Test
259  public void testUserNamespaceReadAndWriteThrottle() throws Exception {
260    final Admin admin = TEST_UTIL.getAdmin();
261    final String userName = User.getCurrent().getShortName();
262    final String NAMESPACE = "default";
263
264    // Add 6req/min limit for read request
265    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE, ThrottleType.READ_NUMBER,
266      6, TimeUnit.MINUTES));
267    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
268
269    // should execute at max 6 read requests and have no limit for write request
270    assertEquals(6, doGets(60, tables[0]));
271    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables[0]));
272
273    waitMinuteQuota();
274
275    // Add 6req/min limit for write request, too
276    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACE, ThrottleType.WRITE_NUMBER,
277      6, TimeUnit.MINUTES));
278    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
279
280    // should execute at max 6 read requests and at max 6 write requests
281    assertEquals(6, doGets(60, tables[0]));
282    assertEquals(6, doPuts(60, FAMILY, QUALIFIER, tables[0]));
283
284    // Remove all the limits
285    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, NAMESPACE));
286    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES);
287    assertEquals(60, doPuts(60, FAMILY, QUALIFIER, tables));
288    assertEquals(60, doGets(60, tables));
289  }
290
291  @Test
292  public void testTableGlobalThrottle() throws Exception {
293    final Admin admin = TEST_UTIL.getAdmin();
294
295    // Add 6req/min limit
296    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
297      6, TimeUnit.MINUTES));
298    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
299
300    // should execute at max 6 requests
301    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
302    // should have no limits
303    assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
304
305    // wait a minute and you should get other 6 requests executed
306    waitMinuteQuota();
307    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
308
309    // Remove all the limits
310    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
311    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
312    assertEquals(80, doGets(80, tables[0], tables[1]));
313  }
314
315  @Test
316  public void testTableGlobalReadAndWriteThrottle() throws Exception {
317    final Admin admin = TEST_UTIL.getAdmin();
318
319    // Add 6req/min limit for read request
320    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.READ_NUMBER, 6,
321      TimeUnit.MINUTES));
322    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
323
324    // should execute at max 6 read requests and have no limit for write request
325    assertEquals(6, doGets(100, tables[0]));
326    assertEquals(100, doPuts(100, FAMILY, QUALIFIER, tables[0]));
327    // should have no limits on tables[1]
328    assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
329    assertEquals(30, doGets(30, tables[1]));
330
331    // wait a minute and you should get other 6 requests executed
332    waitMinuteQuota();
333
334    // Add 6req/min limit for write request, too
335    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 6,
336      TimeUnit.MINUTES));
337    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
338
339    // should execute at max 6 read requests and at max 6 write requests
340    assertEquals(6, doGets(100, tables[0]));
341    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
342    // should have no limits on tables[1]
343    assertEquals(30, doPuts(30, FAMILY, QUALIFIER, tables[1]));
344    assertEquals(30, doGets(30, tables[1]));
345
346    // Remove all the limits
347    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
348    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
349    assertEquals(80, doGets(80, tables[0], tables[1]));
350  }
351
352  @Test
353  public void testNamespaceGlobalThrottle() throws Exception {
354    final Admin admin = TEST_UTIL.getAdmin();
355    final String NAMESPACE = "default";
356
357    // Add 6req/min limit
358    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER, 6,
359      TimeUnit.MINUTES));
360    triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
361
362    // should execute at max 6 requests
363    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
364
365    // wait a minute and you should get other 6 requests executed
366    waitMinuteQuota();
367    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[1]));
368
369    admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
370    triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
371    assertEquals(40, doPuts(40, FAMILY, QUALIFIER, tables[0]));
372  }
373
374  @Test
375  public void testNamespaceGlobalReadAndWriteThrottle() throws Exception {
376    final Admin admin = TEST_UTIL.getAdmin();
377    final String NAMESPACE = "default";
378
379    // Add 6req/min limit for write request
380    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.WRITE_NUMBER, 6,
381      TimeUnit.MINUTES));
382    triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
383
384    // should execute at max 6 write requests and no limit for read request
385    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
386    assertEquals(100, doGets(100, tables[0]));
387
388    // wait a minute and you should get other 6 requests executed
389    waitMinuteQuota();
390
391    // Add 6req/min limit for read request, too
392    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.READ_NUMBER, 6,
393      TimeUnit.MINUTES));
394    triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
395
396    // should execute at max 6 write requests and at max 6 read requests
397    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
398    assertEquals(6, doGets(100, tables[0]));
399
400    admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
401    triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
402    assertEquals(40, doPuts(40, FAMILY, QUALIFIER, tables[0]));
403  }
404
405  @Test
406  public void testUserAndTableThrottle() throws Exception {
407    final Admin admin = TEST_UTIL.getAdmin();
408    final String userName = User.getCurrent().getShortName();
409
410    // Add 6req/min limit for the user on tables[0]
411    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
412      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
413    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
414    // Add 12req/min limit for the user
415    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 12,
416      TimeUnit.MINUTES));
417    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1], TABLE_NAMES[2]);
418    // Add 8req/min limit for the tables[1]
419    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[1], ThrottleType.REQUEST_NUMBER,
420      8, TimeUnit.MINUTES));
421    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1]);
422    // Add a lower table level throttle on tables[0]
423    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
424      3, TimeUnit.MINUTES));
425    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
426
427    // should execute at max 12 requests
428    assertEquals(12, doGets(100, tables[2]));
429
430    // should execute at max 8 requests
431    waitMinuteQuota();
432    assertEquals(8, doGets(100, tables[1]));
433
434    // should execute at max 3 requests
435    waitMinuteQuota();
436    assertEquals(3, doPuts(100, FAMILY, QUALIFIER, tables[0]));
437
438    // Remove all the throttling rules
439    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[0]));
440    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
441    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0], TABLE_NAMES[1]);
442
443    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[1]));
444    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[1]);
445    waitMinuteQuota();
446    assertEquals(40, doGets(40, tables[1]));
447
448    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
449    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
450    waitMinuteQuota();
451    assertEquals(40, doGets(40, tables[0]));
452  }
453
454  @Test
455  public void testUserGlobalBypassThrottle() throws Exception {
456    final Admin admin = TEST_UTIL.getAdmin();
457    final String userName = User.getCurrent().getShortName();
458    final String NAMESPACE = "default";
459
460    // Add 6req/min limit for tables[0]
461    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
462      6, TimeUnit.MINUTES));
463    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
464    // Add 13req/min limit for the user
465    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACE, ThrottleType.REQUEST_NUMBER,
466      13, TimeUnit.MINUTES));
467    triggerNamespaceCacheRefresh(TEST_UTIL, false, TABLE_NAMES[1]);
468
469    // should execute at max 6 requests on table[0] and (13 - 6) on table[1]
470    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
471    assertEquals(7, doGets(100, tables[1]));
472    waitMinuteQuota();
473
474    // Set the global bypass for the user
475    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
476    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[2],
477      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
478    triggerUserCacheRefresh(TEST_UTIL, false, TABLE_NAMES[2]);
479    assertEquals(30, doGets(30, tables[0]));
480    assertEquals(30, doGets(30, tables[1]));
481    waitMinuteQuota();
482
483    // Remove the global bypass
484    // should execute at max 6 requests on table[0] and (13 - 6) on table[1]
485    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
486    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName, TABLE_NAMES[2]));
487    triggerUserCacheRefresh(TEST_UTIL, true, TABLE_NAMES[2]);
488    assertEquals(6, doPuts(100, FAMILY, QUALIFIER, tables[0]));
489    assertEquals(7, doGets(100, tables[1]));
490
491    // unset throttle
492    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
493    admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACE));
494    waitMinuteQuota();
495    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
496    triggerNamespaceCacheRefresh(TEST_UTIL, true, TABLE_NAMES[1]);
497    assertEquals(30, doGets(30, tables[0]));
498    assertEquals(30, doGets(30, tables[1]));
499  }
500
501  @Test
502  public void testTableWriteCapacityUnitThrottle() throws Exception {
503    final Admin admin = TEST_UTIL.getAdmin();
504
505    // Add 6CU/min limit
506    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
507      ThrottleType.WRITE_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
508    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
509
510    // should execute at max 6 capacity units because each put size is 1 capacity unit
511    assertEquals(6, doPuts(20, 10, FAMILY, QUALIFIER, tables[0]));
512
513    // wait a minute and you should execute at max 3 capacity units because each put size is 2
514    // capacity unit
515    waitMinuteQuota();
516    assertEquals(3, doPuts(20, 1025, FAMILY, QUALIFIER, tables[0]));
517
518    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
519    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
520  }
521
522  @Test
523  public void testTableReadCapacityUnitThrottle() throws Exception {
524    final Admin admin = TEST_UTIL.getAdmin();
525
526    // Add 6CU/min limit
527    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0],
528      ThrottleType.READ_CAPACITY_UNIT, 6, TimeUnit.MINUTES));
529    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
530
531    assertEquals(20, doPuts(20, 10, FAMILY, QUALIFIER, tables[0]));
532    // should execute at max 6 capacity units because each get size is 1 capacity unit
533    assertEquals(6, doGets(20, tables[0]));
534
535    assertEquals(20, doPuts(20, 2015, FAMILY, QUALIFIER, tables[0]));
536    // wait a minute and you should execute at max 3 capacity units because each get size is 2
537    // capacity unit on tables[0]
538    waitMinuteQuota();
539    assertEquals(3, doGets(20, tables[0]));
540
541    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
542    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
543  }
544
545  @Test
546  public void testTableExistsGetThrottle() throws Exception {
547    final Admin admin = TEST_UTIL.getAdmin();
548
549    // Add throttle quota
550    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
551      100, TimeUnit.MINUTES));
552    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
553
554    Table table = TEST_UTIL.getConnection().getTable(TABLE_NAMES[0]);
555    // An exists call when having throttle quota
556    table.exists(new Get(Bytes.toBytes("abc")));
557
558    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
559    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
560  }
561
562  @Test
563  public void testRegionServerThrottle() throws Exception {
564    final Admin admin = TEST_UTIL.getAdmin();
565    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 5,
566      TimeUnit.MINUTES));
567
568    // requests are throttled by table quota
569    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
570      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 7, TimeUnit.MINUTES));
571    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
572    triggerRegionServerCacheRefresh(TEST_UTIL, false);
573    assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
574    triggerRegionServerCacheRefresh(TEST_UTIL, false);
575    assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
576
577    // requests are throttled by region server quota
578    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
579      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 4, TimeUnit.MINUTES));
580    triggerRegionServerCacheRefresh(TEST_UTIL, false);
581    assertEquals(4, doPuts(10, FAMILY, QUALIFIER, tables[0]));
582    triggerRegionServerCacheRefresh(TEST_UTIL, false);
583    assertEquals(4, doPuts(10, FAMILY, QUALIFIER, tables[0]));
584
585    // unthrottle
586    admin.setQuota(
587      QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
588    triggerRegionServerCacheRefresh(TEST_UTIL, true);
589    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
590    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
591    triggerRegionServerCacheRefresh(TEST_UTIL, true);
592  }
593
594  @Test
595  public void testExceedThrottleQuota() throws Exception {
596    final Admin admin = TEST_UTIL.getAdmin();
597    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.WRITE_NUMBER, 5,
598      TimeUnit.MINUTES));
599    triggerTableCacheRefresh(TEST_UTIL, false, TABLE_NAMES[0]);
600    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
601      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
602    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
603      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.READ_NUMBER, 10, TimeUnit.SECONDS));
604    triggerRegionServerCacheRefresh(TEST_UTIL, false);
605
606    // enable exceed throttle quota
607    admin.exceedThrottleQuotaSwitch(true);
608    // exceed table limit and allowed by region server limit
609    triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, true);
610    waitMinuteQuota();
611    assertEquals(10, doPuts(10, FAMILY, QUALIFIER, tables[0]));
612    // exceed table limit and throttled by region server limit
613    waitMinuteQuota();
614    assertEquals(20, doPuts(25, FAMILY, QUALIFIER, tables[0]));
615
616    // set region server limiter is lower than table limiter
617    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
618      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 2, TimeUnit.SECONDS));
619    triggerRegionServerCacheRefresh(TEST_UTIL, false);
620    // throttled by region server limiter
621    waitMinuteQuota();
622    assertEquals(2, doPuts(10, FAMILY, QUALIFIER, tables[0]));
623    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(
624      QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, ThrottleType.WRITE_NUMBER, 20, TimeUnit.SECONDS));
625    triggerRegionServerCacheRefresh(TEST_UTIL, false);
626
627    // disable exceed throttle quota
628    admin.exceedThrottleQuotaSwitch(false);
629    triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, false);
630    waitMinuteQuota();
631    // throttled by table limit
632    assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
633
634    // enable exceed throttle quota and unthrottle region server
635    admin.exceedThrottleQuotaSwitch(true);
636    triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, true);
637    waitMinuteQuota();
638    admin.setQuota(
639      QuotaSettingsFactory.unthrottleRegionServer(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY));
640    triggerRegionServerCacheRefresh(TEST_UTIL, true);
641    waitMinuteQuota();
642    // throttled by table limit
643    assertEquals(5, doPuts(10, FAMILY, QUALIFIER, tables[0]));
644
645    // disable exceed throttle quota
646    admin.exceedThrottleQuotaSwitch(false);
647    triggerExceedThrottleQuotaCacheRefresh(TEST_UTIL, false);
648    // unthrottle table
649    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[0]));
650    triggerTableCacheRefresh(TEST_UTIL, true, TABLE_NAMES[0]);
651  }
652
653  @Test
654  public void testSetAndGetAllThrottleTypes() throws Exception {
655    for (ThrottleType throttleType : ThrottleType.values()) {
656      canSetAndGetUserThrottle(throttleType);
657    }
658  }
659
660  private void canSetAndGetUserThrottle(ThrottleType throttleType) throws IOException {
661    final Admin admin = TEST_UTIL.getAdmin();
662    final String userName = User.getCurrent().getShortName();
663
664    QuotaSettings setQuota =
665      QuotaSettingsFactory.throttleUser(userName, throttleType, 123, TimeUnit.SECONDS);
666    admin.setQuota(setQuota);
667
668    boolean found = false;
669    List<QuotaSettings> quotaSettings = admin.getQuota(new QuotaFilter().setUserFilter(userName));
670    for (QuotaSettings settings : quotaSettings) {
671      if (settings instanceof ThrottleSettings) {
672        ThrottleSettings throttle = (ThrottleSettings) settings;
673        if (
674          userName.equals(throttle.getUserName()) && throttle.getThrottleType() == throttleType
675            && throttle.getSoftLimit() == 123 && throttle.getTimeUnit() == TimeUnit.SECONDS
676        ) {
677          found = true;
678          break;
679        }
680      }
681    }
682
683    assertTrue(found, "Expected to find " + throttleType.name() + " quota for user " + userName);
684    admin.setQuota(QuotaSettingsFactory.unthrottleUserByThrottleType(userName, throttleType));
685  }
686
687}