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.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertFalse;
022import static org.junit.jupiter.api.Assertions.assertNull;
023import static org.junit.jupiter.api.Assertions.assertTrue;
024import static org.junit.jupiter.api.Assertions.fail;
025
026import java.io.IOException;
027import java.util.ArrayList;
028import java.util.List;
029import java.util.Objects;
030import java.util.concurrent.TimeUnit;
031import org.apache.hadoop.hbase.Cell;
032import org.apache.hadoop.hbase.CellScanner;
033import org.apache.hadoop.hbase.HBaseTestingUtil;
034import org.apache.hadoop.hbase.HConstants;
035import org.apache.hadoop.hbase.TableName;
036import org.apache.hadoop.hbase.client.Admin;
037import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
038import org.apache.hadoop.hbase.client.Put;
039import org.apache.hadoop.hbase.client.Result;
040import org.apache.hadoop.hbase.client.ResultScanner;
041import org.apache.hadoop.hbase.client.Scan;
042import org.apache.hadoop.hbase.client.Table;
043import org.apache.hadoop.hbase.client.TableDescriptor;
044import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
045import org.apache.hadoop.hbase.security.User;
046import org.apache.hadoop.hbase.testclassification.ClientTests;
047import org.apache.hadoop.hbase.testclassification.LargeTests;
048import org.apache.hadoop.hbase.util.Bytes;
049import org.apache.hadoop.hbase.util.JVMClusterUtil;
050import org.junit.jupiter.api.AfterAll;
051import org.junit.jupiter.api.AfterEach;
052import org.junit.jupiter.api.BeforeAll;
053import org.junit.jupiter.api.Tag;
054import org.junit.jupiter.api.Test;
055import org.slf4j.Logger;
056import org.slf4j.LoggerFactory;
057
058import org.apache.hbase.thirdparty.com.google.common.collect.Iterables;
059
060import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
061import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
062import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
063import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
064
065/**
066 * minicluster tests that validate that quota entries are properly set in the quota table
067 */
068@Tag(ClientTests.TAG)
069@Tag(LargeTests.TAG)
070public class TestQuotaAdmin {
071
072  private static final Logger LOG = LoggerFactory.getLogger(TestQuotaAdmin.class);
073
074  private final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
075
076  private final static TableName[] TABLE_NAMES =
077    new TableName[] { TableName.valueOf("TestQuotaAdmin0"), TableName.valueOf("TestQuotaAdmin1"),
078      TableName.valueOf("TestQuotaAdmin2") };
079
080  private final static String[] NAMESPACES =
081    new String[] { "NAMESPACE01", "NAMESPACE02", "NAMESPACE03" };
082
083  @BeforeAll
084  public static void setUpBeforeClass() throws Exception {
085    TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
086    TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, 2000);
087    TEST_UTIL.getConfiguration().setInt("hbase.hstore.compactionThreshold", 10);
088    TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
089    TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
090    TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6);
091    TEST_UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true);
092    TEST_UTIL.startMiniCluster(1);
093    TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
094  }
095
096  @AfterEach
097  public void clearQuotaTable() throws Exception {
098    if (TEST_UTIL.getAdmin().tableExists(QuotaUtil.QUOTA_TABLE_NAME)) {
099      TEST_UTIL.getAdmin().disableTable(QuotaUtil.QUOTA_TABLE_NAME);
100      TEST_UTIL.getAdmin().truncateTable(QuotaUtil.QUOTA_TABLE_NAME, false);
101    }
102  }
103
104  @AfterAll
105  public static void tearDownAfterClass() throws Exception {
106    TEST_UTIL.shutdownMiniCluster();
107  }
108
109  @Test
110  public void testThrottleType() throws Exception {
111    Admin admin = TEST_UTIL.getAdmin();
112    String userName = User.getCurrent().getShortName();
113
114    admin.setQuota(
115      QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
116    admin.setQuota(
117      QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 12, TimeUnit.MINUTES));
118    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
119
120    try (QuotaRetriever scanner = new QuotaRetriever(TEST_UTIL.getConnection())) {
121      int countThrottle = 0;
122      int countGlobalBypass = 0;
123      for (QuotaSettings settings : scanner) {
124        switch (settings.getQuotaType()) {
125          case THROTTLE:
126            ThrottleSettings throttle = (ThrottleSettings) settings;
127            if (throttle.getSoftLimit() == 6) {
128              assertEquals(ThrottleType.READ_NUMBER, throttle.getThrottleType());
129            } else if (throttle.getSoftLimit() == 12) {
130              assertEquals(ThrottleType.WRITE_NUMBER, throttle.getThrottleType());
131            } else {
132              fail("should not come here, because don't set quota with this limit");
133            }
134            assertEquals(userName, throttle.getUserName());
135            assertEquals(null, throttle.getTableName());
136            assertEquals(null, throttle.getNamespace());
137            assertEquals(TimeUnit.MINUTES, throttle.getTimeUnit());
138            countThrottle++;
139            break;
140          case GLOBAL_BYPASS:
141            countGlobalBypass++;
142            break;
143          default:
144            fail("unexpected settings type: " + settings.getQuotaType());
145        }
146      }
147      assertEquals(2, countThrottle);
148      assertEquals(1, countGlobalBypass);
149    }
150
151    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
152    assertNumResults(1, null);
153    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
154    assertNumResults(0, null);
155  }
156
157  @Test
158  public void testSimpleScan() throws Exception {
159    Admin admin = TEST_UTIL.getAdmin();
160    String userName = User.getCurrent().getShortName();
161
162    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6,
163      TimeUnit.MINUTES));
164    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
165
166    try (QuotaRetriever scanner = new QuotaRetriever(TEST_UTIL.getConnection())) {
167      int countThrottle = 0;
168      int countGlobalBypass = 0;
169      for (QuotaSettings settings : scanner) {
170        LOG.debug(Objects.toString(settings));
171        switch (settings.getQuotaType()) {
172          case THROTTLE:
173            ThrottleSettings throttle = (ThrottleSettings) settings;
174            assertEquals(userName, throttle.getUserName());
175            assertEquals(null, throttle.getTableName());
176            assertEquals(null, throttle.getNamespace());
177            assertEquals(null, throttle.getRegionServer());
178            assertEquals(6, throttle.getSoftLimit());
179            assertEquals(TimeUnit.MINUTES, throttle.getTimeUnit());
180            countThrottle++;
181            break;
182          case GLOBAL_BYPASS:
183            countGlobalBypass++;
184            break;
185          default:
186            fail("unexpected settings type: " + settings.getQuotaType());
187        }
188      }
189      assertEquals(1, countThrottle);
190      assertEquals(1, countGlobalBypass);
191    }
192
193    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
194    assertNumResults(1, null);
195    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
196    assertNumResults(0, null);
197  }
198
199  @Test
200  public void testMultiQuotaThrottling() throws Exception {
201    byte[] FAMILY = Bytes.toBytes("testFamily");
202    byte[] ROW = Bytes.toBytes("testRow");
203    byte[] QUALIFIER = Bytes.toBytes("testQualifier");
204    byte[] VALUE = Bytes.toBytes("testValue");
205
206    Admin admin = TEST_UTIL.getAdmin();
207    TableName tableName = TableName.valueOf("testMultiQuotaThrottling");
208    TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName)
209      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build();
210    admin.createTable(desc);
211
212    // Set up the quota.
213    admin.setQuota(QuotaSettingsFactory.throttleTable(tableName, ThrottleType.WRITE_NUMBER, 6,
214      TimeUnit.SECONDS));
215
216    Thread.sleep(1000);
217    TEST_UTIL.getRSForFirstRegionInTable(tableName).getRegionServerRpcQuotaManager().getQuotaCache()
218      .triggerCacheRefresh();
219    Thread.sleep(1000);
220
221    Table t = TEST_UTIL.getConnection().getTable(tableName);
222    try {
223      int size = 5;
224      List actions = new ArrayList();
225      Object[] results = new Object[size];
226
227      for (int i = 0; i < size; i++) {
228        Put put1 = new Put(ROW);
229        put1.addColumn(FAMILY, QUALIFIER, VALUE);
230        actions.add(put1);
231      }
232      t.batch(actions, results);
233      t.batch(actions, results);
234    } catch (IOException e) {
235      fail("Not supposed to get ThrottlingExcepiton " + e);
236    } finally {
237      t.close();
238    }
239  }
240
241  @Test
242  public void testQuotaRetrieverFilter() throws Exception {
243    Admin admin = TEST_UTIL.getAdmin();
244    TableName[] tables = new TableName[] { TableName.valueOf("T0"), TableName.valueOf("T01"),
245      TableName.valueOf("NS0:T2"), };
246    String[] namespaces = new String[] { "NS0", "NS01", "NS2" };
247    String[] users = new String[] { "User0", "User01", "User2" };
248
249    for (String user : users) {
250      admin.setQuota(
251        QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 1, TimeUnit.MINUTES));
252
253      for (TableName table : tables) {
254        admin.setQuota(QuotaSettingsFactory.throttleUser(user, table, ThrottleType.REQUEST_NUMBER,
255          2, TimeUnit.MINUTES));
256      }
257
258      for (String ns : namespaces) {
259        admin.setQuota(QuotaSettingsFactory.throttleUser(user, ns, ThrottleType.REQUEST_NUMBER, 3,
260          TimeUnit.MINUTES));
261      }
262    }
263    assertNumResults(21, null);
264
265    for (TableName table : tables) {
266      admin.setQuota(QuotaSettingsFactory.throttleTable(table, ThrottleType.REQUEST_NUMBER, 4,
267        TimeUnit.MINUTES));
268    }
269    assertNumResults(24, null);
270
271    for (String ns : namespaces) {
272      admin.setQuota(QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_NUMBER, 5,
273        TimeUnit.MINUTES));
274    }
275    assertNumResults(27, null);
276
277    assertNumResults(7, new QuotaFilter().setUserFilter("User0"));
278    assertNumResults(0, new QuotaFilter().setUserFilter("User"));
279    assertNumResults(21, new QuotaFilter().setUserFilter("User.*"));
280    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("T0"));
281    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("NS.*"));
282    assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setTableFilter("T"));
283    assertNumResults(6, new QuotaFilter().setUserFilter("User.*").setTableFilter("T.*"));
284    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS0"));
285    assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS"));
286    assertNumResults(9, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS.*"));
287    assertNumResults(6,
288      new QuotaFilter().setUserFilter("User.*").setTableFilter("T0").setNamespaceFilter("NS0"));
289    assertNumResults(1, new QuotaFilter().setTableFilter("T0"));
290    assertNumResults(0, new QuotaFilter().setTableFilter("T"));
291    assertNumResults(2, new QuotaFilter().setTableFilter("T.*"));
292    assertNumResults(3, new QuotaFilter().setTableFilter(".*T.*"));
293    assertNumResults(1, new QuotaFilter().setNamespaceFilter("NS0"));
294    assertNumResults(0, new QuotaFilter().setNamespaceFilter("NS"));
295    assertNumResults(3, new QuotaFilter().setNamespaceFilter("NS.*"));
296
297    for (String user : users) {
298      admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
299      for (TableName table : tables) {
300        admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, table));
301      }
302      for (String ns : namespaces) {
303        admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, ns));
304      }
305    }
306    assertNumResults(6, null);
307
308    for (TableName table : tables) {
309      admin.setQuota(QuotaSettingsFactory.unthrottleTable(table));
310    }
311    assertNumResults(3, null);
312
313    for (String ns : namespaces) {
314      admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(ns));
315    }
316    assertNumResults(0, null);
317  }
318
319  @Test
320  public void testSetGetRemoveSpaceQuota() throws Exception {
321    Admin admin = TEST_UTIL.getAdmin();
322    final TableName tn = TableName.valueOf("sq_table1");
323    final long sizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
324    final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_WRITES;
325    QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tn, sizeLimit, violationPolicy);
326    admin.setQuota(settings);
327
328    // Verify the Quotas in the table
329    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
330      ResultScanner scanner = quotaTable.getScanner(new Scan());
331      try {
332        Result r = Iterables.getOnlyElement(scanner);
333        CellScanner cells = r.cellScanner();
334        assertTrue(cells.advance(), "Expected to find a cell");
335        assertSpaceQuota(sizeLimit, violationPolicy, cells.current());
336      } finally {
337        scanner.close();
338      }
339    }
340
341    // Verify we can retrieve it via the QuotaRetriever API
342    try (QuotaRetriever scanner = new QuotaRetriever(admin.getConnection())) {
343      assertSpaceQuota(sizeLimit, violationPolicy, Iterables.getOnlyElement(scanner));
344    }
345
346    // Now, remove the quota
347    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
348    admin.setQuota(removeQuota);
349
350    // Verify that the record doesn't exist in the table
351    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
352      ResultScanner rs = quotaTable.getScanner(new Scan());
353      try {
354        assertNull(rs.next(), "Did not expect to find a quota entry");
355      } finally {
356        rs.close();
357      }
358    }
359
360    // Verify that we can also not fetch it via the API
361    try (QuotaRetriever scanner = new QuotaRetriever(admin.getConnection())) {
362      assertNull(scanner.next(), "Did not expect to find a quota entry");
363    }
364  }
365
366  @Test
367  public void testSetModifyRemoveSpaceQuota() throws Exception {
368    Admin admin = TEST_UTIL.getAdmin();
369    final TableName tn = TableName.valueOf("sq_table2");
370    final long originalSizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
371    final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_WRITES;
372    QuotaSettings settings =
373      QuotaSettingsFactory.limitTableSpace(tn, originalSizeLimit, violationPolicy);
374    admin.setQuota(settings);
375
376    // Verify the Quotas in the table
377    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
378      ResultScanner scanner = quotaTable.getScanner(new Scan());
379      try {
380        Result r = Iterables.getOnlyElement(scanner);
381        CellScanner cells = r.cellScanner();
382        assertTrue(cells.advance(), "Expected to find a cell");
383        assertSpaceQuota(originalSizeLimit, violationPolicy, cells.current());
384      } finally {
385        scanner.close();
386      }
387    }
388
389    // Verify we can retrieve it via the QuotaRetriever API
390    try (QuotaRetriever quotaScanner = new QuotaRetriever(admin.getConnection())) {
391      assertSpaceQuota(originalSizeLimit, violationPolicy, Iterables.getOnlyElement(quotaScanner));
392    }
393
394    // Setting a new size and policy should be reflected
395    final long newSizeLimit = 1024L * 1024L * 1024L * 1024L; // 1TB
396    final SpaceViolationPolicy newViolationPolicy = SpaceViolationPolicy.NO_WRITES_COMPACTIONS;
397    QuotaSettings newSettings =
398      QuotaSettingsFactory.limitTableSpace(tn, newSizeLimit, newViolationPolicy);
399    admin.setQuota(newSettings);
400
401    // Verify the new Quotas in the table
402    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
403      ResultScanner scanner = quotaTable.getScanner(new Scan());
404      try {
405        Result r = Iterables.getOnlyElement(scanner);
406        CellScanner cells = r.cellScanner();
407        assertTrue(cells.advance(), "Expected to find a cell");
408        assertSpaceQuota(newSizeLimit, newViolationPolicy, cells.current());
409      } finally {
410        scanner.close();
411      }
412    }
413
414    // Verify we can retrieve the new quota via the QuotaRetriever API
415    try (QuotaRetriever quotaScanner = new QuotaRetriever(admin.getConnection())) {
416      assertSpaceQuota(newSizeLimit, newViolationPolicy, Iterables.getOnlyElement(quotaScanner));
417    }
418
419    // Now, remove the quota
420    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
421    admin.setQuota(removeQuota);
422
423    // Verify that the record doesn't exist in the table
424    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
425      ResultScanner scanner = quotaTable.getScanner(new Scan());
426      try {
427        assertNull(scanner.next(), "Did not expect to find a quota entry");
428      } finally {
429        scanner.close();
430      }
431    }
432
433    // Verify that we can also not fetch it via the API
434    try (QuotaRetriever quotaScanner = new QuotaRetriever(admin.getConnection())) {
435      assertNull(quotaScanner.next(), "Did not expect to find a quota entry");
436    }
437  }
438
439  private void assertNumResults(int expected, final QuotaFilter filter) throws Exception {
440    assertEquals(expected, countResults(filter));
441  }
442
443  @Test
444  public void testSetGetRemoveRPCQuota() throws Exception {
445    testSetGetRemoveRPCQuota(ThrottleType.REQUEST_SIZE);
446    testSetGetRemoveRPCQuota(ThrottleType.REQUEST_CAPACITY_UNIT);
447  }
448
449  private void testSetGetRemoveRPCQuota(ThrottleType throttleType) throws Exception {
450    Admin admin = TEST_UTIL.getAdmin();
451    final TableName tn = TableName.valueOf("sq_table1");
452    QuotaSettings settings =
453      QuotaSettingsFactory.throttleTable(tn, throttleType, 2L, TimeUnit.HOURS);
454    admin.setQuota(settings);
455
456    // Verify the Quota in the table
457    verifyRecordPresentInQuotaTable(throttleType, 2L, TimeUnit.HOURS);
458
459    // Verify we can retrieve it via the QuotaRetriever API
460    verifyFetchableViaAPI(admin, throttleType, 2L, TimeUnit.HOURS);
461
462    // Now, remove the quota
463    QuotaSettings removeQuota = QuotaSettingsFactory.unthrottleTable(tn);
464    admin.setQuota(removeQuota);
465
466    // Verify that the record doesn't exist in the table
467    verifyRecordNotPresentInQuotaTable();
468
469    // Verify that we can also not fetch it via the API
470    verifyNotFetchableViaAPI(admin);
471  }
472
473  @Test
474  public void testSetModifyRemoveRPCQuota() throws Exception {
475    Admin admin = TEST_UTIL.getAdmin();
476    final TableName tn = TableName.valueOf("sq_table1");
477    QuotaSettings settings =
478      QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
479    admin.setQuota(settings);
480
481    // Verify the Quota in the table
482    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
483
484    // Verify we can retrieve it via the QuotaRetriever API
485    verifyFetchableViaAPI(admin, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
486
487    // Setting a limit and time unit should be reflected
488    QuotaSettings newSettings =
489      QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
490    admin.setQuota(newSettings);
491
492    // Verify the new Quota in the table
493    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
494
495    // Verify we can retrieve the new quota via the QuotaRetriever API
496    verifyFetchableViaAPI(admin, ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
497
498    // Now, remove the quota
499    QuotaSettings removeQuota = QuotaSettingsFactory.unthrottleTable(tn);
500    admin.setQuota(removeQuota);
501
502    // Verify that the record doesn't exist in the table
503    verifyRecordNotPresentInQuotaTable();
504
505    // Verify that we can also not fetch it via the API
506    verifyNotFetchableViaAPI(admin);
507
508  }
509
510  @Test
511  public void testSetAndRemoveRegionServerQuota() throws Exception {
512    Admin admin = TEST_UTIL.getAdmin();
513    String regionServer = QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY;
514    QuotaFilter rsFilter = new QuotaFilter().setRegionServerFilter(regionServer);
515
516    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer,
517      ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES));
518    assertNumResults(1, rsFilter);
519    // Verify the Quota in the table
520    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES);
521
522    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer,
523      ThrottleType.REQUEST_NUMBER, 20, TimeUnit.MINUTES));
524    assertNumResults(1, rsFilter);
525    // Verify the Quota in the table
526    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 20, TimeUnit.MINUTES);
527
528    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer, ThrottleType.READ_NUMBER,
529      30, TimeUnit.SECONDS));
530    int count = 0;
531    try (QuotaRetriever scanner = new QuotaRetriever(TEST_UTIL.getConnection(), rsFilter)) {
532      for (QuotaSettings settings : scanner) {
533        assertTrue(settings.getQuotaType() == QuotaType.THROTTLE);
534        ThrottleSettings throttleSettings = (ThrottleSettings) settings;
535        assertEquals(regionServer, throttleSettings.getRegionServer());
536        count++;
537        if (throttleSettings.getThrottleType() == ThrottleType.REQUEST_NUMBER) {
538          assertEquals(20, throttleSettings.getSoftLimit());
539          assertEquals(TimeUnit.MINUTES, throttleSettings.getTimeUnit());
540        } else if (throttleSettings.getThrottleType() == ThrottleType.READ_NUMBER) {
541          assertEquals(30, throttleSettings.getSoftLimit());
542          assertEquals(TimeUnit.SECONDS, throttleSettings.getTimeUnit());
543        }
544      }
545    }
546    assertEquals(2, count);
547
548    admin.setQuota(QuotaSettingsFactory.unthrottleRegionServer(regionServer));
549    assertNumResults(0, new QuotaFilter().setRegionServerFilter(regionServer));
550  }
551
552  @Test
553  public void testRpcThrottleWhenStartup() throws IOException, InterruptedException {
554    TEST_UTIL.getAdmin().switchRpcThrottle(false);
555    assertFalse(TEST_UTIL.getAdmin().isRpcThrottleEnabled());
556    TEST_UTIL.killMiniHBaseCluster();
557
558    TEST_UTIL.startMiniHBaseCluster();
559    assertFalse(TEST_UTIL.getAdmin().isRpcThrottleEnabled());
560    for (JVMClusterUtil.RegionServerThread rs : TEST_UTIL.getHBaseCluster()
561      .getRegionServerThreads()) {
562      RegionServerRpcQuotaManager quotaManager =
563        rs.getRegionServer().getRegionServerRpcQuotaManager();
564      assertFalse(quotaManager.isRpcThrottleEnabled());
565    }
566    // enable rpc throttle
567    TEST_UTIL.getAdmin().switchRpcThrottle(true);
568    assertTrue(TEST_UTIL.getAdmin().isRpcThrottleEnabled());
569  }
570
571  @Test
572  public void testSwitchRpcThrottle() throws IOException {
573    Admin admin = TEST_UTIL.getAdmin();
574    testSwitchRpcThrottle(admin, true, true);
575    testSwitchRpcThrottle(admin, true, false);
576    testSwitchRpcThrottle(admin, false, false);
577    testSwitchRpcThrottle(admin, false, true);
578  }
579
580  @Test
581  public void testSwitchExceedThrottleQuota() throws IOException {
582    String regionServer = QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY;
583    Admin admin = TEST_UTIL.getAdmin();
584
585    try {
586      admin.exceedThrottleQuotaSwitch(true);
587      fail("should not come here, because can't enable exceed throttle quota "
588        + "if there is no region server quota");
589    } catch (IOException e) {
590      LOG.warn("Expected exception", e);
591    }
592
593    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer,
594      ThrottleType.WRITE_NUMBER, 100, TimeUnit.SECONDS));
595    try {
596      admin.exceedThrottleQuotaSwitch(true);
597      fail("should not come here, because can't enable exceed throttle quota "
598        + "if there is no read region server quota");
599    } catch (IOException e) {
600      LOG.warn("Expected exception", e);
601    }
602
603    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer, ThrottleType.READ_NUMBER,
604      20, TimeUnit.MINUTES));
605    try {
606      admin.exceedThrottleQuotaSwitch(true);
607      fail("should not come here, because can't enable exceed throttle quota "
608        + "because not all region server quota are in seconds time unit");
609    } catch (IOException e) {
610      LOG.warn("Expected exception", e);
611    }
612    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(regionServer, ThrottleType.READ_NUMBER,
613      20, TimeUnit.SECONDS));
614
615    assertFalse(admin.exceedThrottleQuotaSwitch(true));
616    assertTrue(admin.exceedThrottleQuotaSwitch(true));
617    assertTrue(admin.exceedThrottleQuotaSwitch(false));
618    assertFalse(admin.exceedThrottleQuotaSwitch(false));
619    assertEquals(2, admin.getQuota(new QuotaFilter()).size());
620    admin.setQuota(QuotaSettingsFactory.unthrottleRegionServer(regionServer));
621  }
622
623  @Test
624  public void testQuotaScope() throws Exception {
625    Admin admin = TEST_UTIL.getAdmin();
626    String user = "user1";
627    String namespace = "testQuotaScope_ns";
628    TableName tableName = TableName.valueOf("testQuotaScope");
629    QuotaFilter filter = new QuotaFilter();
630
631    // set CLUSTER quota scope for namespace
632    admin.setQuota(QuotaSettingsFactory.throttleNamespace(namespace, ThrottleType.REQUEST_NUMBER,
633      10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
634    assertNumResults(1, filter);
635    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
636      QuotaScope.CLUSTER);
637    admin.setQuota(QuotaSettingsFactory.throttleNamespace(namespace, ThrottleType.REQUEST_NUMBER,
638      10, TimeUnit.MINUTES, QuotaScope.MACHINE));
639    assertNumResults(1, filter);
640    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
641      QuotaScope.MACHINE);
642    admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(namespace));
643    assertNumResults(0, filter);
644
645    // set CLUSTER quota scope for table
646    admin.setQuota(QuotaSettingsFactory.throttleTable(tableName, ThrottleType.REQUEST_NUMBER, 10,
647      TimeUnit.MINUTES, QuotaScope.CLUSTER));
648    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
649      QuotaScope.CLUSTER);
650    admin.setQuota(QuotaSettingsFactory.unthrottleTable(tableName));
651
652    // set CLUSTER quota scope for user
653    admin.setQuota(QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 10,
654      TimeUnit.MINUTES, QuotaScope.CLUSTER));
655    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
656      QuotaScope.CLUSTER);
657    admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
658
659    // set CLUSTER quota scope for user and table
660    admin.setQuota(QuotaSettingsFactory.throttleUser(user, tableName, ThrottleType.REQUEST_NUMBER,
661      10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
662    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
663      QuotaScope.CLUSTER);
664    admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
665
666    // set CLUSTER quota scope for user and namespace
667    admin.setQuota(QuotaSettingsFactory.throttleUser(user, namespace, ThrottleType.REQUEST_NUMBER,
668      10, TimeUnit.MINUTES, QuotaScope.CLUSTER));
669    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_NUMBER, 10, TimeUnit.MINUTES,
670      QuotaScope.CLUSTER);
671    admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
672  }
673
674  private void testSwitchRpcThrottle(Admin admin, boolean oldRpcThrottle, boolean newRpcThrottle)
675    throws IOException {
676    boolean state = admin.switchRpcThrottle(newRpcThrottle);
677    assertEquals(oldRpcThrottle, state);
678    assertEquals(newRpcThrottle, admin.isRpcThrottleEnabled());
679    TEST_UTIL.getHBaseCluster().getRegionServerThreads().stream()
680      .forEach(rs -> assertEquals(newRpcThrottle,
681        rs.getRegionServer().getRegionServerRpcQuotaManager().isRpcThrottleEnabled()));
682  }
683
684  private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu)
685    throws Exception {
686    verifyRecordPresentInQuotaTable(type, limit, tu, QuotaScope.MACHINE);
687  }
688
689  private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu,
690    QuotaScope scope) throws Exception {
691    // Verify the RPC Quotas in the table
692    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
693      ResultScanner scanner = quotaTable.getScanner(new Scan())) {
694      Result r = Iterables.getOnlyElement(scanner);
695      CellScanner cells = r.cellScanner();
696      assertTrue(cells.advance(), "Expected to find a cell");
697      assertRPCQuota(type, limit, tu, scope, cells.current());
698    }
699  }
700
701  private void verifyRecordNotPresentInQuotaTable() throws Exception {
702    // Verify that the record doesn't exist in the QuotaTableUtil.QUOTA_TABLE_NAME
703    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
704      ResultScanner scanner = quotaTable.getScanner(new Scan())) {
705      assertNull(scanner.next(), "Did not expect to find a quota entry");
706    }
707  }
708
709  private void verifyFetchableViaAPI(Admin admin, ThrottleType type, long limit, TimeUnit tu)
710    throws Exception {
711    // Verify we can retrieve the new quota via the QuotaRetriever API
712    try (QuotaRetriever quotaScanner = new QuotaRetriever(admin.getConnection())) {
713      assertRPCQuota(type, limit, tu, Iterables.getOnlyElement(quotaScanner));
714    }
715  }
716
717  private void verifyNotFetchableViaAPI(Admin admin) throws Exception {
718    // Verify that we can also not fetch it via the API
719    try (QuotaRetriever quotaScanner = new QuotaRetriever(admin.getConnection())) {
720      assertNull(quotaScanner.next(), "Did not expect to find a quota entry");
721    }
722  }
723
724  private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu, QuotaScope scope,
725    Cell cell) throws Exception {
726    Quotas q = QuotaTableUtil.quotasFromData(cell.getValueArray(), cell.getValueOffset(),
727      cell.getValueLength());
728    assertTrue(q.hasThrottle(), "Quota should have rpc quota defined");
729
730    QuotaProtos.Throttle rpcQuota = q.getThrottle();
731    QuotaProtos.TimedQuota t = null;
732
733    switch (type) {
734      case REQUEST_SIZE:
735        assertTrue(rpcQuota.hasReqSize());
736        t = rpcQuota.getReqSize();
737        break;
738      case READ_NUMBER:
739        assertTrue(rpcQuota.hasReadNum());
740        t = rpcQuota.getReadNum();
741        break;
742      case READ_SIZE:
743        assertTrue(rpcQuota.hasReadSize());
744        t = rpcQuota.getReadSize();
745        break;
746      case REQUEST_NUMBER:
747        assertTrue(rpcQuota.hasReqNum());
748        t = rpcQuota.getReqNum();
749        break;
750      case WRITE_NUMBER:
751        assertTrue(rpcQuota.hasWriteNum());
752        t = rpcQuota.getWriteNum();
753        break;
754      case WRITE_SIZE:
755        assertTrue(rpcQuota.hasWriteSize());
756        t = rpcQuota.getWriteSize();
757        break;
758      case REQUEST_CAPACITY_UNIT:
759        assertTrue(rpcQuota.hasReqCapacityUnit());
760        t = rpcQuota.getReqCapacityUnit();
761        break;
762      case READ_CAPACITY_UNIT:
763        assertTrue(rpcQuota.hasReadCapacityUnit());
764        t = rpcQuota.getReadCapacityUnit();
765        break;
766      case WRITE_CAPACITY_UNIT:
767        assertTrue(rpcQuota.hasWriteCapacityUnit());
768        t = rpcQuota.getWriteCapacityUnit();
769        break;
770      case ATOMIC_READ_SIZE:
771        assertTrue(rpcQuota.hasAtomicReadSize());
772        t = rpcQuota.getAtomicReadSize();
773        break;
774      case ATOMIC_REQUEST_NUMBER:
775        assertTrue(rpcQuota.hasAtomicReqNum());
776        t = rpcQuota.getAtomicReqNum();
777        break;
778      default:
779    }
780
781    assertEquals(scope, ProtobufUtil.toQuotaScope(t.getScope()));
782    assertEquals(t.getSoftLimit(), limit);
783    assertEquals(t.getTimeUnit(), ProtobufUtil.toProtoTimeUnit(tu));
784  }
785
786  private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu,
787    QuotaSettings actualSettings) throws Exception {
788    assertTrue(actualSettings instanceof ThrottleSettings,
789      "The actual QuotaSettings was not an instance of " + ThrottleSettings.class + " but of "
790        + actualSettings.getClass());
791    QuotaProtos.ThrottleRequest throttleRequest = ((ThrottleSettings) actualSettings).getProto();
792    assertEquals(limit, throttleRequest.getTimedQuota().getSoftLimit());
793    assertEquals(ProtobufUtil.toProtoTimeUnit(tu), throttleRequest.getTimedQuota().getTimeUnit());
794    assertEquals(ProtobufUtil.toProtoThrottleType(type), throttleRequest.getType());
795  }
796
797  private void assertSpaceQuota(long sizeLimit, SpaceViolationPolicy violationPolicy, Cell cell)
798    throws Exception {
799    Quotas q = QuotaTableUtil.quotasFromData(cell.getValueArray(), cell.getValueOffset(),
800      cell.getValueLength());
801    assertTrue(q.hasSpace(), "Quota should have space quota defined");
802    QuotaProtos.SpaceQuota spaceQuota = q.getSpace();
803    assertEquals(sizeLimit, spaceQuota.getSoftLimit());
804    assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(spaceQuota.getViolationPolicy()));
805  }
806
807  private void assertSpaceQuota(long sizeLimit, SpaceViolationPolicy violationPolicy,
808    QuotaSettings actualSettings) {
809    assertTrue(actualSettings instanceof SpaceLimitSettings,
810      "The actual QuotaSettings was not an instance of " + SpaceLimitSettings.class + " but of "
811        + actualSettings.getClass());
812    SpaceLimitRequest spaceLimitRequest = ((SpaceLimitSettings) actualSettings).getProto();
813    assertEquals(sizeLimit, spaceLimitRequest.getQuota().getSoftLimit());
814    assertEquals(violationPolicy,
815      ProtobufUtil.toViolationPolicy(spaceLimitRequest.getQuota().getViolationPolicy()));
816  }
817
818  private int countResults(final QuotaFilter filter) throws Exception {
819    try (QuotaRetriever scanner = new QuotaRetriever(TEST_UTIL.getConnection(), filter)) {
820      int count = 0;
821      for (QuotaSettings settings : scanner) {
822        LOG.debug(Objects.toString(settings));
823        count++;
824      }
825      return count;
826    }
827  }
828
829  @Test
830  public void testUserUnThrottleByType() throws Exception {
831    final Admin admin = TEST_UTIL.getAdmin();
832    final String userName = User.getCurrent().getShortName();
833    String userName01 = "user01";
834    // Add 6req/min limit
835    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6,
836      TimeUnit.MINUTES));
837    admin.setQuota(
838      QuotaSettingsFactory.throttleUser(userName, ThrottleType.REQUEST_SIZE, 6, TimeUnit.MINUTES));
839    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, ThrottleType.REQUEST_NUMBER, 6,
840      TimeUnit.MINUTES));
841    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, ThrottleType.REQUEST_SIZE, 6,
842      TimeUnit.MINUTES));
843    admin.setQuota(
844      QuotaSettingsFactory.unthrottleUserByThrottleType(userName, ThrottleType.REQUEST_NUMBER));
845    assertEquals(3, getQuotaSettingCount(admin));
846    admin.setQuota(
847      QuotaSettingsFactory.unthrottleUserByThrottleType(userName, ThrottleType.REQUEST_SIZE));
848    assertEquals(2, getQuotaSettingCount(admin));
849    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName01));
850    assertEquals(0, getQuotaSettingCount(admin));
851  }
852
853  @Test
854  public void testUserTableUnThrottleByType() throws Exception {
855    final Admin admin = TEST_UTIL.getAdmin();
856    final String userName = User.getCurrent().getShortName();
857    String userName01 = "user01";
858    // Add 6req/min limit
859    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
860      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
861    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, TABLE_NAMES[0],
862      ThrottleType.REQUEST_SIZE, 6, TimeUnit.MINUTES));
863    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, TABLE_NAMES[1],
864      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
865    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, TABLE_NAMES[1],
866      ThrottleType.REQUEST_SIZE, 6, TimeUnit.MINUTES));
867    admin.setQuota(QuotaSettingsFactory.unthrottleUserByThrottleType(userName, TABLE_NAMES[0],
868      ThrottleType.REQUEST_NUMBER));
869    assertEquals(3, getQuotaSettingCount(admin));
870    admin.setQuota(QuotaSettingsFactory.unthrottleUserByThrottleType(userName, TABLE_NAMES[0],
871      ThrottleType.REQUEST_SIZE));
872    assertEquals(2, getQuotaSettingCount(admin));
873    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName01));
874    assertEquals(0, getQuotaSettingCount(admin));
875  }
876
877  @Test
878  public void testUserNameSpaceUnThrottleByType() throws Exception {
879    final Admin admin = TEST_UTIL.getAdmin();
880    final String userName = User.getCurrent().getShortName();
881    String userName01 = "user01";
882    // Add 6req/min limit
883    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACES[0],
884      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
885    admin.setQuota(QuotaSettingsFactory.throttleUser(userName, NAMESPACES[0],
886      ThrottleType.REQUEST_SIZE, 6, TimeUnit.MINUTES));
887    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, NAMESPACES[1],
888      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
889    admin.setQuota(QuotaSettingsFactory.throttleUser(userName01, NAMESPACES[1],
890      ThrottleType.REQUEST_SIZE, 6, TimeUnit.MINUTES));
891    admin.setQuota(QuotaSettingsFactory.unthrottleUserByThrottleType(userName, NAMESPACES[0],
892      ThrottleType.REQUEST_NUMBER));
893    assertEquals(3, getQuotaSettingCount(admin));
894    admin.setQuota(QuotaSettingsFactory.unthrottleUserByThrottleType(userName, NAMESPACES[0],
895      ThrottleType.REQUEST_SIZE));
896    assertEquals(2, getQuotaSettingCount(admin));
897    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName01));
898    assertEquals(0, getQuotaSettingCount(admin));
899  }
900
901  @Test
902  public void testTableUnThrottleByType() throws Exception {
903    final Admin admin = TEST_UTIL.getAdmin();
904    final String userName = User.getCurrent().getShortName();
905    // Add 6req/min limit
906    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_NUMBER,
907      6, TimeUnit.MINUTES));
908    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[0], ThrottleType.REQUEST_SIZE, 6,
909      TimeUnit.MINUTES));
910    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[1], ThrottleType.REQUEST_NUMBER,
911      6, TimeUnit.MINUTES));
912    admin.setQuota(QuotaSettingsFactory.throttleTable(TABLE_NAMES[1], ThrottleType.REQUEST_SIZE, 6,
913      TimeUnit.MINUTES));
914    admin.setQuota(QuotaSettingsFactory.unthrottleTableByThrottleType(TABLE_NAMES[0],
915      ThrottleType.REQUEST_NUMBER));
916    assertEquals(3, getQuotaSettingCount(admin));
917    admin.setQuota(QuotaSettingsFactory.unthrottleTableByThrottleType(TABLE_NAMES[0],
918      ThrottleType.REQUEST_SIZE));
919    assertEquals(2, getQuotaSettingCount(admin));
920    admin.setQuota(QuotaSettingsFactory.unthrottleTable(TABLE_NAMES[1]));
921    assertEquals(0, getQuotaSettingCount(admin));
922  }
923
924  @Test
925  public void testNameSpaceUnThrottleByType() throws Exception {
926    final Admin admin = TEST_UTIL.getAdmin();
927    final String userName = User.getCurrent().getShortName();
928    // Add 6req/min limit
929    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACES[0],
930      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
931    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACES[0], ThrottleType.REQUEST_SIZE,
932      6, TimeUnit.MINUTES));
933    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACES[1],
934      ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
935    admin.setQuota(QuotaSettingsFactory.throttleNamespace(NAMESPACES[1], ThrottleType.REQUEST_SIZE,
936      6, TimeUnit.MINUTES));
937    admin.setQuota(QuotaSettingsFactory.unthrottleNamespaceByThrottleType(NAMESPACES[0],
938      ThrottleType.REQUEST_NUMBER));
939    assertEquals(3, getQuotaSettingCount(admin));
940    admin.setQuota(QuotaSettingsFactory.unthrottleNamespaceByThrottleType(NAMESPACES[0],
941      ThrottleType.REQUEST_SIZE));
942    assertEquals(2, getQuotaSettingCount(admin));
943    admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(NAMESPACES[1]));
944    assertEquals(0, getQuotaSettingCount(admin));
945  }
946
947  @Test
948  public void testRegionServerUnThrottleByType() throws Exception {
949    final Admin admin = TEST_UTIL.getAdmin();
950    final String[] REGIONSERVER = { "RS01", "RS02" };
951
952    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(REGIONSERVER[0],
953      ThrottleType.READ_NUMBER, 4, TimeUnit.MINUTES));
954    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(REGIONSERVER[0],
955      ThrottleType.WRITE_NUMBER, 4, TimeUnit.MINUTES));
956    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(REGIONSERVER[1],
957      ThrottleType.READ_NUMBER, 4, TimeUnit.MINUTES));
958    admin.setQuota(QuotaSettingsFactory.throttleRegionServer(REGIONSERVER[1],
959      ThrottleType.WRITE_NUMBER, 4, TimeUnit.MINUTES));
960
961    admin.setQuota(QuotaSettingsFactory.unthrottleRegionServerByThrottleType(REGIONSERVER[0],
962      ThrottleType.READ_NUMBER));
963    assertEquals(3, getQuotaSettingCount(admin));
964    admin.setQuota(QuotaSettingsFactory.unthrottleRegionServerByThrottleType(REGIONSERVER[0],
965      ThrottleType.WRITE_NUMBER));
966    assertEquals(2, getQuotaSettingCount(admin));
967    admin.setQuota(QuotaSettingsFactory.unthrottleRegionServer(REGIONSERVER[1]));
968    assertEquals(0, getQuotaSettingCount(admin));
969  }
970
971  public int getQuotaSettingCount(Admin admin) throws IOException {
972    List<QuotaSettings> list_quotas = admin.getQuota(new QuotaFilter());
973    int quotaSettingCount = 0;
974    for (QuotaSettings setting : list_quotas) {
975      quotaSettingCount++;
976      LOG.info("Quota Setting:" + setting);
977    }
978    return quotaSettingCount;
979  }
980
981  @Test
982  public void testQuotaTableDisableAndEnable() throws Exception {
983    final Admin admin = TEST_UTIL.getAdmin();
984    admin.disableTable(QuotaUtil.QUOTA_TABLE_NAME);
985    try {
986      admin.enableTable(QuotaUtil.QUOTA_TABLE_NAME);
987    } catch (Exception ex) {
988      fail("Got an exception while enabling table: " + QuotaUtil.QUOTA_TABLE_NAME);
989    }
990  }
991}