View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.exceptions;
21  
22  import java.io.EOFException;
23  import java.io.IOException;
24  import java.io.SyncFailedException;
25  import java.lang.reflect.UndeclaredThrowableException;
26  import java.net.ConnectException;
27  import java.net.SocketTimeoutException;
28  import java.nio.channels.ClosedChannelException;
29  import java.util.concurrent.TimeoutException;
30  
31  import org.apache.hadoop.hbase.CallDroppedException;
32  import org.apache.hadoop.hbase.CallQueueTooBigException;
33  import org.apache.hadoop.hbase.DoNotRetryIOException;
34  import org.apache.hadoop.hbase.MultiActionResultTooLarge;
35  import org.apache.hadoop.hbase.NotServingRegionException;
36  import org.apache.hadoop.hbase.RegionTooBusyException;
37  import org.apache.hadoop.hbase.RetryImmediatelyException;
38  import org.apache.hadoop.hbase.classification.InterfaceAudience;
39  import org.apache.hadoop.hbase.classification.InterfaceStability;
40  import org.apache.hadoop.hbase.ipc.CallTimeoutException;
41  import org.apache.hadoop.hbase.ipc.FailedServerException;
42  import org.apache.hadoop.hbase.quotas.ThrottlingException;
43  import org.apache.hadoop.ipc.RemoteException;
44  
45  @InterfaceAudience.Private
46  @InterfaceStability.Evolving
47  public final class ClientExceptionsUtil {
48  
49    private ClientExceptionsUtil() {}
50  
51    public static boolean isMetaClearingException(Throwable cur) {
52      cur = findException(cur);
53  
54      if (cur == null) {
55        return true;
56      }
57      return !isSpecialException(cur) || (cur instanceof RegionMovedException)
58          || cur instanceof NotServingRegionException;
59    }
60  
61    public static boolean isSpecialException(Throwable cur) {
62      return (cur instanceof RegionMovedException || cur instanceof RegionOpeningException
63          || cur instanceof RegionTooBusyException || cur instanceof ThrottlingException
64          || cur instanceof MultiActionResultTooLarge || cur instanceof RetryImmediatelyException
65          || cur instanceof CallQueueTooBigException || cur instanceof CallDroppedException
66          || cur instanceof NotServingRegionException || cur instanceof RequestTooBigException);
67    }
68  
69  
70    /**
71     * Look for an exception we know in the remote exception:
72     * - hadoop.ipc wrapped exceptions
73     * - nested exceptions
74     *
75     * Looks for: RegionMovedException / RegionOpeningException / RegionTooBusyException /
76     *            ThrottlingException
77     * @return null if we didn't find the exception, the exception otherwise.
78     */
79    public static Throwable findException(Object exception) {
80      if (exception == null || !(exception instanceof Throwable)) {
81        return null;
82      }
83      Throwable cur = (Throwable) exception;
84      while (cur != null) {
85        if (isSpecialException(cur)) {
86          return cur;
87        }
88        if (cur instanceof RemoteException) {
89          RemoteException re = (RemoteException) cur;
90          cur = re.unwrapRemoteException();
91  
92          // unwrapRemoteException can return the exception given as a parameter when it cannot
93          //  unwrap it. In this case, there is no need to look further
94          // noinspection ObjectEquality
95          if (cur == re) {
96            return cur;
97          }
98  
99          // When we receive RemoteException which wraps IOException which has a cause as
100         // RemoteException we can get into infinite loop here; so if the cause of the exception
101         // is RemoteException, we shouldn't look further.
102       } else if (cur.getCause() != null && !(cur.getCause() instanceof RemoteException)) {
103         cur = cur.getCause();
104       } else {
105         return cur;
106       }
107     }
108 
109     return null;
110   }
111 
112   /**
113    * Checks if the exception is CallQueueTooBig exception (maybe wrapped
114    * into some RemoteException).
115    * @param t exception to check
116    * @return true if it's a CQTBE, false otherwise
117    */
118   public static boolean isCallQueueTooBigException(Throwable t) {
119     t = findException(t);
120     return (t instanceof CallQueueTooBigException);
121   }
122 
123   /**
124    * Checks if the exception is CallDroppedException (maybe wrapped
125    * into some RemoteException).
126    * @param t exception to check
127    * @return true if it's a CQTBE, false otherwise
128    */
129   public static boolean isCallDroppedException(Throwable t) {
130     t = findException(t);
131     return (t instanceof CallDroppedException);
132   }
133 
134   /**
135    * Check if the exception is something that indicates that we cannot
136    * contact/communicate with the server.
137    *
138    * @param e exception to check
139    * @return true when exception indicates that the client wasn't able to make contact with server
140    */
141   public static boolean isConnectionException(Throwable e) {
142     if (e == null) {
143       return false;
144     }
145     // This list covers most connectivity exceptions but not all.
146     // For example, in SocketOutputStream a plain IOException is thrown
147     // at times when the channel is closed.
148     return (e instanceof SocketTimeoutException || e instanceof ConnectException
149       || e instanceof ClosedChannelException || e instanceof SyncFailedException
150       || e instanceof EOFException || e instanceof TimeoutException
151       || e instanceof CallTimeoutException || e instanceof ConnectionClosingException
152       || e instanceof FailedServerException);
153   }
154 
155   /**
156    * Translates exception for preemptive fast fail checks.
157    * @param t exception to check
158    * @return translated exception
159    * @throws IOException
160    */
161   public static Throwable translatePFFE(Throwable t) throws IOException {
162     if (t instanceof NoSuchMethodError) {
163       // We probably can't recover from this exception by retrying.
164       throw (NoSuchMethodError) t;
165     }
166 
167     if (t instanceof NullPointerException) {
168       // The same here. This is probably a bug.
169       throw (NullPointerException) t;
170     }
171 
172     if (t instanceof UndeclaredThrowableException) {
173       t = t.getCause();
174     }
175     if (t instanceof RemoteException) {
176       t = ((RemoteException) t).unwrapRemoteException();
177     }
178     if (t instanceof DoNotRetryIOException) {
179       throw (DoNotRetryIOException) t;
180     }
181     if (t instanceof Error) {
182       throw (Error) t;
183     }
184     return t;
185   }
186 }