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.assertNull;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.io.IOException;
026import java.util.ArrayList;
027import java.util.List;
028import java.util.Objects;
029import java.util.concurrent.TimeUnit;
030
031import org.apache.hadoop.hbase.Cell;
032import org.apache.hadoop.hbase.CellScanner;
033import org.apache.hadoop.hbase.HBaseClassTestRule;
034import org.apache.hadoop.hbase.HBaseTestingUtility;
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.MediumTests;
049import org.apache.hadoop.hbase.util.Bytes;
050import org.junit.After;
051import org.junit.AfterClass;
052import org.junit.BeforeClass;
053import org.junit.ClassRule;
054import org.junit.Test;
055import org.junit.experimental.categories.Category;
056import org.slf4j.Logger;
057import org.slf4j.LoggerFactory;
058
059import org.apache.hbase.thirdparty.com.google.common.collect.Iterables;
060
061import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
062import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
063import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
064import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
065
066/**
067 * minicluster tests that validate that quota  entries are properly set in the quota table
068 */
069@Category({ClientTests.class, MediumTests.class})
070public class TestQuotaAdmin {
071
072  @ClassRule
073  public static final HBaseClassTestRule CLASS_RULE =
074      HBaseClassTestRule.forClass(TestQuotaAdmin.class);
075
076  private static final Logger LOG = LoggerFactory.getLogger(TestQuotaAdmin.class);
077
078  private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
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, 2000);
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
093  @After
094  public void clearQuotaTable() throws Exception {
095    if (TEST_UTIL.getAdmin().tableExists(QuotaUtil.QUOTA_TABLE_NAME)) {
096      TEST_UTIL.getAdmin().disableTable(QuotaUtil.QUOTA_TABLE_NAME);
097      TEST_UTIL.getAdmin().truncateTable(QuotaUtil.QUOTA_TABLE_NAME, false);
098    }
099  }
100
101  @AfterClass
102  public static void tearDownAfterClass() throws Exception {
103    TEST_UTIL.shutdownMiniCluster();
104  }
105
106  @Test
107  public void testThrottleType() throws Exception {
108    Admin admin = TEST_UTIL.getAdmin();
109    String userName = User.getCurrent().getShortName();
110
111    admin.setQuota(
112        QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES));
113    admin.setQuota(QuotaSettingsFactory
114        .throttleUser(userName, ThrottleType.WRITE_NUMBER, 12, TimeUnit.MINUTES));
115    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
116
117    try (QuotaRetriever scanner = QuotaRetriever.open(TEST_UTIL.getConfiguration())) {
118      int countThrottle = 0;
119      int countGlobalBypass = 0;
120      for (QuotaSettings settings: scanner) {
121        switch (settings.getQuotaType()) {
122          case THROTTLE:
123            ThrottleSettings throttle = (ThrottleSettings)settings;
124            if (throttle.getSoftLimit() == 6) {
125              assertEquals(ThrottleType.READ_NUMBER, throttle.getThrottleType());
126            } else if (throttle.getSoftLimit() == 12) {
127              assertEquals(ThrottleType.WRITE_NUMBER, throttle.getThrottleType());
128            } else {
129              fail("should not come here, because don't set quota with this limit");
130            }
131            assertEquals(userName, throttle.getUserName());
132            assertEquals(null, throttle.getTableName());
133            assertEquals(null, throttle.getNamespace());
134            assertEquals(TimeUnit.MINUTES, throttle.getTimeUnit());
135            countThrottle++;
136            break;
137          case GLOBAL_BYPASS:
138            countGlobalBypass++;
139            break;
140          default:
141            fail("unexpected settings type: " + settings.getQuotaType());
142        }
143      }
144      assertEquals(2, countThrottle);
145      assertEquals(1, countGlobalBypass);
146    }
147
148    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
149    assertNumResults(1, null);
150    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
151    assertNumResults(0, null);
152  }
153
154  @Test
155  public void testSimpleScan() throws Exception {
156    Admin admin = TEST_UTIL.getAdmin();
157    String userName = User.getCurrent().getShortName();
158
159    admin.setQuota(QuotaSettingsFactory
160      .throttleUser(userName, ThrottleType.REQUEST_NUMBER, 6, TimeUnit.MINUTES));
161    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true));
162
163    try (QuotaRetriever scanner = QuotaRetriever.open(TEST_UTIL.getConfiguration())) {
164      int countThrottle = 0;
165      int countGlobalBypass = 0;
166      for (QuotaSettings settings: scanner) {
167        LOG.debug(Objects.toString(settings));
168        switch (settings.getQuotaType()) {
169          case THROTTLE:
170            ThrottleSettings throttle = (ThrottleSettings)settings;
171            assertEquals(userName, throttle.getUserName());
172            assertEquals(null, throttle.getTableName());
173            assertEquals(null, throttle.getNamespace());
174            assertEquals(6, throttle.getSoftLimit());
175            assertEquals(TimeUnit.MINUTES, throttle.getTimeUnit());
176            countThrottle++;
177            break;
178          case GLOBAL_BYPASS:
179            countGlobalBypass++;
180            break;
181          default:
182            fail("unexpected settings type: " + settings.getQuotaType());
183        }
184      }
185      assertEquals(1, countThrottle);
186      assertEquals(1, countGlobalBypass);
187    }
188
189    admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName));
190    assertNumResults(1, null);
191    admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false));
192    assertNumResults(0, null);
193  }
194
195  @Test
196  public void testMultiQuotaThrottling() throws Exception {
197    byte[] FAMILY = Bytes.toBytes("testFamily");
198    byte[] ROW = Bytes.toBytes("testRow");
199    byte[] QUALIFIER = Bytes.toBytes("testQualifier");
200    byte[] VALUE = Bytes.toBytes("testValue");
201
202    Admin admin = TEST_UTIL.getAdmin();
203    TableName tableName = TableName.valueOf("testMultiQuotaThrottling");
204    TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName)
205        .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build();
206    admin.createTable(desc);
207
208    // Set up the quota.
209    admin.setQuota(QuotaSettingsFactory.throttleTable(tableName, ThrottleType.WRITE_NUMBER, 6,
210        TimeUnit.SECONDS));
211
212    Thread.sleep(1000);
213    TEST_UTIL.getRSForFirstRegionInTable(tableName).getRegionServerRpcQuotaManager().
214        getQuotaCache().triggerCacheRefresh();
215    Thread.sleep(1000);
216
217    Table t =  TEST_UTIL.getConnection().getTable(tableName);
218    try {
219      int size = 5;
220      List actions = new ArrayList();
221      Object[] results = new Object[size];
222
223      for (int i = 0; i < size; i++) {
224        Put put1 = new Put(ROW);
225        put1.addColumn(FAMILY, QUALIFIER, VALUE);
226        actions.add(put1);
227      }
228      t.batch(actions, results);
229      t.batch(actions, results);
230    } catch (IOException e) {
231      fail("Not supposed to get ThrottlingExcepiton " + e);
232    } finally {
233      t.close();
234    }
235  }
236
237
238  @Test
239  public void testQuotaRetrieverFilter() throws Exception {
240    Admin admin = TEST_UTIL.getAdmin();
241    TableName[] tables = new TableName[] {
242      TableName.valueOf("T0"), TableName.valueOf("T01"), TableName.valueOf("NS0:T2"),
243    };
244    String[] namespaces = new String[] { "NS0", "NS01", "NS2" };
245    String[] users = new String[] { "User0", "User01", "User2" };
246
247    for (String user: users) {
248      admin.setQuota(QuotaSettingsFactory
249        .throttleUser(user, ThrottleType.REQUEST_NUMBER, 1, TimeUnit.MINUTES));
250
251      for (TableName table: tables) {
252        admin.setQuota(QuotaSettingsFactory
253          .throttleUser(user, table, ThrottleType.REQUEST_NUMBER, 2, TimeUnit.MINUTES));
254      }
255
256      for (String ns: namespaces) {
257        admin.setQuota(QuotaSettingsFactory
258          .throttleUser(user, ns, ThrottleType.REQUEST_NUMBER, 3, TimeUnit.MINUTES));
259      }
260    }
261    assertNumResults(21, null);
262
263    for (TableName table: tables) {
264      admin.setQuota(QuotaSettingsFactory
265        .throttleTable(table, ThrottleType.REQUEST_NUMBER, 4, TimeUnit.MINUTES));
266    }
267    assertNumResults(24, null);
268
269    for (String ns: namespaces) {
270      admin.setQuota(QuotaSettingsFactory
271        .throttleNamespace(ns, ThrottleType.REQUEST_NUMBER, 5, TimeUnit.MINUTES));
272    }
273    assertNumResults(27, null);
274
275    assertNumResults(7, new QuotaFilter().setUserFilter("User0"));
276    assertNumResults(0, new QuotaFilter().setUserFilter("User"));
277    assertNumResults(21, new QuotaFilter().setUserFilter("User.*"));
278    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("T0"));
279    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("NS.*"));
280    assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setTableFilter("T"));
281    assertNumResults(6, new QuotaFilter().setUserFilter("User.*").setTableFilter("T.*"));
282    assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS0"));
283    assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS"));
284    assertNumResults(9, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS.*"));
285    assertNumResults(6, new QuotaFilter().setUserFilter("User.*")
286                                            .setTableFilter("T0").setNamespaceFilter("NS0"));
287    assertNumResults(1, new QuotaFilter().setTableFilter("T0"));
288    assertNumResults(0, new QuotaFilter().setTableFilter("T"));
289    assertNumResults(2, new QuotaFilter().setTableFilter("T.*"));
290    assertNumResults(3, new QuotaFilter().setTableFilter(".*T.*"));
291    assertNumResults(1, new QuotaFilter().setNamespaceFilter("NS0"));
292    assertNumResults(0, new QuotaFilter().setNamespaceFilter("NS"));
293    assertNumResults(3, new QuotaFilter().setNamespaceFilter("NS.*"));
294
295    for (String user: users) {
296      admin.setQuota(QuotaSettingsFactory.unthrottleUser(user));
297      for (TableName table: tables) {
298        admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, table));
299      }
300      for (String ns: namespaces) {
301        admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, ns));
302      }
303    }
304    assertNumResults(6, null);
305
306    for (TableName table: tables) {
307      admin.setQuota(QuotaSettingsFactory.unthrottleTable(table));
308    }
309    assertNumResults(3, null);
310
311    for (String ns: namespaces) {
312      admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(ns));
313    }
314    assertNumResults(0, null);
315  }
316
317  @Test
318  public void testSetGetRemoveSpaceQuota() throws Exception {
319    Admin admin = TEST_UTIL.getAdmin();
320    final TableName tn = TableName.valueOf("sq_table1");
321    final long sizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
322    final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_WRITES;
323    QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tn, sizeLimit, violationPolicy);
324    admin.setQuota(settings);
325
326    // Verify the Quotas in the table
327    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
328      ResultScanner scanner = quotaTable.getScanner(new Scan());
329      try {
330        Result r = Iterables.getOnlyElement(scanner);
331        CellScanner cells = r.cellScanner();
332        assertTrue("Expected to find a cell", cells.advance());
333        assertSpaceQuota(sizeLimit, violationPolicy, cells.current());
334      } finally {
335        scanner.close();
336      }
337    }
338
339    // Verify we can retrieve it via the QuotaRetriever API
340    QuotaRetriever scanner = QuotaRetriever.open(admin.getConfiguration());
341    try {
342      assertSpaceQuota(sizeLimit, violationPolicy, Iterables.getOnlyElement(scanner));
343    } finally {
344      scanner.close();
345    }
346
347    // Now, remove the quota
348    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
349    admin.setQuota(removeQuota);
350
351    // Verify that the record doesn't exist in the table
352    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
353      ResultScanner rs = quotaTable.getScanner(new Scan());
354      try {
355        assertNull("Did not expect to find a quota entry", rs.next());
356      } finally {
357        rs.close();
358      }
359    }
360
361    // Verify that we can also not fetch it via the API
362    scanner = QuotaRetriever.open(admin.getConfiguration());
363    try {
364      assertNull("Did not expect to find a quota entry", scanner.next());
365    } finally {
366      scanner.close();
367    }
368  }
369
370  @Test
371  public void testSetModifyRemoveSpaceQuota() throws Exception {
372    Admin admin = TEST_UTIL.getAdmin();
373    final TableName tn = TableName.valueOf("sq_table2");
374    final long originalSizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB
375    final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_WRITES;
376    QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tn, originalSizeLimit,
377        violationPolicy);
378    admin.setQuota(settings);
379
380    // Verify the Quotas in the table
381    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
382      ResultScanner scanner = quotaTable.getScanner(new Scan());
383      try {
384        Result r = Iterables.getOnlyElement(scanner);
385        CellScanner cells = r.cellScanner();
386        assertTrue("Expected to find a cell", cells.advance());
387        assertSpaceQuota(originalSizeLimit, violationPolicy, cells.current());
388      } finally {
389        scanner.close();
390      }
391    }
392
393    // Verify we can retrieve it via the QuotaRetriever API
394    QuotaRetriever quotaScanner = QuotaRetriever.open(admin.getConfiguration());
395    try {
396      assertSpaceQuota(originalSizeLimit, violationPolicy, Iterables.getOnlyElement(quotaScanner));
397    } finally {
398      quotaScanner.close();
399    }
400
401    // Setting a new size and policy should be reflected
402    final long newSizeLimit = 1024L * 1024L * 1024L * 1024L; // 1TB
403    final SpaceViolationPolicy newViolationPolicy = SpaceViolationPolicy.NO_WRITES_COMPACTIONS;
404    QuotaSettings newSettings = QuotaSettingsFactory.limitTableSpace(tn, newSizeLimit,
405        newViolationPolicy);
406    admin.setQuota(newSettings);
407
408    // Verify the new Quotas in the table
409    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
410      ResultScanner scanner = quotaTable.getScanner(new Scan());
411      try {
412        Result r = Iterables.getOnlyElement(scanner);
413        CellScanner cells = r.cellScanner();
414        assertTrue("Expected to find a cell", cells.advance());
415        assertSpaceQuota(newSizeLimit, newViolationPolicy, cells.current());
416      } finally {
417        scanner.close();
418      }
419    }
420
421    // Verify we can retrieve the new quota via the QuotaRetriever API
422    quotaScanner = QuotaRetriever.open(admin.getConfiguration());
423    try {
424      assertSpaceQuota(newSizeLimit, newViolationPolicy, Iterables.getOnlyElement(quotaScanner));
425    } finally {
426      quotaScanner.close();
427    }
428
429    // Now, remove the quota
430    QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn);
431    admin.setQuota(removeQuota);
432
433    // Verify that the record doesn't exist in the table
434    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
435      ResultScanner scanner = quotaTable.getScanner(new Scan());
436      try {
437        assertNull("Did not expect to find a quota entry", scanner.next());
438      } finally {
439        scanner.close();
440      }
441    }
442
443    // Verify that we can also not fetch it via the API
444    quotaScanner = QuotaRetriever.open(admin.getConfiguration());
445    try {
446      assertNull("Did not expect to find a quota entry", quotaScanner.next());
447    } finally {
448      quotaScanner.close();
449    }
450  }
451
452  private void assertNumResults(int expected, final QuotaFilter filter) throws Exception {
453    assertEquals(expected, countResults(filter));
454  }
455
456  @Test
457  public void testSetGetRemoveRPCQuota() throws Exception {
458    Admin admin = TEST_UTIL.getAdmin();
459    final TableName tn = TableName.valueOf("sq_table1");
460    QuotaSettings settings =
461        QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
462    admin.setQuota(settings);
463
464    // Verify the Quota in the table
465    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
466
467    // Verify we can retrieve it via the QuotaRetriever API
468    verifyFetchableViaAPI(admin, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
469
470    // Now, remove the quota
471    QuotaSettings removeQuota = QuotaSettingsFactory.unthrottleTable(tn);
472    admin.setQuota(removeQuota);
473
474    // Verify that the record doesn't exist in the table
475    verifyRecordNotPresentInQuotaTable();
476
477    // Verify that we can also not fetch it via the API
478    verifyNotFetchableViaAPI(admin);
479  }
480
481  @Test
482  public void testSetModifyRemoveRPCQuota() throws Exception {
483    Admin admin = TEST_UTIL.getAdmin();
484    final TableName tn = TableName.valueOf("sq_table1");
485    QuotaSettings settings =
486        QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
487    admin.setQuota(settings);
488
489    // Verify the Quota in the table
490    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
491
492    // Verify we can retrieve it via the QuotaRetriever API
493    verifyFetchableViaAPI(admin, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS);
494
495    // Setting a limit and time unit should be reflected
496    QuotaSettings newSettings =
497        QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
498    admin.setQuota(newSettings);
499
500    // Verify the new Quota in the table
501    verifyRecordPresentInQuotaTable(ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
502
503    // Verify we can retrieve the new quota via the QuotaRetriever API
504    verifyFetchableViaAPI(admin, ThrottleType.REQUEST_SIZE, 3L, TimeUnit.DAYS);
505
506    // Now, remove the quota
507    QuotaSettings removeQuota = QuotaSettingsFactory.unthrottleTable(tn);
508    admin.setQuota(removeQuota);
509
510    // Verify that the record doesn't exist in the table
511    verifyRecordNotPresentInQuotaTable();
512
513    // Verify that we can also not fetch it via the API
514    verifyNotFetchableViaAPI(admin);
515
516  }
517
518  private void verifyRecordPresentInQuotaTable(ThrottleType type, long limit, TimeUnit tu)
519      throws Exception {
520    // Verify the RPC Quotas in the table
521    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
522        ResultScanner scanner = quotaTable.getScanner(new Scan())) {
523      Result r = Iterables.getOnlyElement(scanner);
524      CellScanner cells = r.cellScanner();
525      assertTrue("Expected to find a cell", cells.advance());
526      assertRPCQuota(type, limit, tu, cells.current());
527    }
528  }
529
530  private void verifyRecordNotPresentInQuotaTable() throws Exception {
531    // Verify that the record doesn't exist in the QuotaTableUtil.QUOTA_TABLE_NAME
532    try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME);
533        ResultScanner scanner = quotaTable.getScanner(new Scan())) {
534      assertNull("Did not expect to find a quota entry", scanner.next());
535    }
536  }
537
538  private void verifyFetchableViaAPI(Admin admin, ThrottleType type, long limit, TimeUnit tu)
539      throws Exception {
540    // Verify we can retrieve the new quota via the QuotaRetriever API
541    try (QuotaRetriever quotaScanner = QuotaRetriever.open(admin.getConfiguration())) {
542      assertRPCQuota(type, limit, tu, Iterables.getOnlyElement(quotaScanner));
543    }
544  }
545
546  private void verifyNotFetchableViaAPI(Admin admin) throws Exception {
547    // Verify that we can also not fetch it via the API
548    try (QuotaRetriever quotaScanner = QuotaRetriever.open(admin.getConfiguration())) {
549      assertNull("Did not expect to find a quota entry", quotaScanner.next());
550    }
551  }
552
553  private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu, Cell cell)
554      throws Exception {
555    Quotas q = QuotaTableUtil
556        .quotasFromData(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
557    assertTrue("Quota should have rpc quota defined", q.hasThrottle());
558
559    QuotaProtos.Throttle rpcQuota = q.getThrottle();
560    QuotaProtos.TimedQuota t = null;
561
562    switch (type) {
563      case REQUEST_SIZE:
564        assertTrue(rpcQuota.hasReqSize());
565        t = rpcQuota.getReqSize();
566        break;
567      case READ_NUMBER:
568        assertTrue(rpcQuota.hasReadNum());
569        t = rpcQuota.getReadNum();
570        break;
571      case READ_SIZE:
572        assertTrue(rpcQuota.hasReadSize());
573        t = rpcQuota.getReadSize();
574        break;
575      case REQUEST_NUMBER:
576        assertTrue(rpcQuota.hasReqNum());
577        t = rpcQuota.getReqNum();
578        break;
579      case WRITE_NUMBER:
580        assertTrue(rpcQuota.hasWriteNum());
581        t = rpcQuota.getWriteNum();
582        break;
583      case WRITE_SIZE:
584        assertTrue(rpcQuota.hasWriteSize());
585        t = rpcQuota.getWriteSize();
586        break;
587    }
588
589    assertEquals(t.getSoftLimit(), limit);
590    assertEquals(t.getTimeUnit(), ProtobufUtil.toProtoTimeUnit(tu));
591  }
592
593  private void assertRPCQuota(ThrottleType type, long limit, TimeUnit tu,
594      QuotaSettings actualSettings) throws Exception {
595    assertTrue(
596        "The actual QuotaSettings was not an instance of " + ThrottleSettings.class + " but of "
597            + actualSettings.getClass(), actualSettings instanceof ThrottleSettings);
598    QuotaProtos.ThrottleRequest throttleRequest = ((ThrottleSettings) actualSettings).getProto();
599    assertEquals(limit, throttleRequest.getTimedQuota().getSoftLimit());
600    assertEquals(ProtobufUtil.toProtoTimeUnit(tu), throttleRequest.getTimedQuota().getTimeUnit());
601    assertEquals(ProtobufUtil.toProtoThrottleType(type), throttleRequest.getType());
602  }
603
604  private void assertSpaceQuota(
605      long sizeLimit, SpaceViolationPolicy violationPolicy, Cell cell) throws Exception {
606    Quotas q = QuotaTableUtil.quotasFromData(
607        cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
608    assertTrue("Quota should have space quota defined", q.hasSpace());
609    QuotaProtos.SpaceQuota spaceQuota = q.getSpace();
610    assertEquals(sizeLimit, spaceQuota.getSoftLimit());
611    assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(spaceQuota.getViolationPolicy()));
612  }
613
614  private void assertSpaceQuota(
615      long sizeLimit, SpaceViolationPolicy violationPolicy, QuotaSettings actualSettings) {
616    assertTrue("The actual QuotaSettings was not an instance of " + SpaceLimitSettings.class
617        + " but of " + actualSettings.getClass(), actualSettings instanceof SpaceLimitSettings);
618    SpaceLimitRequest spaceLimitRequest = ((SpaceLimitSettings) actualSettings).getProto();
619    assertEquals(sizeLimit, spaceLimitRequest.getQuota().getSoftLimit());
620    assertEquals(violationPolicy,
621        ProtobufUtil.toViolationPolicy(spaceLimitRequest.getQuota().getViolationPolicy()));
622  }
623
624  private int countResults(final QuotaFilter filter) throws Exception {
625    QuotaRetriever scanner = QuotaRetriever.open(TEST_UTIL.getConfiguration(), filter);
626    try {
627      int count = 0;
628      for (QuotaSettings settings: scanner) {
629        LOG.debug(Objects.toString(settings));
630        count++;
631      }
632      return count;
633    } finally {
634      scanner.close();
635    }
636  }
637}