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 */ 018 019package org.apache.hadoop.hbase.quotas; 020 021import org.apache.yetus.audience.InterfaceAudience; 022import org.apache.yetus.audience.InterfaceStability; 023import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas; 024import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 025 026/** 027 * In-Memory state of table or namespace quotas 028 */ 029@InterfaceAudience.Private 030@InterfaceStability.Evolving 031@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="IS2_INCONSISTENT_SYNC", 032 justification="FindBugs seems confused; says globalLimiter and lastUpdate " + 033 "are mostly synchronized...but to me it looks like they are totally synchronized") 034public class QuotaState { 035 protected long lastUpdate = 0; 036 protected long lastQuery = 0; 037 038 protected QuotaLimiter globalLimiter = NoopQuotaLimiter.get(); 039 040 public QuotaState() { 041 this(0); 042 } 043 044 public QuotaState(final long updateTs) { 045 lastUpdate = updateTs; 046 } 047 048 public synchronized long getLastUpdate() { 049 return lastUpdate; 050 } 051 052 public synchronized long getLastQuery() { 053 return lastQuery; 054 } 055 056 @Override 057 public synchronized String toString() { 058 StringBuilder builder = new StringBuilder(); 059 builder.append("QuotaState(ts=" + getLastUpdate()); 060 if (isBypass()) { 061 builder.append(" bypass"); 062 } else { 063 if (globalLimiter != NoopQuotaLimiter.get()) { 064 //builder.append(" global-limiter"); 065 builder.append(" " + globalLimiter); 066 } 067 } 068 builder.append(')'); 069 return builder.toString(); 070 } 071 072 /** 073 * @return true if there is no quota information associated to this object 074 */ 075 public synchronized boolean isBypass() { 076 return globalLimiter == NoopQuotaLimiter.get(); 077 } 078 079 /** 080 * Setup the global quota information. 081 * (This operation is part of the QuotaState setup) 082 */ 083 public synchronized void setQuotas(final Quotas quotas) { 084 if (quotas.hasThrottle()) { 085 globalLimiter = QuotaLimiterFactory.fromThrottle(quotas.getThrottle()); 086 } else { 087 globalLimiter = NoopQuotaLimiter.get(); 088 } 089 } 090 091 /** 092 * Perform an update of the quota info based on the other quota info object. 093 * (This operation is executed by the QuotaCache) 094 */ 095 public synchronized void update(final QuotaState other) { 096 if (globalLimiter == NoopQuotaLimiter.get()) { 097 globalLimiter = other.globalLimiter; 098 } else if (other.globalLimiter == NoopQuotaLimiter.get()) { 099 globalLimiter = NoopQuotaLimiter.get(); 100 } else { 101 globalLimiter = QuotaLimiterFactory.update(globalLimiter, other.globalLimiter); 102 } 103 lastUpdate = other.lastUpdate; 104 } 105 106 /** 107 * Return the limiter associated with this quota. 108 * @return the quota limiter 109 */ 110 public synchronized QuotaLimiter getGlobalLimiter() { 111 lastQuery = EnvironmentEdgeManager.currentTime(); 112 return globalLimiter; 113 } 114 115 /** 116 * Return the limiter associated with this quota without updating internal last query stats 117 * @return the quota limiter 118 */ 119 synchronized QuotaLimiter getGlobalLimiterWithoutUpdatingLastQuery() { 120 return globalLimiter; 121 } 122}