001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license 003 * agreements. See the NOTICE file distributed with this work for additional information regarding 004 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the 005 * "License"); you may not use this file except in compliance with the License. You may obtain a 006 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 007 * law or agreed to in writing, software distributed under the License is distributed on an "AS IS" 008 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 009 * for the specific language governing permissions and limitations under the License. 010 */ 011 012package org.apache.hadoop.hbase.quotas; 013 014import java.util.regex.Matcher; 015import java.util.regex.Pattern; 016import org.apache.hadoop.hbase.HBaseIOException; 017import org.apache.hadoop.util.StringUtils; 018 019import org.apache.yetus.audience.InterfaceAudience; 020 021/** 022 * Describe the throttling result. TODO: At some point this will be handled on the client side to 023 * prevent operation to go on the server if the waitInterval is greater than the one got as result 024 * of this exception. 025 */ 026@InterfaceAudience.Public 027public class RpcThrottlingException extends HBaseIOException { 028 029 @InterfaceAudience.Public 030 public enum Type { 031 NumRequestsExceeded, RequestSizeExceeded, NumReadRequestsExceeded, NumWriteRequestsExceeded, 032 WriteSizeExceeded, ReadSizeExceeded, RequestCapacityUnitExceeded, ReadCapacityUnitExceeded, 033 WriteCapacityUnitExceeded 034 } 035 036 private static final String[] MSG_TYPE = 037 new String[] { "number of requests exceeded", "request size limit exceeded", 038 "number of read requests exceeded", "number of write requests exceeded", 039 "write size limit exceeded", "read size limit exceeded", "request capacity unit exceeded", 040 "read capacity unit exceeded", "write capacity unit exceeded" }; 041 042 private static final String MSG_WAIT = " - wait "; 043 044 private long waitInterval; 045 private Type type; 046 047 public RpcThrottlingException(String msg) { 048 super(msg); 049 050 // Dirty workaround to get the information after 051 // ((RemoteException)e.getCause()).unwrapRemoteException() 052 for (int i = 0; i < MSG_TYPE.length; ++i) { 053 int index = msg.indexOf(MSG_TYPE[i]); 054 if (index >= 0) { 055 String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length()); 056 type = Type.values()[i]; 057 waitInterval = timeFromString(waitTimeStr); 058 break; 059 } 060 } 061 } 062 063 public RpcThrottlingException(final Type type, final long waitInterval, final String msg) { 064 super(msg); 065 this.waitInterval = waitInterval; 066 this.type = type; 067 } 068 069 public Type getType() { 070 return this.type; 071 } 072 073 public long getWaitInterval() { 074 return this.waitInterval; 075 } 076 077 public static void throwNumRequestsExceeded(final long waitInterval) throws 078 RpcThrottlingException { 079 throwThrottlingException(Type.NumRequestsExceeded, waitInterval); 080 } 081 082 public static void throwRequestSizeExceeded(final long waitInterval) 083 throws RpcThrottlingException { 084 throwThrottlingException(Type.RequestSizeExceeded, waitInterval); 085 } 086 087 public static void throwNumReadRequestsExceeded(final long waitInterval) 088 throws RpcThrottlingException { 089 throwThrottlingException(Type.NumReadRequestsExceeded, waitInterval); 090 } 091 092 public static void throwNumWriteRequestsExceeded(final long waitInterval) 093 throws RpcThrottlingException { 094 throwThrottlingException(Type.NumWriteRequestsExceeded, waitInterval); 095 } 096 097 public static void throwWriteSizeExceeded(final long waitInterval) throws RpcThrottlingException { 098 throwThrottlingException(Type.WriteSizeExceeded, waitInterval); 099 } 100 101 public static void throwReadSizeExceeded(final long waitInterval) throws RpcThrottlingException { 102 throwThrottlingException(Type.ReadSizeExceeded, waitInterval); 103 } 104 105 public static void throwRequestCapacityUnitExceeded(final long waitInterval) 106 throws RpcThrottlingException { 107 throwThrottlingException(Type.RequestCapacityUnitExceeded, waitInterval); 108 } 109 110 public static void throwReadCapacityUnitExceeded(final long waitInterval) 111 throws RpcThrottlingException { 112 throwThrottlingException(Type.ReadCapacityUnitExceeded, waitInterval); 113 } 114 115 public static void throwWriteCapacityUnitExceeded(final long waitInterval) 116 throws RpcThrottlingException { 117 throwThrottlingException(Type.WriteCapacityUnitExceeded, waitInterval); 118 } 119 120 private static void throwThrottlingException(final Type type, final long waitInterval) 121 throws RpcThrottlingException { 122 String msg = MSG_TYPE[type.ordinal()] + MSG_WAIT + StringUtils.formatTime(waitInterval); 123 throw new RpcThrottlingException(type, waitInterval, msg); 124 } 125 126 private static long timeFromString(String timeDiff) { 127 Pattern[] patterns = 128 new Pattern[] { Pattern.compile("^(\\d+\\.\\d\\d)sec"), 129 Pattern.compile("^(\\d+)mins, (\\d+\\.\\d\\d)sec"), 130 Pattern.compile("^(\\d+)hrs, (\\d+)mins, (\\d+\\.\\d\\d)sec") }; 131 132 for (int i = 0; i < patterns.length; ++i) { 133 Matcher m = patterns[i].matcher(timeDiff); 134 if (m.find()) { 135 long time = Math.round(Float.parseFloat(m.group(1 + i)) * 1000); 136 if (i > 0) { 137 time += Long.parseLong(m.group(i)) * (60 * 1000); 138 } 139 if (i > 1) { 140 time += Long.parseLong(m.group(i - 1)) * (60 * 60 * 1000); 141 } 142 return time; 143 } 144 } 145 146 return -1; 147 } 148}