View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.quotas;
20  
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.classification.InterfaceStability;
26  
27  /**
28   * Describe the throttling result.
29   *
30   * TODO: At some point this will be handled on the client side to prevent
31   * operation to go on the server if the waitInterval is grater than the one got
32   * as result of this exception.
33   */
34  @InterfaceAudience.Public
35  @InterfaceStability.Evolving
36  public class ThrottlingException extends QuotaExceededException {
37    private static final long serialVersionUID = 1406576492085155743L;
38  
39    @InterfaceAudience.Public
40    @InterfaceStability.Evolving
41    public enum Type {
42      NumRequestsExceeded,
43      RequestSizeExceeded,
44      NumReadRequestsExceeded,
45      NumWriteRequestsExceeded,
46      WriteSizeExceeded,
47      ReadSizeExceeded,
48    }
49  
50    private static final String[] MSG_TYPE = new String[] {
51      "number of requests exceeded",
52      "request size limit exceeded",
53      "number of read requests exceeded",
54      "number of write requests exceeded",
55      "write size limit exceeded",
56      "read size limit exceeded",
57    };
58  
59    private static final String MSG_WAIT = " - wait ";
60  
61    private long waitInterval;
62    private Type type;
63  
64    public ThrottlingException(String msg) {
65      super(msg);
66  
67      // Dirty workaround to get the information after
68      // ((RemoteException)e.getCause()).unwrapRemoteException()
69      for (int i = 0; i < MSG_TYPE.length; ++i) {
70        int index = msg.indexOf(MSG_TYPE[i]);
71        if (index >= 0) {
72          String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length());
73          type = Type.values()[i];;
74          waitInterval = timeFromString(waitTimeStr);
75          break;
76        }
77      }
78    }
79  
80    public ThrottlingException(final Type type, final long waitInterval, final String msg) {
81      super(msg);
82      this.waitInterval = waitInterval;
83      this.type = type;
84    }
85  
86    public Type getType() {
87      return this.type;
88    }
89  
90    public long getWaitInterval() {
91      return this.waitInterval;
92    }
93  
94    public static void throwNumRequestsExceeded(final long waitInterval)
95        throws ThrottlingException {
96      throwThrottlingException(Type.NumRequestsExceeded, waitInterval);
97    }
98  
99    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 }