View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional information regarding
4    * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
7    * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
8    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
9    * for the specific language governing permissions and limitations under the License.
10   */
11  
12  package org.apache.hadoop.hbase.quotas;
13  
14  import java.util.regex.Matcher;
15  import java.util.regex.Pattern;
16  import org.apache.hadoop.hbase.HBaseIOException;
17  import org.apache.hadoop.hbase.classification.InterfaceAudience;
18  import org.apache.hadoop.hbase.classification.InterfaceStability;
19  import org.apache.hadoop.util.StringUtils;
20  
21  /**
22   * Describe the throttling result. TODO: At some point this will be handled on the client side to
23   * prevent operation to go on the server if the waitInterval is greater than the one got as result
24   * of this exception.
25   */
26  @InterfaceAudience.Public
27  @InterfaceStability.Evolving
28  public class RpcThrottlingException extends HBaseIOException {
29    private static final long serialVersionUID = 1L;
30  
31    @InterfaceAudience.Public
32    @InterfaceStability.Evolving
33    public enum Type {
34      NumRequestsExceeded, RequestSizeExceeded, NumReadRequestsExceeded, NumWriteRequestsExceeded,
35      WriteSizeExceeded, ReadSizeExceeded, RequestCapacityUnitExceeded, ReadCapacityUnitExceeded,
36      WriteCapacityUnitExceeded
37    }
38  
39    private static final String[] MSG_TYPE =
40        new String[] { "number of requests exceeded", "request size limit exceeded",
41          "number of read requests exceeded", "number of write requests exceeded",
42          "write size limit exceeded", "read size limit exceeded", "request capacity unit exceeded",
43          "read capacity unit exceeded", "write capacity unit exceeded" };
44  
45    private static final String MSG_WAIT = " - wait ";
46  
47    private long waitInterval;
48    private Type type;
49  
50    public RpcThrottlingException(String msg) {
51      super(msg);
52  
53      // Dirty workaround to get the information after
54      // ((RemoteException)e.getCause()).unwrapRemoteException()
55      for (int i = 0; i < MSG_TYPE.length; ++i) {
56        int index = msg.indexOf(MSG_TYPE[i]);
57        if (index >= 0) {
58          String waitTimeStr = msg.substring(index + MSG_TYPE[i].length() + MSG_WAIT.length());
59          type = Type.values()[i];
60          waitInterval = timeFromString(waitTimeStr);
61          break;
62        }
63      }
64    }
65  
66    public RpcThrottlingException(final Type type, final long waitInterval, final String msg) {
67      super(msg);
68      this.waitInterval = waitInterval;
69      this.type = type;
70    }
71  
72    public Type getType() {
73      return this.type;
74    }
75  
76    public long getWaitInterval() {
77      return this.waitInterval;
78    }
79  
80    public static void throwNumRequestsExceeded(final long waitInterval) throws
81        RpcThrottlingException {
82      throwThrottlingException(Type.NumRequestsExceeded, waitInterval);
83    }
84  
85    public static void throwRequestSizeExceeded(final long waitInterval)
86        throws RpcThrottlingException {
87      throwThrottlingException(Type.RequestSizeExceeded, waitInterval);
88    }
89  
90    public static void throwNumReadRequestsExceeded(final long waitInterval)
91        throws RpcThrottlingException {
92      throwThrottlingException(Type.NumReadRequestsExceeded, waitInterval);
93    }
94  
95    public static void throwNumWriteRequestsExceeded(final long waitInterval)
96        throws RpcThrottlingException {
97      throwThrottlingException(Type.NumWriteRequestsExceeded, waitInterval);
98    }
99  
100   public static void throwWriteSizeExceeded(final long waitInterval) throws RpcThrottlingException {
101     throwThrottlingException(Type.WriteSizeExceeded, waitInterval);
102   }
103 
104   public static void throwReadSizeExceeded(final long waitInterval) throws RpcThrottlingException {
105     throwThrottlingException(Type.ReadSizeExceeded, waitInterval);
106   }
107 
108   public static void throwRequestCapacityUnitExceeded(final long waitInterval)
109       throws RpcThrottlingException {
110     throwThrottlingException(Type.RequestCapacityUnitExceeded, waitInterval);
111   }
112 
113   public static void throwReadCapacityUnitExceeded(final long waitInterval)
114       throws RpcThrottlingException {
115     throwThrottlingException(Type.ReadCapacityUnitExceeded, waitInterval);
116   }
117 
118   public static void throwWriteCapacityUnitExceeded(final long waitInterval)
119       throws RpcThrottlingException {
120     throwThrottlingException(Type.WriteCapacityUnitExceeded, waitInterval);
121   }
122 
123   private static void throwThrottlingException(final Type type, final long waitInterval)
124       throws RpcThrottlingException {
125     String msg = MSG_TYPE[type.ordinal()] + MSG_WAIT + StringUtils.formatTime(waitInterval);
126     throw new RpcThrottlingException(type, waitInterval, msg);
127   }
128 
129   private static long timeFromString(String timeDiff) {
130     Pattern[] patterns =
131         new Pattern[] { Pattern.compile("^(\\d+\\.\\d\\d)sec"),
132             Pattern.compile("^(\\d+)mins, (\\d+\\.\\d\\d)sec"),
133             Pattern.compile("^(\\d+)hrs, (\\d+)mins, (\\d+\\.\\d\\d)sec") };
134 
135     for (int i = 0; i < patterns.length; ++i) {
136       Matcher m = patterns[i].matcher(timeDiff);
137       if (m.find()) {
138         long time = Math.round(Float.parseFloat(m.group(1 + i)) * 1000);
139         if (i > 0) {
140           time += Long.parseLong(m.group(i)) * (60 * 1000);
141         }
142         if (i > 1) {
143           time += Long.parseLong(m.group(i - 1)) * (60 * 60 * 1000);
144         }
145         return time;
146       }
147     }
148 
149     return -1;
150   }
151 }