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