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, 033 } 034 035 private static final String[] MSG_TYPE = 036 new String[] { "number of requests exceeded", "request size limit exceeded", 037 "number of read requests exceeded", "number of write requests exceeded", 038 "write size limit exceeded", "read size limit exceeded", }; 039 040 private static final String MSG_WAIT = " - wait "; 041 042 private long waitInterval; 043 private Type type; 044 045 public RpcThrottlingException(String msg) { 046 super(msg); 047 048 // Dirty workaround to get the information after 049 // ((RemoteException)e.getCause()).unwrapRemoteException() 050 for (int i = 0; i < MSG_TYPE.length; ++i) { 051 int index = msg.indexOf(MSG_TYPE[i]); 052 if (index >= 0) { 053 String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length()); 054 type = Type.values()[i]; 055 waitInterval = timeFromString(waitTimeStr); 056 break; 057 } 058 } 059 } 060 061 public RpcThrottlingException(final Type type, final long waitInterval, final String msg) { 062 super(msg); 063 this.waitInterval = waitInterval; 064 this.type = type; 065 } 066 067 public Type getType() { 068 return this.type; 069 } 070 071 public long getWaitInterval() { 072 return this.waitInterval; 073 } 074 075 public static void throwNumRequestsExceeded(final long waitInterval) throws 076 RpcThrottlingException { 077 throwThrottlingException(Type.NumRequestsExceeded, waitInterval); 078 } 079 080 public static void throwRequestSizeExceeded(final long waitInterval) 081 throws RpcThrottlingException { 082 throwThrottlingException(Type.RequestSizeExceeded, waitInterval); 083 } 084 085 public static void throwNumReadRequestsExceeded(final long waitInterval) 086 throws RpcThrottlingException { 087 throwThrottlingException(Type.NumReadRequestsExceeded, waitInterval); 088 } 089 090 public static void throwNumWriteRequestsExceeded(final long waitInterval) 091 throws RpcThrottlingException { 092 throwThrottlingException(Type.NumWriteRequestsExceeded, waitInterval); 093 } 094 095 public static void throwWriteSizeExceeded(final long waitInterval) throws RpcThrottlingException { 096 throwThrottlingException(Type.WriteSizeExceeded, waitInterval); 097 } 098 099 public static void throwReadSizeExceeded(final long waitInterval) throws RpcThrottlingException { 100 throwThrottlingException(Type.ReadSizeExceeded, waitInterval); 101 } 102 103 private static void throwThrottlingException(final Type type, final long waitInterval) 104 throws RpcThrottlingException { 105 String msg = MSG_TYPE[type.ordinal()] + MSG_WAIT + StringUtils.formatTime(waitInterval); 106 throw new RpcThrottlingException(type, waitInterval, msg); 107 } 108 109 private static long timeFromString(String timeDiff) { 110 Pattern[] patterns = 111 new Pattern[] { Pattern.compile("^(\\d+\\.\\d\\d)sec"), 112 Pattern.compile("^(\\d+)mins, (\\d+\\.\\d\\d)sec"), 113 Pattern.compile("^(\\d+)hrs, (\\d+)mins, (\\d+\\.\\d\\d)sec") }; 114 115 for (int i = 0; i < patterns.length; ++i) { 116 Matcher m = patterns[i].matcher(timeDiff); 117 if (m.find()) { 118 long time = Math.round(Float.parseFloat(m.group(1 + i)) * 1000); 119 if (i > 0) { 120 time += Long.parseLong(m.group(i)) * (60 * 1000); 121 } 122 if (i > 1) { 123 time += Long.parseLong(m.group(i - 1)) * (60 * 60 * 1000); 124 } 125 return time; 126 } 127 } 128 129 return -1; 130 } 131}