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 builder.append(String.format("%dreq", timedQuota.getSoftLimit())); 097 break; 098 case REQUEST_SIZE: 099 case WRITE_SIZE: 100 case READ_SIZE: 101 builder.append(sizeToString(timedQuota.getSoftLimit())); 102 break; 103 case REQUEST_CAPACITY_UNIT: 104 case READ_CAPACITY_UNIT: 105 case WRITE_CAPACITY_UNIT: 106 builder.append(String.format("%dCU", timedQuota.getSoftLimit())); 107 break; 108 default: 109 } 110 } else if (timedQuota.hasShare()) { 111 builder.append(String.format("%.2f%%", timedQuota.getShare())); 112 } 113 builder.append('/'); 114 builder.append(timeToString(ProtobufUtil.toTimeUnit(timedQuota.getTimeUnit()))); 115 if (timedQuota.hasScope()) { 116 builder.append(", SCOPE => "); 117 builder.append(timedQuota.getScope().toString()); 118 } 119 } else { 120 builder.append(", LIMIT => NONE"); 121 } 122 return builder.toString(); 123 } 124 125 @Override 126 protected ThrottleSettings merge(QuotaSettings other) throws IOException { 127 if (other instanceof ThrottleSettings) { 128 ThrottleSettings otherThrottle = (ThrottleSettings) other; 129 130 // Make sure this and the other target the same "subject" 131 validateQuotaTarget(other); 132 133 QuotaProtos.ThrottleRequest.Builder builder = proto.toBuilder(); 134 if (!otherThrottle.proto.hasType()) { 135 return null; 136 } 137 138 QuotaProtos.ThrottleRequest otherProto = otherThrottle.proto; 139 if (otherProto.hasTimedQuota()) { 140 if (otherProto.hasTimedQuota()) { 141 validateTimedQuota(otherProto.getTimedQuota()); 142 } 143 144 if (!proto.getType().equals(otherProto.getType())) { 145 throw new IllegalArgumentException("Cannot merge a ThrottleRequest for " + proto.getType() 146 + " with " + otherProto.getType()); 147 } 148 QuotaProtos.TimedQuota.Builder timedQuotaBuilder = proto.getTimedQuota().toBuilder(); 149 timedQuotaBuilder.mergeFrom(otherProto.getTimedQuota()); 150 151 QuotaProtos.ThrottleRequest mergedReq = 152 builder.setTimedQuota(timedQuotaBuilder.build()).build(); 153 return new ThrottleSettings(getUserName(), getTableName(), getNamespace(), 154 getRegionServer(), mergedReq); 155 } 156 } 157 return this; 158 } 159 160 private void validateTimedQuota(final TimedQuota timedQuota) throws IOException { 161 if (timedQuota.getSoftLimit() < 1) { 162 throw new DoNotRetryIOException(new UnsupportedOperationException( 163 "The throttle limit must be greater then 0, got " + timedQuota.getSoftLimit())); 164 } 165 } 166 167 static ThrottleSettings fromTimedQuota(final String userName, final TableName tableName, 168 final String namespace, final String regionServer, ThrottleType type, 169 QuotaProtos.TimedQuota timedQuota) { 170 QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder(); 171 builder.setType(ProtobufUtil.toProtoThrottleType(type)); 172 builder.setTimedQuota(timedQuota); 173 return new ThrottleSettings(userName, tableName, namespace, regionServer, builder.build()); 174 } 175}