QuotaState quotaInfo = new QuotaState(); assertEquals(0, quotaInfo.getLastUpdate()); assertTrue(quotaInfo.isBypass()); QuotaState otherQuotaState = new QuotaState(LAST_UPDATE_1); otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_1)); assertEquals(LAST_UPDATE_1, otherQuotaState.getLastUpdate()); assertFalse(otherQuotaState.isBypass()); quotaInfo.update(otherQuotaState); assertEquals(LAST_UPDATE_1, quotaInfo.getLastUpdate()); assertFalse(quotaInfo.isBypass()); assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_1); otherQuotaState = new QuotaState(LAST_UPDATE_2); otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_2)); assertEquals(LAST_UPDATE_2, otherQuotaState.getLastUpdate()); assertFalse(otherQuotaState.isBypass()); quotaInfo.update(otherQuotaState); assertEquals(LAST_UPDATE_2, quotaInfo.getLastUpdate()); assertFalse(quotaInfo.isBypass()); assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_2 - NUM_GLOBAL_THROTTLE_1); otherQuotaState = new QuotaState(LAST_UPDATE_3); assertEquals(LAST_UPDATE_3, otherQuotaState.getLastUpdate()); assertTrue(otherQuotaState.isBypass());
List<K> toRemove = new ArrayList<>(); for (Map.Entry<K, V> entry: quotasMap.entrySet()) { long lastUpdate = entry.getValue().getLastUpdate(); long lastQuery = entry.getValue().getLastQuery(); if (lastQuery > 0 && (now - lastQuery) >= evictPeriod) { toRemove.add(entry.getKey()); V quotaInfo = quotasMap.putIfAbsent(entry.getKey(), entry.getValue()); if (quotaInfo != null) { quotaInfo.update(entry.getValue());
@Override public synchronized String toString() { StringBuilder builder = new StringBuilder(); builder.append("QuotaState(ts=" + getLastUpdate()); if (isBypass()) { builder.append(" bypass"); } else { if (globalLimiter != NoopQuotaLimiter.get()) { //builder.append(" global-limiter"); builder.append(" " + globalLimiter); } } builder.append(')'); return builder.toString(); }
public static <K> Map<K, QuotaState> fetchGlobalQuotas(final String type, final Connection connection, final List<Get> gets, final KeyFromRow<K> kfr) throws IOException { long nowTs = EnvironmentEdgeManager.currentTime(); Result[] results = doGet(connection, gets); Map<K, QuotaState> globalQuotas = new HashMap<>(results.length); for (int i = 0; i < results.length; ++i) { byte[] row = gets.get(i).getRow(); K key = kfr.getKeyFromRow(row); QuotaState quotaInfo = new QuotaState(nowTs); globalQuotas.put(key, quotaInfo); if (results[i].isEmpty()) continue; assert Bytes.equals(row, results[i].getRow()); byte[] data = results[i].getValue(QUOTA_FAMILY_INFO, QUOTA_QUALIFIER_SETTINGS); if (data == null) continue; try { Quotas quotas = quotasFromData(data); quotaInfo.setQuotas(quotas); } catch (IOException e) { LOG.error("Unable to parse " + type + " '" + key + "' quotas", e); globalQuotas.remove(key); } } return globalQuotas; }
@Test public void testQuotaStateBypass() { QuotaState quotaInfo = new QuotaState(); assertTrue(quotaInfo.isBypass()); assertNoopLimiter(quotaInfo.getGlobalLimiter()); UserQuotaState userQuotaState = new UserQuotaState(); assertTrue(userQuotaState.isBypass()); assertNoopLimiter(userQuotaState.getTableLimiter(UNKNOWN_TABLE_NAME)); }
/** * Returns the limiter associated to the specified region server. * * @param regionServer the region server to limit * @return the limiter associated to the specified region server */ public QuotaLimiter getRegionServerQuotaLimiter(final String regionServer) { return getQuotaState(this.regionServerQuotaCache, regionServer).getGlobalLimiter(); }
@Override @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="GC_UNRELATED_TYPES", justification="I do not understand why the complaints, it looks good to me -- FIX") protected void chore() { // Prefetch online tables/namespaces for (TableName table: ((HRegionServer)QuotaCache.this.rsServices).getOnlineTables()) { if (table.isSystemTable()) continue; if (!QuotaCache.this.tableQuotaCache.containsKey(table)) { QuotaCache.this.tableQuotaCache.putIfAbsent(table, new QuotaState()); } String ns = table.getNamespaceAsString(); if (!QuotaCache.this.namespaceQuotaCache.containsKey(ns)) { QuotaCache.this.namespaceQuotaCache.putIfAbsent(ns, new QuotaState()); } } QuotaCache.this.regionServerQuotaCache.putIfAbsent(QuotaTableUtil.QUOTA_REGION_SERVER_ROW_KEY, new QuotaState()); fetchNamespaceQuotaState(); fetchTableQuotaState(); fetchUserQuotaState(); fetchRegionServerQuotaState(); lastUpdate = EnvironmentEdgeManager.currentTime(); }
@Override public synchronized void setQuotas(final Quotas quotas) { super.setQuotas(quotas); bypassGlobals = quotas.getBypassGlobals(); }
/** * Perform an update of the quota state based on the other quota state object. * (This operation is executed by the QuotaCache) */ @Override public synchronized void update(final QuotaState other) { super.update(other); if (other instanceof UserQuotaState) { UserQuotaState uOther = (UserQuotaState)other; tableLimiters = updateLimiters(tableLimiters, uOther.tableLimiters); namespaceLimiters = updateLimiters(namespaceLimiters, uOther.namespaceLimiters); bypassGlobals = uOther.bypassGlobals; } else { tableLimiters = null; namespaceLimiters = null; bypassGlobals = false; } }
/** * Return the limiter associated with this quota. * @return the quota limiter */ public synchronized QuotaLimiter getGlobalLimiter() { setLastQuery(EnvironmentEdgeManager.currentTime()); return globalLimiter; }
@Test public void testQuotaStateBypass() { QuotaState quotaInfo = new QuotaState(); assertTrue(quotaInfo.isBypass()); assertNoopLimiter(quotaInfo.getGlobalLimiter()); UserQuotaState userQuotaState = new UserQuotaState(); assertTrue(userQuotaState.isBypass()); assertNoopLimiter(userQuotaState.getTableLimiter(UNKNOWN_TABLE_NAME)); }
@Override public synchronized String toString() { StringBuilder builder = new StringBuilder(); builder.append("QuotaState(ts=" + getLastUpdate()); if (isBypass()) { builder.append(" bypass"); } else { if (globalLimiter != NoopQuotaLimiter.get()) { // builder.append(" global-limiter"); builder.append(" " + globalLimiter); } } builder.append(')'); return builder.toString(); }
public static <K> Map<K, QuotaState> fetchGlobalQuotas(final String type, final Connection connection, final List<Get> gets, final KeyFromRow<K> kfr) throws IOException { long nowTs = EnvironmentEdgeManager.currentTime(); Result[] results = doGet(connection, gets); Map<K, QuotaState> globalQuotas = new HashMap<K, QuotaState>(results.length); for (int i = 0; i < results.length; ++i) { byte[] row = gets.get(i).getRow(); K key = kfr.getKeyFromRow(row); QuotaState quotaInfo = new QuotaState(nowTs); globalQuotas.put(key, quotaInfo); if (results[i].isEmpty()) continue; assert Bytes.equals(row, results[i].getRow()); byte[] data = results[i].getValue(QUOTA_FAMILY_INFO, QUOTA_QUALIFIER_SETTINGS); if (data == null) continue; try { Quotas quotas = quotasFromData(data); quotaInfo.setQuotas(quotas); } catch (IOException e) { LOG.error("Unable to parse " + type + " '" + key + "' quotas", e); globalQuotas.remove(key); } } return globalQuotas; }
/** * Returns the limiter associated to the specified table. * * @param table the table to limit * @return the limiter associated to the specified table */ public QuotaLimiter getTableLimiter(final TableName table) { return getQuotaState(this.tableQuotaCache, table).getGlobalLimiter(); }
/** * Returns the QuotaState requested. If the quota info is not in cache an empty one will be * returned and the quota request will be enqueued for the next cache refresh. */ private <K> QuotaState getQuotaState(final ConcurrentHashMap<K, QuotaState> quotasMap, final K key) { QuotaState quotaInfo = quotasMap.get(key); if (quotaInfo == null) { quotaInfo = new QuotaState(); if (quotasMap.putIfAbsent(key, quotaInfo) == null) { triggerCacheRefresh(); } } return quotaInfo; }
@Override public synchronized void setQuotas(final Quotas quotas) { super.setQuotas(quotas); bypassGlobals = quotas.getBypassGlobals(); }
/** * Perform an update of the quota state based on the other quota state object. (This operation is * executed by the QuotaCache) */ @Override public synchronized void update(final QuotaState other) { super.update(other); if (other instanceof UserQuotaState) { UserQuotaState uOther = (UserQuotaState) other; tableLimiters = updateLimiters(tableLimiters, uOther.tableLimiters); namespaceLimiters = updateLimiters(namespaceLimiters, uOther.namespaceLimiters); bypassGlobals = uOther.bypassGlobals; } else { tableLimiters = null; namespaceLimiters = null; bypassGlobals = false; } }
QuotaState quotaInfo = new QuotaState(); assertEquals(0, quotaInfo.getLastUpdate()); assertTrue(quotaInfo.isBypass()); QuotaState otherQuotaState = new QuotaState(LAST_UPDATE_1); otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_1)); assertEquals(LAST_UPDATE_1, otherQuotaState.getLastUpdate()); assertFalse(otherQuotaState.isBypass()); quotaInfo.update(otherQuotaState); assertEquals(LAST_UPDATE_1, quotaInfo.getLastUpdate()); assertFalse(quotaInfo.isBypass()); assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_1); otherQuotaState = new QuotaState(LAST_UPDATE_2); otherQuotaState.setQuotas(buildReqNumThrottle(NUM_GLOBAL_THROTTLE_2)); assertEquals(LAST_UPDATE_2, otherQuotaState.getLastUpdate()); assertFalse(otherQuotaState.isBypass()); quotaInfo.update(otherQuotaState); assertEquals(LAST_UPDATE_2, quotaInfo.getLastUpdate()); assertFalse(quotaInfo.isBypass()); assertThrottleException(quotaInfo.getGlobalLimiter(), NUM_GLOBAL_THROTTLE_2 - NUM_GLOBAL_THROTTLE_1); otherQuotaState = new QuotaState(LAST_UPDATE_3); assertEquals(LAST_UPDATE_3, otherQuotaState.getLastUpdate()); assertTrue(otherQuotaState.isBypass());
List<K> toRemove = new ArrayList<K>(); for (Map.Entry<K, V> entry : quotasMap.entrySet()) { long lastUpdate = entry.getValue().getLastUpdate(); long lastQuery = entry.getValue().getLastQuery(); if (lastQuery > 0 && (now - lastQuery) >= evictPeriod) { toRemove.add(entry.getKey()); V quotaInfo = quotasMap.putIfAbsent(entry.getKey(), entry.getValue()); if (quotaInfo != null) { quotaInfo.update(entry.getValue());
/** * Returns the limiter associated to the specified namespace. * * @param namespace the namespace to limit * @return the limiter associated to the specified namespace */ public QuotaLimiter getNamespaceLimiter(final String namespace) { return getQuotaState(this.namespaceQuotaCache, namespace).getGlobalLimiter(); }