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.client; 019 020import static org.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.fail; 023 024import java.util.Objects; 025import java.util.concurrent.TimeUnit; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HConstants; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.quotas.QuotaCache; 030import org.apache.hadoop.hbase.quotas.QuotaFilter; 031import org.apache.hadoop.hbase.quotas.QuotaSettings; 032import org.apache.hadoop.hbase.quotas.QuotaSettingsFactory; 033import org.apache.hadoop.hbase.quotas.QuotaTableUtil; 034import org.apache.hadoop.hbase.quotas.QuotaUtil; 035import org.apache.hadoop.hbase.quotas.ThrottleType; 036import org.apache.hadoop.hbase.security.User; 037import org.apache.hadoop.hbase.testclassification.ClientTests; 038import org.apache.hadoop.hbase.testclassification.MediumTests; 039import org.junit.BeforeClass; 040import org.junit.ClassRule; 041import org.junit.Test; 042import org.junit.experimental.categories.Category; 043import org.junit.runner.RunWith; 044import org.junit.runners.Parameterized; 045 046@RunWith(Parameterized.class) 047@Category({ ClientTests.class, MediumTests.class }) 048public class TestAsyncQuotaAdminApi extends TestAsyncAdminBase { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestAsyncQuotaAdminApi.class); 053 054 @BeforeClass 055 public static void setUpBeforeClass() throws Exception { 056 TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true); 057 TEST_UTIL.getConfiguration().setInt(QuotaCache.REFRESH_CONF_KEY, 2000); 058 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 60000); 059 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, 120000); 060 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2); 061 TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); 062 TEST_UTIL.startMiniCluster(1); 063 TEST_UTIL.waitTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME); 064 ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); 065 } 066 067 @Test 068 public void testThrottleType() throws Exception { 069 String userName = User.getCurrent().getShortName(); 070 071 admin.setQuota( 072 QuotaSettingsFactory.throttleUser(userName, ThrottleType.READ_NUMBER, 6, TimeUnit.MINUTES)) 073 .get(); 074 admin.setQuota( 075 QuotaSettingsFactory.throttleUser(userName, ThrottleType.WRITE_NUMBER, 12, TimeUnit.MINUTES)) 076 .get(); 077 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, true)).get(); 078 079 int countThrottle = 0; 080 int countGlobalBypass = 0; 081 for (QuotaSettings settings : admin.getQuota(null).get()) { 082 switch (settings.getQuotaType()) { 083 case THROTTLE: 084 countThrottle++; 085 break; 086 case GLOBAL_BYPASS: 087 countGlobalBypass++; 088 break; 089 default: 090 fail("unexpected settings type: " + settings.getQuotaType()); 091 } 092 } 093 assertEquals(2, countThrottle); 094 assertEquals(1, countGlobalBypass); 095 096 admin.setQuota(QuotaSettingsFactory.unthrottleUser(userName)).get(); 097 assertNumResults(1, null); 098 admin.setQuota(QuotaSettingsFactory.bypassGlobals(userName, false)).get(); 099 assertNumResults(0, null); 100 } 101 102 @Test 103 public void testQuotaRetrieverFilter() throws Exception { 104 TableName[] tables = new TableName[] { TableName.valueOf("T0"), TableName.valueOf("T01"), 105 TableName.valueOf("NS0:T2"), }; 106 String[] namespaces = new String[] { "NS0", "NS01", "NS2" }; 107 String[] users = new String[] { "User0", "User01", "User2" }; 108 109 for (String user : users) { 110 admin.setQuota( 111 QuotaSettingsFactory.throttleUser(user, ThrottleType.REQUEST_NUMBER, 1, TimeUnit.MINUTES)) 112 .get(); 113 114 for (TableName table : tables) { 115 admin.setQuota(QuotaSettingsFactory.throttleUser(user, table, ThrottleType.REQUEST_NUMBER, 116 2, TimeUnit.MINUTES)).get(); 117 } 118 119 for (String ns : namespaces) { 120 admin.setQuota(QuotaSettingsFactory.throttleUser(user, ns, ThrottleType.REQUEST_NUMBER, 3, 121 TimeUnit.MINUTES)).get(); 122 } 123 } 124 assertNumResults(21, null); 125 126 for (TableName table : tables) { 127 admin.setQuota( 128 QuotaSettingsFactory.throttleTable(table, ThrottleType.REQUEST_NUMBER, 4, TimeUnit.MINUTES)) 129 .get(); 130 } 131 assertNumResults(24, null); 132 133 for (String ns : namespaces) { 134 admin.setQuota(QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_NUMBER, 5, 135 TimeUnit.MINUTES)).get(); 136 } 137 assertNumResults(27, null); 138 139 assertNumResults(7, new QuotaFilter().setUserFilter("User0")); 140 assertNumResults(0, new QuotaFilter().setUserFilter("User")); 141 assertNumResults(21, new QuotaFilter().setUserFilter("User.*")); 142 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("T0")); 143 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setTableFilter("NS.*")); 144 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setTableFilter("T")); 145 assertNumResults(6, new QuotaFilter().setUserFilter("User.*").setTableFilter("T.*")); 146 assertNumResults(3, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS0")); 147 assertNumResults(0, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS")); 148 assertNumResults(9, new QuotaFilter().setUserFilter("User.*").setNamespaceFilter("NS.*")); 149 assertNumResults(6, 150 new QuotaFilter().setUserFilter("User.*").setTableFilter("T0").setNamespaceFilter("NS0")); 151 assertNumResults(1, new QuotaFilter().setTableFilter("T0")); 152 assertNumResults(0, new QuotaFilter().setTableFilter("T")); 153 assertNumResults(2, new QuotaFilter().setTableFilter("T.*")); 154 assertNumResults(3, new QuotaFilter().setTableFilter(".*T.*")); 155 assertNumResults(1, new QuotaFilter().setNamespaceFilter("NS0")); 156 assertNumResults(0, new QuotaFilter().setNamespaceFilter("NS")); 157 assertNumResults(3, new QuotaFilter().setNamespaceFilter("NS.*")); 158 159 for (String user : users) { 160 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user)).get(); 161 for (TableName table : tables) { 162 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, table)).get(); 163 } 164 for (String ns : namespaces) { 165 admin.setQuota(QuotaSettingsFactory.unthrottleUser(user, ns)).get(); 166 } 167 } 168 assertNumResults(6, null); 169 170 for (TableName table : tables) { 171 admin.setQuota(QuotaSettingsFactory.unthrottleTable(table)).get(); 172 } 173 assertNumResults(3, null); 174 175 for (String ns : namespaces) { 176 admin.setQuota(QuotaSettingsFactory.unthrottleNamespace(ns)).get(); 177 } 178 assertNumResults(0, null); 179 } 180 181 private void assertNumResults(int expected, final QuotaFilter filter) throws Exception { 182 assertEquals(expected, countResults(filter)); 183 } 184 185 private int countResults(final QuotaFilter filter) throws Exception { 186 int count = 0; 187 for (QuotaSettings settings : admin.getQuota(filter).get()) { 188 LOG.debug(Objects.toString(settings)); 189 count++; 190 } 191 return count; 192 } 193}