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.ArrayList; 022import java.util.List; 023import java.util.concurrent.TimeUnit; 024 025import org.apache.hadoop.hbase.TableName; 026import org.apache.yetus.audience.InterfaceAudience; 027 028import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest; 029import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 030import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos; 031import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas; 032import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota; 033 034@InterfaceAudience.Public 035public class QuotaSettingsFactory { 036 static class QuotaGlobalsSettingsBypass extends QuotaSettings { 037 private final boolean bypassGlobals; 038 039 QuotaGlobalsSettingsBypass(final String userName, final TableName tableName, 040 final String namespace, final boolean bypassGlobals) { 041 super(userName, tableName, namespace); 042 this.bypassGlobals = bypassGlobals; 043 } 044 045 @Override 046 public QuotaType getQuotaType() { 047 return QuotaType.GLOBAL_BYPASS; 048 } 049 050 @Override 051 protected void setupSetQuotaRequest(SetQuotaRequest.Builder builder) { 052 builder.setBypassGlobals(bypassGlobals); 053 } 054 055 @Override 056 public String toString() { 057 return "GLOBAL_BYPASS => " + bypassGlobals; 058 } 059 060 protected boolean getBypass() { 061 return bypassGlobals; 062 } 063 064 @Override 065 protected QuotaGlobalsSettingsBypass merge(QuotaSettings newSettings) throws IOException { 066 if (newSettings instanceof QuotaGlobalsSettingsBypass) { 067 QuotaGlobalsSettingsBypass other = (QuotaGlobalsSettingsBypass) newSettings; 068 069 validateQuotaTarget(other); 070 071 if (getBypass() != other.getBypass()) { 072 return other; 073 } 074 } 075 return this; 076 } 077 } 078 079 /* ========================================================================== 080 * QuotaSettings from the Quotas object 081 */ 082 static List<QuotaSettings> fromUserQuotas(final String userName, final Quotas quotas) { 083 return fromQuotas(userName, null, null, quotas); 084 } 085 086 static List<QuotaSettings> fromUserQuotas(final String userName, final TableName tableName, 087 final Quotas quotas) { 088 return fromQuotas(userName, tableName, null, quotas); 089 } 090 091 static List<QuotaSettings> fromUserQuotas(final String userName, final String namespace, 092 final Quotas quotas) { 093 return fromQuotas(userName, null, namespace, quotas); 094 } 095 096 static List<QuotaSettings> fromTableQuotas(final TableName tableName, final Quotas quotas) { 097 return fromQuotas(null, tableName, null, quotas); 098 } 099 100 static List<QuotaSettings> fromNamespaceQuotas(final String namespace, final Quotas quotas) { 101 return fromQuotas(null, null, namespace, quotas); 102 } 103 104 private static List<QuotaSettings> fromQuotas(final String userName, final TableName tableName, 105 final String namespace, final Quotas quotas) { 106 List<QuotaSettings> settings = new ArrayList<>(); 107 if (quotas.hasThrottle()) { 108 settings.addAll(fromThrottle(userName, tableName, namespace, quotas.getThrottle())); 109 } 110 if (quotas.getBypassGlobals() == true) { 111 settings.add(new QuotaGlobalsSettingsBypass(userName, tableName, namespace, true)); 112 } 113 if (quotas.hasSpace()) { 114 settings.add(fromSpace(tableName, namespace, quotas.getSpace())); 115 } 116 return settings; 117 } 118 119 protected static List<QuotaSettings> fromThrottle(final String userName, final TableName tableName, 120 final String namespace, final QuotaProtos.Throttle throttle) { 121 List<QuotaSettings> settings = new ArrayList<>(); 122 if (throttle.hasReqNum()) { 123 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 124 ThrottleType.REQUEST_NUMBER, throttle.getReqNum())); 125 } 126 if (throttle.hasReqSize()) { 127 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 128 ThrottleType.REQUEST_SIZE, throttle.getReqSize())); 129 } 130 if (throttle.hasWriteNum()) { 131 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 132 ThrottleType.WRITE_NUMBER, throttle.getWriteNum())); 133 } 134 if (throttle.hasWriteSize()) { 135 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 136 ThrottleType.WRITE_SIZE, throttle.getWriteSize())); 137 } 138 if (throttle.hasReadNum()) { 139 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 140 ThrottleType.READ_NUMBER, throttle.getReadNum())); 141 } 142 if (throttle.hasReadSize()) { 143 settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace, 144 ThrottleType.READ_SIZE, throttle.getReadSize())); 145 } 146 return settings; 147 } 148 149 static QuotaSettings fromSpace(TableName table, String namespace, SpaceQuota protoQuota) { 150 if (protoQuota == null) { 151 return null; 152 } 153 if ((table == null && namespace == null) || (table != null && namespace != null)) { 154 throw new IllegalArgumentException( 155 "Can only construct SpaceLimitSettings for a table or namespace."); 156 } 157 if (table != null) { 158 if (protoQuota.getRemove()) { 159 return new SpaceLimitSettings(table); 160 } 161 return SpaceLimitSettings.fromSpaceQuota(table, protoQuota); 162 } else { 163 if (protoQuota.getRemove()) { 164 return new SpaceLimitSettings(namespace); 165 } 166 // namespace must be non-null 167 return SpaceLimitSettings.fromSpaceQuota(namespace, protoQuota); 168 } 169 } 170 171 /* ========================================================================== 172 * RPC Throttle 173 */ 174 175 /** 176 * Throttle the specified user. 177 * 178 * @param userName the user to throttle 179 * @param type the type of throttling 180 * @param limit the allowed number of request/data per timeUnit 181 * @param timeUnit the limit time unit 182 * @return the quota settings 183 */ 184 public static QuotaSettings throttleUser(final String userName, final ThrottleType type, 185 final long limit, final TimeUnit timeUnit) { 186 return throttle(userName, null, null, type, limit, timeUnit); 187 } 188 189 /** 190 * Throttle the specified user on the specified table. 191 * 192 * @param userName the user to throttle 193 * @param tableName the table to throttle 194 * @param type the type of throttling 195 * @param limit the allowed number of request/data per timeUnit 196 * @param timeUnit the limit time unit 197 * @return the quota settings 198 */ 199 public static QuotaSettings throttleUser(final String userName, final TableName tableName, 200 final ThrottleType type, final long limit, final TimeUnit timeUnit) { 201 return throttle(userName, tableName, null, type, limit, timeUnit); 202 } 203 204 /** 205 * Throttle the specified user on the specified namespace. 206 * 207 * @param userName the user to throttle 208 * @param namespace the namespace to throttle 209 * @param type the type of throttling 210 * @param limit the allowed number of request/data per timeUnit 211 * @param timeUnit the limit time unit 212 * @return the quota settings 213 */ 214 public static QuotaSettings throttleUser(final String userName, final String namespace, 215 final ThrottleType type, final long limit, final TimeUnit timeUnit) { 216 return throttle(userName, null, namespace, type, limit, timeUnit); 217 } 218 219 /** 220 * Remove the throttling for the specified user. 221 * 222 * @param userName the user 223 * @return the quota settings 224 */ 225 public static QuotaSettings unthrottleUser(final String userName) { 226 return throttle(userName, null, null, null, 0, null); 227 } 228 229 /** 230 * Remove the throttling for the specified user on the specified table. 231 * 232 * @param userName the user 233 * @param tableName the table 234 * @return the quota settings 235 */ 236 public static QuotaSettings unthrottleUser(final String userName, final TableName tableName) { 237 return throttle(userName, tableName, null, null, 0, null); 238 } 239 240 /** 241 * Remove the throttling for the specified user on the specified namespace. 242 * 243 * @param userName the user 244 * @param namespace the namespace 245 * @return the quota settings 246 */ 247 public static QuotaSettings unthrottleUser(final String userName, final String namespace) { 248 return throttle(userName, null, namespace, null, 0, null); 249 } 250 251 /** 252 * Throttle the specified table. 253 * 254 * @param tableName the table to throttle 255 * @param type the type of throttling 256 * @param limit the allowed number of request/data per timeUnit 257 * @param timeUnit the limit time unit 258 * @return the quota settings 259 */ 260 public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type, 261 final long limit, final TimeUnit timeUnit) { 262 return throttle(null, tableName, null, type, limit, timeUnit); 263 } 264 265 /** 266 * Remove the throttling for the specified table. 267 * 268 * @param tableName the table 269 * @return the quota settings 270 */ 271 public static QuotaSettings unthrottleTable(final TableName tableName) { 272 return throttle(null, tableName, null, null, 0, null); 273 } 274 275 /** 276 * Throttle the specified namespace. 277 * 278 * @param namespace the namespace to throttle 279 * @param type the type of throttling 280 * @param limit the allowed number of request/data per timeUnit 281 * @param timeUnit the limit time unit 282 * @return the quota settings 283 */ 284 public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type, 285 final long limit, final TimeUnit timeUnit) { 286 return throttle(null, null, namespace, type, limit, timeUnit); 287 } 288 289 /** 290 * Remove the throttling for the specified namespace. 291 * 292 * @param namespace the namespace 293 * @return the quota settings 294 */ 295 public static QuotaSettings unthrottleNamespace(final String namespace) { 296 return throttle(null, null, namespace, null, 0, null); 297 } 298 299 /* Throttle helper */ 300 private static QuotaSettings throttle(final String userName, final TableName tableName, 301 final String namespace, final ThrottleType type, final long limit, 302 final TimeUnit timeUnit) { 303 QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder(); 304 if (type != null) { 305 builder.setType(ProtobufUtil.toProtoThrottleType(type)); 306 } 307 if (timeUnit != null) { 308 builder.setTimedQuota(ProtobufUtil.toTimedQuota(limit, timeUnit, QuotaScope.MACHINE)); 309 } 310 return new ThrottleSettings(userName, tableName, namespace, builder.build()); 311 } 312 313 /* ========================================================================== 314 * Global Settings 315 */ 316 317 /** 318 * Set the "bypass global settings" for the specified user 319 * 320 * @param userName the user to throttle 321 * @param bypassGlobals true if the global settings should be bypassed 322 * @return the quota settings 323 */ 324 public static QuotaSettings bypassGlobals(final String userName, final boolean bypassGlobals) { 325 return new QuotaGlobalsSettingsBypass(userName, null, null, bypassGlobals); 326 } 327 328 /* ========================================================================== 329 * FileSystem Space Settings 330 */ 331 332 /** 333 * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given table 334 * to the given size in bytes. When the space usage is exceeded by the table, the provided 335 * {@link SpaceViolationPolicy} is enacted on the table. 336 * 337 * @param tableName The name of the table on which the quota should be applied. 338 * @param sizeLimit The limit of a table's size in bytes. 339 * @param violationPolicy The action to take when the quota is exceeded. 340 * @return An {@link QuotaSettings} object. 341 */ 342 public static QuotaSettings limitTableSpace( 343 final TableName tableName, long sizeLimit, final SpaceViolationPolicy violationPolicy) { 344 return new SpaceLimitSettings(tableName, sizeLimit, violationPolicy); 345 } 346 347 /** 348 * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given 349 * table. 350 * 351 * @param tableName The name of the table to remove the quota for. 352 * @return A {@link QuotaSettings} object. 353 */ 354 public static QuotaSettings removeTableSpaceLimit(TableName tableName) { 355 return new SpaceLimitSettings(tableName); 356 } 357 358 /** 359 * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given 360 * namespace to the given size in bytes. When the space usage is exceeded by all tables in the 361 * namespace, the provided {@link SpaceViolationPolicy} is enacted on all tables in the namespace. 362 * 363 * @param namespace The namespace on which the quota should be applied. 364 * @param sizeLimit The limit of the namespace's size in bytes. 365 * @param violationPolicy The action to take when the the quota is exceeded. 366 * @return An {@link QuotaSettings} object. 367 */ 368 public static QuotaSettings limitNamespaceSpace( 369 final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) { 370 return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy); 371 } 372 373 /** 374 * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given 375 * namespace. 376 * 377 * @param namespace The namespace to remove the quota on. 378 * @return A {@link QuotaSettings} object. 379 */ 380 public static QuotaSettings removeNamespaceSpaceLimit(String namespace) { 381 return new SpaceLimitSettings(namespace); 382 } 383}