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