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 org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 021import org.apache.yetus.audience.InterfaceAudience; 022import org.apache.yetus.audience.InterfaceStability; 023 024import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas; 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 /** Returns true if there is no quota information associated to this object */ 073 public synchronized boolean isBypass() { 074 return globalLimiter == NoopQuotaLimiter.get(); 075 } 076 077 /** 078 * Setup the global quota information. (This operation is part of the QuotaState setup) 079 */ 080 public synchronized void setQuotas(final Quotas quotas) { 081 if (quotas.hasThrottle()) { 082 globalLimiter = QuotaLimiterFactory.fromThrottle(quotas.getThrottle()); 083 } else { 084 globalLimiter = NoopQuotaLimiter.get(); 085 } 086 } 087 088 /** 089 * Perform an update of the quota info based on the other quota info object. (This operation is 090 * executed by the QuotaCache) 091 */ 092 public synchronized void update(final QuotaState other) { 093 if (globalLimiter == NoopQuotaLimiter.get()) { 094 globalLimiter = other.globalLimiter; 095 } else if (other.globalLimiter == NoopQuotaLimiter.get()) { 096 globalLimiter = NoopQuotaLimiter.get(); 097 } else { 098 globalLimiter = QuotaLimiterFactory.update(globalLimiter, other.globalLimiter); 099 } 100 lastUpdate = other.lastUpdate; 101 } 102 103 /** 104 * Return the limiter associated with this quota. 105 * @return the quota limiter 106 */ 107 public synchronized QuotaLimiter getGlobalLimiter() { 108 lastQuery = EnvironmentEdgeManager.currentTime(); 109 return globalLimiter; 110 } 111 112 /** 113 * Return the limiter associated with this quota without updating internal last query stats 114 * @return the quota limiter 115 */ 116 synchronized QuotaLimiter getGlobalLimiterWithoutUpdatingLastQuery() { 117 return globalLimiter; 118 } 119}