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.hadoop.util.StringUtils; 024import org.apache.yetus.audience.InterfaceAudience; 025 026/** 027 * Describe the throttling result. TODO: At some point this will be handled on the client side to 028 * prevent operation to go on the server if the waitInterval is greater than the one got as result 029 * of this exception. 030 */ 031@InterfaceAudience.Public 032public class RpcThrottlingException extends HBaseIOException { 033 034 @InterfaceAudience.Public 035 public enum Type { 036 NumRequestsExceeded, 037 RequestSizeExceeded, 038 NumReadRequestsExceeded, 039 NumWriteRequestsExceeded, 040 WriteSizeExceeded, 041 ReadSizeExceeded, 042 RequestCapacityUnitExceeded, 043 ReadCapacityUnitExceeded, 044 WriteCapacityUnitExceeded 045 } 046 047 private static final String[] MSG_TYPE = 048 new String[] { "number of requests exceeded", "request size limit exceeded", 049 "number of read requests exceeded", "number of write requests exceeded", 050 "write size limit exceeded", "read size limit exceeded", "request capacity unit exceeded", 051 "read capacity unit exceeded", "write capacity unit exceeded" }; 052 053 private static final String MSG_WAIT = " - wait "; 054 055 private long waitInterval; 056 private Type type; 057 058 public RpcThrottlingException(String msg) { 059 super(msg); 060 061 // Dirty workaround to get the information after 062 // ((RemoteException)e.getCause()).unwrapRemoteException() 063 for (int i = 0; i < MSG_TYPE.length; ++i) { 064 int index = msg.indexOf(MSG_TYPE[i]); 065 if (index >= 0) { 066 String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length()); 067 type = Type.values()[i]; 068 waitInterval = timeFromString(waitTimeStr); 069 break; 070 } 071 } 072 } 073 074 public RpcThrottlingException(final Type type, final long waitInterval, final String msg) { 075 super(msg); 076 this.waitInterval = waitInterval; 077 this.type = type; 078 } 079 080 public Type getType() { 081 return this.type; 082 } 083 084 public long getWaitInterval() { 085 return this.waitInterval; 086 } 087 088 public static void throwNumRequestsExceeded(final long waitInterval) 089 throws RpcThrottlingException { 090 throwThrottlingException(Type.NumRequestsExceeded, waitInterval); 091 } 092 093 public static void throwRequestSizeExceeded(final long waitInterval) 094 throws RpcThrottlingException { 095 throwThrottlingException(Type.RequestSizeExceeded, waitInterval); 096 } 097 098 public static void throwNumReadRequestsExceeded(final long waitInterval) 099 throws RpcThrottlingException { 100 throwThrottlingException(Type.NumReadRequestsExceeded, waitInterval); 101 } 102 103 public static void throwNumWriteRequestsExceeded(final long waitInterval) 104 throws RpcThrottlingException { 105 throwThrottlingException(Type.NumWriteRequestsExceeded, waitInterval); 106 } 107 108 public static void throwWriteSizeExceeded(final long waitInterval) throws RpcThrottlingException { 109 throwThrottlingException(Type.WriteSizeExceeded, waitInterval); 110 } 111 112 public static void throwReadSizeExceeded(final long waitInterval) throws RpcThrottlingException { 113 throwThrottlingException(Type.ReadSizeExceeded, waitInterval); 114 } 115 116 public static void throwRequestCapacityUnitExceeded(final long waitInterval) 117 throws RpcThrottlingException { 118 throwThrottlingException(Type.RequestCapacityUnitExceeded, waitInterval); 119 } 120 121 public static void throwReadCapacityUnitExceeded(final long waitInterval) 122 throws RpcThrottlingException { 123 throwThrottlingException(Type.ReadCapacityUnitExceeded, waitInterval); 124 } 125 126 public static void throwWriteCapacityUnitExceeded(final long waitInterval) 127 throws RpcThrottlingException { 128 throwThrottlingException(Type.WriteCapacityUnitExceeded, waitInterval); 129 } 130 131 private static void throwThrottlingException(final Type type, final long waitInterval) 132 throws RpcThrottlingException { 133 String msg = MSG_TYPE[type.ordinal()] + MSG_WAIT + StringUtils.formatTime(waitInterval); 134 throw new RpcThrottlingException(type, waitInterval, msg); 135 } 136 137 private static long timeFromString(String timeDiff) { 138 Pattern[] patterns = new Pattern[] { Pattern.compile("^(\\d+\\.\\d\\d)sec"), 139 Pattern.compile("^(\\d+)mins, (\\d+\\.\\d\\d)sec"), 140 Pattern.compile("^(\\d+)hrs, (\\d+)mins, (\\d+\\.\\d\\d)sec") }; 141 142 for (int i = 0; i < patterns.length; ++i) { 143 Matcher m = patterns[i].matcher(timeDiff); 144 if (m.find()) { 145 long time = Math.round(Float.parseFloat(m.group(1 + i)) * 1000); 146 if (i > 0) { 147 time += Long.parseLong(m.group(i)) * (60 * 1000); 148 } 149 if (i > 1) { 150 time += Long.parseLong(m.group(i - 1)) * (60 * 60 * 1000); 151 } 152 return time; 153 } 154 } 155 156 return -1; 157 } 158}