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