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