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.util.regex.Matcher; 021import java.util.regex.Pattern; 022import org.apache.hadoop.hbase.HBaseIOException; 023import org.apache.yetus.audience.InterfaceAudience; 024 025/** 026 * Describe the throttling result. TODO: At some point this will be handled on the client side to 027 * prevent operation to go on the server if the waitInterval is greater than the one got as result 028 * of this exception. 029 */ 030@InterfaceAudience.Public 031public class RpcThrottlingException extends HBaseIOException { 032 033 @InterfaceAudience.Public 034 public enum Type { 035 NumRequestsExceeded, 036 RequestSizeExceeded, 037 NumReadRequestsExceeded, 038 NumWriteRequestsExceeded, 039 WriteSizeExceeded, 040 ReadSizeExceeded, 041 RequestCapacityUnitExceeded, 042 ReadCapacityUnitExceeded, 043 WriteCapacityUnitExceeded, 044 AtomicRequestNumberExceeded, 045 AtomicReadSizeExceeded, 046 AtomicWriteSizeExceeded, 047 RequestHandlerUsageTimeExceeded, 048 } 049 050 private static final String[] MSG_TYPE = new String[] { "number of requests exceeded", 051 "request size limit exceeded", "number of read requests exceeded", 052 "number of write requests exceeded", "write size limit exceeded", "read size limit exceeded", 053 "request capacity unit exceeded", "read capacity unit exceeded", "write capacity unit exceeded", 054 "atomic request number exceeded", "atomic read size exceeded", "atomic write size exceeded", 055 "request handler usage time exceeded" }; 056 057 private static final String MSG_WAIT = " - wait "; 058 059 private long waitInterval; 060 private Type type; 061 062 public RpcThrottlingException(String msg) { 063 super(msg); 064 065 // Dirty workaround to get the information after 066 // ((RemoteException)e.getCause()).unwrapRemoteException() 067 for (int i = 0; i < MSG_TYPE.length; ++i) { 068 int index = msg.indexOf(MSG_TYPE[i]); 069 if (index >= 0) { 070 String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length()); 071 type = Type.values()[i]; 072 waitInterval = timeFromString(waitTimeStr); 073 break; 074 } 075 } 076 } 077 078 public RpcThrottlingException(final Type type, final long waitInterval, final String msg) { 079 super(msg); 080 this.waitInterval = waitInterval; 081 this.type = type; 082 } 083 084 public Type getType() { 085 return this.type; 086 } 087 088 public long getWaitInterval() { 089 return this.waitInterval; 090 } 091 092 public static void throwNumRequestsExceeded(final long waitInterval) 093 throws RpcThrottlingException { 094 throwThrottlingException(Type.NumRequestsExceeded, waitInterval); 095 } 096 097 public static void throwRequestSizeExceeded(final long waitInterval) 098 throws RpcThrottlingException { 099 throwThrottlingException(Type.RequestSizeExceeded, waitInterval); 100 } 101 102 public static void throwNumReadRequestsExceeded(final long waitInterval) 103 throws RpcThrottlingException { 104 throwThrottlingException(Type.NumReadRequestsExceeded, waitInterval); 105 } 106 107 public static void throwNumWriteRequestsExceeded(final long waitInterval) 108 throws RpcThrottlingException { 109 throwThrottlingException(Type.NumWriteRequestsExceeded, waitInterval); 110 } 111 112 public static void throwWriteSizeExceeded(final long waitInterval) throws RpcThrottlingException { 113 throwThrottlingException(Type.WriteSizeExceeded, waitInterval); 114 } 115 116 public static void throwReadSizeExceeded(final long waitInterval) throws RpcThrottlingException { 117 throwThrottlingException(Type.ReadSizeExceeded, waitInterval); 118 } 119 120 public static void throwRequestCapacityUnitExceeded(final long waitInterval) 121 throws RpcThrottlingException { 122 throwThrottlingException(Type.RequestCapacityUnitExceeded, waitInterval); 123 } 124 125 public static void throwReadCapacityUnitExceeded(final long waitInterval) 126 throws RpcThrottlingException { 127 throwThrottlingException(Type.ReadCapacityUnitExceeded, waitInterval); 128 } 129 130 public static void throwWriteCapacityUnitExceeded(final long waitInterval) 131 throws RpcThrottlingException { 132 throwThrottlingException(Type.WriteCapacityUnitExceeded, waitInterval); 133 } 134 135 public static void throwAtomicRequestNumberExceeded(final long waitInterval) 136 throws RpcThrottlingException { 137 throwThrottlingException(Type.AtomicRequestNumberExceeded, waitInterval); 138 } 139 140 public static void throwAtomicReadSizeExceeded(final long waitInterval) 141 throws RpcThrottlingException { 142 throwThrottlingException(Type.AtomicReadSizeExceeded, waitInterval); 143 } 144 145 public static void throwAtomicWriteSizeExceeded(final long waitInterval) 146 throws RpcThrottlingException { 147 throwThrottlingException(Type.AtomicWriteSizeExceeded, waitInterval); 148 } 149 150 public static void throwRequestHandlerUsageTimeExceeded(final long waitInterval) 151 throws RpcThrottlingException { 152 throwThrottlingException(Type.RequestHandlerUsageTimeExceeded, waitInterval); 153 } 154 155 private static void throwThrottlingException(final Type type, final long waitInterval) 156 throws RpcThrottlingException { 157 String msg = MSG_TYPE[type.ordinal()] + MSG_WAIT + stringFromMillis(waitInterval); 158 throw new RpcThrottlingException(type, waitInterval, msg); 159 } 160 161 // Visible for TestRpcThrottlingException 162 protected static String stringFromMillis(long millis) { 163 StringBuilder buf = new StringBuilder(); 164 long hours = millis / (60 * 60 * 1000); 165 long rem = (millis % (60 * 60 * 1000)); 166 long minutes = rem / (60 * 1000); 167 rem = rem % (60 * 1000); 168 long seconds = rem / 1000; 169 long milliseconds = rem % 1000; 170 171 if (hours != 0) { 172 buf.append(hours); 173 buf.append(hours > 1 ? "hrs, " : "hr, "); 174 } 175 if (minutes != 0) { 176 buf.append(minutes); 177 buf.append(minutes > 1 ? "mins, " : "min, "); 178 } 179 if (seconds != 0) { 180 buf.append(seconds); 181 buf.append("sec, "); 182 } 183 buf.append(milliseconds); 184 buf.append("ms"); 185 return buf.toString(); 186 } 187 188 // Visible for TestRpcThrottlingException 189 protected static long timeFromString(String timeDiff) { 190 Pattern pattern = 191 Pattern.compile("^(?:(\\d+)hrs?, )?(?:(\\d+)mins?, )?(?:(\\d+)sec[, ]{0,2})?(?:(\\d+)ms)?"); 192 long[] factors = new long[] { 60 * 60 * 1000, 60 * 1000, 1000, 1 }; 193 Matcher m = pattern.matcher(timeDiff); 194 if (m.find()) { 195 int numGroups = m.groupCount(); 196 long time = 0; 197 for (int j = 1; j <= numGroups; j++) { 198 String group = m.group(j); 199 if (group == null) { 200 continue; 201 } 202 time += Math.round(Float.parseFloat(group) * factors[j - 1]); 203 } 204 return time; 205 } 206 return -1; 207 } 208}