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 java.io.IOException; 021import java.util.concurrent.TimeUnit; 022import org.apache.hadoop.hbase.DoNotRetryIOException; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.apache.yetus.audience.InterfaceStability; 026 027import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 028import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest; 029import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos; 030import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.TimedQuota; 031 032@InterfaceAudience.Private 033@InterfaceStability.Evolving 034public class ThrottleSettings extends QuotaSettings { 035 final QuotaProtos.ThrottleRequest proto; 036 037 ThrottleSettings(final String userName, final TableName tableName, final String namespace, 038 final String regionServer, final QuotaProtos.ThrottleRequest proto) { 039 super(userName, tableName, namespace, regionServer); 040 this.proto = proto; 041 } 042 043 public ThrottleType getThrottleType() { 044 return ProtobufUtil.toThrottleType(proto.getType()); 045 } 046 047 public long getSoftLimit() { 048 return proto.hasTimedQuota() ? proto.getTimedQuota().getSoftLimit() : -1; 049 } 050 051 /** 052 * Returns a copy of the internal state of <code>this</code> 053 */ 054 QuotaProtos.ThrottleRequest getProto() { 055 return proto.toBuilder().build(); 056 } 057 058 public TimeUnit getTimeUnit() { 059 return proto.hasTimedQuota() 060 ? ProtobufUtil.toTimeUnit(proto.getTimedQuota().getTimeUnit()) 061 : null; 062 } 063 064 public QuotaScope getQuotaScope() { 065 return proto.hasTimedQuota() 066 ? ProtobufUtil.toQuotaScope(proto.getTimedQuota().getScope()) 067 : null; 068 } 069 070 @Override 071 public QuotaType getQuotaType() { 072 return QuotaType.THROTTLE; 073 } 074 075 @Override 076 protected void setupSetQuotaRequest(SetQuotaRequest.Builder builder) { 077 builder.setThrottle(proto); 078 } 079 080 @Override 081 public String toString() { 082 StringBuilder builder = new StringBuilder(); 083 builder.append("TYPE => THROTTLE"); 084 if (proto.hasType()) { 085 builder.append(", THROTTLE_TYPE => "); 086 builder.append(proto.getType().toString()); 087 } 088 if (proto.hasTimedQuota()) { 089 QuotaProtos.TimedQuota timedQuota = proto.getTimedQuota(); 090 builder.append(", LIMIT => "); 091 if (timedQuota.hasSoftLimit()) { 092 switch (getThrottleType()) { 093 case REQUEST_NUMBER: 094 case WRITE_NUMBER: 095 case READ_NUMBER: 096 case ATOMIC_REQUEST_NUMBER: 097 builder.append(String.format("%dreq", timedQuota.getSoftLimit())); 098 break; 099 case REQUEST_SIZE: 100 case WRITE_SIZE: 101 case READ_SIZE: 102 case ATOMIC_READ_SIZE: 103 case ATOMIC_WRITE_SIZE: 104 builder.append(sizeToString(timedQuota.getSoftLimit())); 105 break; 106 case REQUEST_CAPACITY_UNIT: 107 case READ_CAPACITY_UNIT: 108 case WRITE_CAPACITY_UNIT: 109 builder.append(String.format("%dCU", timedQuota.getSoftLimit())); 110 break; 111 case REQUEST_HANDLER_USAGE_MS: 112 builder.append(String.format("%dms", timedQuota.getSoftLimit())); 113 break; 114 default: 115 } 116 } else if (timedQuota.hasShare()) { 117 builder.append(String.format("%.2f%%", timedQuota.getShare())); 118 } 119 builder.append('/'); 120 builder.append(timeToString(ProtobufUtil.toTimeUnit(timedQuota.getTimeUnit()))); 121 if (timedQuota.hasScope()) { 122 builder.append(", SCOPE => "); 123 builder.append(timedQuota.getScope().toString()); 124 } 125 } else { 126 builder.append(", LIMIT => NONE"); 127 } 128 return builder.toString(); 129 } 130 131 @Override 132 protected ThrottleSettings merge(QuotaSettings other) throws IOException { 133 if (other instanceof ThrottleSettings) { 134 ThrottleSettings otherThrottle = (ThrottleSettings) other; 135 136 // Make sure this and the other target the same "subject" 137 validateQuotaTarget(other); 138 139 QuotaProtos.ThrottleRequest.Builder builder = proto.toBuilder(); 140 if (!otherThrottle.proto.hasType()) { 141 return null; 142 } 143 144 QuotaProtos.ThrottleRequest otherProto = otherThrottle.proto; 145 if (otherProto.hasTimedQuota()) { 146 if (otherProto.hasTimedQuota()) { 147 validateTimedQuota(otherProto.getTimedQuota()); 148 } 149 150 if (!proto.getType().equals(otherProto.getType())) { 151 throw new IllegalArgumentException("Cannot merge a ThrottleRequest for " + proto.getType() 152 + " with " + otherProto.getType()); 153 } 154 QuotaProtos.TimedQuota.Builder timedQuotaBuilder = proto.getTimedQuota().toBuilder(); 155 timedQuotaBuilder.mergeFrom(otherProto.getTimedQuota()); 156 157 QuotaProtos.ThrottleRequest mergedReq = 158 builder.setTimedQuota(timedQuotaBuilder.build()).build(); 159 return new ThrottleSettings(getUserName(), getTableName(), getNamespace(), 160 getRegionServer(), mergedReq); 161 } 162 } 163 return this; 164 } 165 166 private void validateTimedQuota(final TimedQuota timedQuota) throws IOException { 167 if (timedQuota.getSoftLimit() < 1) { 168 throw new DoNotRetryIOException(new UnsupportedOperationException( 169 "The throttle limit must be greater then 0, got " + timedQuota.getSoftLimit())); 170 } 171 } 172 173 static ThrottleSettings fromTimedQuota(final String userName, final TableName tableName, 174 final String namespace, final String regionServer, ThrottleType type, 175 QuotaProtos.TimedQuota timedQuota) { 176 QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder(); 177 builder.setType(ProtobufUtil.toProtoThrottleType(type)); 178 builder.setTimedQuota(timedQuota); 179 return new ThrottleSettings(userName, tableName, namespace, regionServer, builder.build()); 180 } 181}