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()) : null; 061 } 062 063 public QuotaScope getQuotaScope() { 064 return proto.hasTimedQuota() ? ProtobufUtil.toQuotaScope(proto.getTimedQuota().getScope()) 065 : null; 066 } 067 068 @Override 069 public QuotaType getQuotaType() { 070 return QuotaType.THROTTLE; 071 } 072 073 @Override 074 protected void setupSetQuotaRequest(SetQuotaRequest.Builder builder) { 075 builder.setThrottle(proto); 076 } 077 078 @Override 079 public String toString() { 080 StringBuilder builder = new StringBuilder(); 081 builder.append("TYPE => THROTTLE"); 082 if (proto.hasType()) { 083 builder.append(", THROTTLE_TYPE => "); 084 builder.append(proto.getType().toString()); 085 } 086 if (proto.hasTimedQuota()) { 087 QuotaProtos.TimedQuota timedQuota = proto.getTimedQuota(); 088 builder.append(", LIMIT => "); 089 if (timedQuota.hasSoftLimit()) { 090 switch (getThrottleType()) { 091 case REQUEST_NUMBER: 092 case WRITE_NUMBER: 093 case READ_NUMBER: 094 builder.append(String.format("%dreq", timedQuota.getSoftLimit())); 095 break; 096 case REQUEST_SIZE: 097 case WRITE_SIZE: 098 case READ_SIZE: 099 builder.append(sizeToString(timedQuota.getSoftLimit())); 100 break; 101 case REQUEST_CAPACITY_UNIT: 102 case READ_CAPACITY_UNIT: 103 case WRITE_CAPACITY_UNIT: 104 builder.append(String.format("%dCU", timedQuota.getSoftLimit())); 105 break; 106 default: 107 } 108 } else if (timedQuota.hasShare()) { 109 builder.append(String.format("%.2f%%", timedQuota.getShare())); 110 } 111 builder.append('/'); 112 builder.append(timeToString(ProtobufUtil.toTimeUnit(timedQuota.getTimeUnit()))); 113 if (timedQuota.hasScope()) { 114 builder.append(", SCOPE => "); 115 builder.append(timedQuota.getScope().toString()); 116 } 117 } else { 118 builder.append(", LIMIT => NONE"); 119 } 120 return builder.toString(); 121 } 122 123 @Override 124 protected ThrottleSettings merge(QuotaSettings other) throws IOException { 125 if (other instanceof ThrottleSettings) { 126 ThrottleSettings otherThrottle = (ThrottleSettings) other; 127 128 // Make sure this and the other target the same "subject" 129 validateQuotaTarget(other); 130 131 QuotaProtos.ThrottleRequest.Builder builder = proto.toBuilder(); 132 if (!otherThrottle.proto.hasType()) { 133 return null; 134 } 135 136 QuotaProtos.ThrottleRequest otherProto = otherThrottle.proto; 137 if (otherProto.hasTimedQuota()) { 138 if (otherProto.hasTimedQuota()) { 139 validateTimedQuota(otherProto.getTimedQuota()); 140 } 141 142 if (!proto.getType().equals(otherProto.getType())) { 143 throw new IllegalArgumentException( 144 "Cannot merge a ThrottleRequest for " + proto.getType() + " with " + 145 otherProto.getType()); 146 } 147 QuotaProtos.TimedQuota.Builder timedQuotaBuilder = proto.getTimedQuota().toBuilder(); 148 timedQuotaBuilder.mergeFrom(otherProto.getTimedQuota()); 149 150 QuotaProtos.ThrottleRequest mergedReq = builder.setTimedQuota( 151 timedQuotaBuilder.build()).build(); 152 return new ThrottleSettings(getUserName(), getTableName(), getNamespace(), 153 getRegionServer(), mergedReq); 154 } 155 } 156 return this; 157 } 158 159 private void validateTimedQuota(final TimedQuota timedQuota) throws IOException { 160 if (timedQuota.getSoftLimit() < 1) { 161 throw new DoNotRetryIOException(new UnsupportedOperationException( 162 "The throttle limit must be greater then 0, got " + timedQuota.getSoftLimit())); 163 } 164 } 165 166 static ThrottleSettings fromTimedQuota(final String userName, final TableName tableName, 167 final String namespace, final String regionServer, ThrottleType type, 168 QuotaProtos.TimedQuota timedQuota) { 169 QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder(); 170 builder.setType(ProtobufUtil.toProtoThrottleType(type)); 171 builder.setTimedQuota(timedQuota); 172 return new ThrottleSettings(userName, tableName, namespace, regionServer, builder.build()); 173 } 174}