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;
021
022import java.util.concurrent.TimeUnit;
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.HBaseTestingUtil;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.Admin;
027import org.apache.hadoop.hbase.testclassification.MediumTests;
028import org.apache.hadoop.hbase.testclassification.RegionServerTests;
029import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
030import org.apache.hadoop.security.UserGroupInformation;
031import org.junit.After;
032import org.junit.Before;
033import org.junit.ClassRule;
034import org.junit.Test;
035import org.junit.experimental.categories.Category;
036
037@Category({ RegionServerTests.class, MediumTests.class })
038public class TestQuotaCache {
039
040  @ClassRule
041  public static final HBaseClassTestRule CLASS_RULE =
042    HBaseClassTestRule.forClass(TestQuotaCache.class);
043
044  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
045  private static final int REFRESH_TIME_MS = 1000;
046
047  @After
048  public void tearDown() throws Exception {
049    ThrottleQuotaTestUtil.clearQuotaCache(TEST_UTIL);
050    EnvironmentEdgeManager.reset();
051    TEST_UTIL.shutdownMiniCluster();
052  }
053
054  @Before
055  public void setUp() throws Exception {
056    TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
057    TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, REFRESH_TIME_MS);
058    TEST_UTIL.getConfiguration().setInt(QuotaUtil.QUOTA_DEFAULT_USER_MACHINE_READ_NUM, 1000);
059
060    TEST_UTIL.startMiniCluster(1);
061    TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
062  }
063
064  @Test
065  public void testUserQuotaLookup() throws Exception {
066    QuotaCache quotaCache =
067      ThrottleQuotaTestUtil.getQuotaCaches(TEST_UTIL).stream().findAny().get();
068    final Admin admin = TEST_UTIL.getAdmin();
069    admin.setQuota(QuotaSettingsFactory.throttleUser("my_user", ThrottleType.READ_NUMBER, 3737,
070      TimeUnit.MINUTES));
071
072    // Setting a quota and then looking it up from the cache should work, even if the cache has not
073    // refreshed
074    UserGroupInformation ugi = UserGroupInformation.createRemoteUser("my_user");
075    QuotaLimiter quotaLimiter = quotaCache.getUserLimiter(ugi, TableName.valueOf("my_table"));
076    assertEquals(3737, quotaLimiter.getReadNumLimit());
077
078    // if no specific user quota, fall back to default
079    ugi = UserGroupInformation.createRemoteUser("my_user2");
080    quotaLimiter = quotaCache.getUserLimiter(ugi, TableName.valueOf("my_table"));
081    assertEquals(1000, quotaLimiter.getReadNumLimit());
082
083    // still works after refresh
084    quotaCache.forceSynchronousCacheRefresh();
085    ugi = UserGroupInformation.createRemoteUser("my_user");
086    quotaLimiter = quotaCache.getUserLimiter(ugi, TableName.valueOf("my_table"));
087    assertEquals(3737, quotaLimiter.getReadNumLimit());
088
089    ugi = UserGroupInformation.createRemoteUser("my_user2");
090    quotaLimiter = quotaCache.getUserLimiter(ugi, TableName.valueOf("my_table"));
091    assertEquals(1000, quotaLimiter.getReadNumLimit());
092  }
093
094  @Test
095  public void testTableQuotaLookup() throws Exception {
096    QuotaCache quotaCache =
097      ThrottleQuotaTestUtil.getQuotaCaches(TEST_UTIL).stream().findAny().get();
098    final Admin admin = TEST_UTIL.getAdmin();
099    admin.setQuota(QuotaSettingsFactory.throttleTable(TableName.valueOf("my_table"),
100      ThrottleType.READ_NUMBER, 3737, TimeUnit.MINUTES));
101
102    // Setting a quota and then looking it up from the cache should work, even if the cache has not
103    // refreshed
104    QuotaLimiter quotaLimiter = quotaCache.getTableLimiter(TableName.valueOf("my_table"));
105    assertEquals(3737, quotaLimiter.getReadNumLimit());
106
107    // if no specific table quota, fall back to default
108    quotaLimiter = quotaCache.getTableLimiter(TableName.valueOf("my_table2"));
109    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
110
111    // still works after refresh
112    quotaCache.forceSynchronousCacheRefresh();
113    quotaLimiter = quotaCache.getTableLimiter(TableName.valueOf("my_table"));
114    assertEquals(3737, quotaLimiter.getReadNumLimit());
115
116    quotaLimiter = quotaCache.getTableLimiter(TableName.valueOf("my_table2"));
117    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
118  }
119
120  @Test
121  public void testNamespaceQuotaLookup() throws Exception {
122    QuotaCache quotaCache =
123      ThrottleQuotaTestUtil.getQuotaCaches(TEST_UTIL).stream().findAny().get();
124    final Admin admin = TEST_UTIL.getAdmin();
125    admin.setQuota(QuotaSettingsFactory.throttleNamespace("my_namespace", ThrottleType.READ_NUMBER,
126      3737, TimeUnit.MINUTES));
127
128    // Setting a quota and then looking it up from the cache should work, even if the cache has not
129    // refreshed
130    QuotaLimiter quotaLimiter = quotaCache.getNamespaceLimiter("my_namespace");
131    assertEquals(3737, quotaLimiter.getReadNumLimit());
132
133    // if no specific namespace quota, fall back to default
134    quotaLimiter = quotaCache.getNamespaceLimiter("my_namespace2");
135    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
136
137    // still works after refresh
138    quotaCache.forceSynchronousCacheRefresh();
139    quotaLimiter = quotaCache.getNamespaceLimiter("my_namespace");
140    assertEquals(3737, quotaLimiter.getReadNumLimit());
141
142    quotaLimiter = quotaCache.getNamespaceLimiter("my_namespace2");
143    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
144  }
145
146  @Test
147  public void testRegionServerQuotaLookup() throws Exception {
148    QuotaCache quotaCache =
149      ThrottleQuotaTestUtil.getQuotaCaches(TEST_UTIL).stream().findAny().get();
150    final Admin admin = TEST_UTIL.getAdmin();
151    admin.setQuota(QuotaSettingsFactory.throttleRegionServer("my_region_server",
152      ThrottleType.READ_NUMBER, 3737, TimeUnit.MINUTES));
153
154    // Setting a quota and then looking it up from the cache should work, even if the cache has not
155    // refreshed
156    QuotaLimiter quotaLimiter = quotaCache.getRegionServerQuotaLimiter("my_region_server");
157    assertEquals(3737, quotaLimiter.getReadNumLimit());
158
159    // if no specific server quota, fall back to default
160    quotaLimiter = quotaCache.getRegionServerQuotaLimiter("my_region_server2");
161    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
162
163    // still works after refresh
164    quotaCache.forceSynchronousCacheRefresh();
165    quotaLimiter = quotaCache.getRegionServerQuotaLimiter("my_region_server");
166    assertEquals(3737, quotaLimiter.getReadNumLimit());
167
168    quotaLimiter = quotaCache.getRegionServerQuotaLimiter("my_region_server2");
169    assertEquals(Long.MAX_VALUE, quotaLimiter.getReadNumLimit());
170  }
171}