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 */ 018package org.apache.hadoop.hbase.exceptions; 019 020import java.io.EOFException; 021import java.io.IOException; 022import java.io.SyncFailedException; 023import java.lang.reflect.UndeclaredThrowableException; 024import java.net.ConnectException; 025import java.net.SocketTimeoutException; 026import java.nio.channels.ClosedChannelException; 027import java.util.Set; 028import java.util.concurrent.TimeoutException; 029import org.apache.hadoop.hbase.CallDroppedException; 030import org.apache.hadoop.hbase.CallQueueTooBigException; 031import org.apache.hadoop.hbase.DoNotRetryIOException; 032import org.apache.hadoop.hbase.MultiActionResultTooLarge; 033import org.apache.hadoop.hbase.NotServingRegionException; 034import org.apache.hadoop.hbase.RegionTooBusyException; 035import org.apache.hadoop.hbase.RetryImmediatelyException; 036import org.apache.hadoop.hbase.ipc.CallTimeoutException; 037import org.apache.hadoop.hbase.ipc.FailedServerException; 038import org.apache.hadoop.hbase.quotas.RpcThrottlingException; 039import org.apache.hadoop.ipc.RemoteException; 040import org.apache.yetus.audience.InterfaceAudience; 041import org.apache.yetus.audience.InterfaceStability; 042 043import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableSet; 044 045@InterfaceAudience.Private 046@InterfaceStability.Evolving 047public final class ClientExceptionsUtil { 048 049 private ClientExceptionsUtil() { 050 } 051 052 public static boolean isMetaClearingException(Throwable cur) { 053 cur = findException(cur); 054 055 if (cur == null) { 056 return true; 057 } 058 return !isSpecialException(cur) || (cur instanceof RegionMovedException) 059 || cur instanceof NotServingRegionException; 060 } 061 062 public static boolean isSpecialException(Throwable cur) { 063 return (cur instanceof RegionMovedException || cur instanceof RegionOpeningException 064 || cur instanceof RegionTooBusyException || cur instanceof RpcThrottlingException 065 || cur instanceof MultiActionResultTooLarge || cur instanceof RetryImmediatelyException 066 || cur instanceof CallQueueTooBigException || cur instanceof CallDroppedException 067 || cur instanceof NotServingRegionException || cur instanceof RequestTooBigException); 068 } 069 070 /** 071 * Look for an exception we know in the remote exception: - hadoop.ipc wrapped exceptions - nested 072 * exceptions Looks for: RegionMovedException / RegionOpeningException / RegionTooBusyException / 073 * RpcThrottlingException 074 * @return null if we didn't find the exception, the exception otherwise. 075 */ 076 public static Throwable findException(Object exception) { 077 if (exception == null || !(exception instanceof Throwable)) { 078 return null; 079 } 080 Throwable cur = (Throwable) exception; 081 while (cur != null) { 082 if (isSpecialException(cur)) { 083 return cur; 084 } 085 if (cur instanceof RemoteException) { 086 RemoteException re = (RemoteException) cur; 087 cur = re.unwrapRemoteException(); 088 089 // unwrapRemoteException can return the exception given as a parameter when it cannot 090 // unwrap it. In this case, there is no need to look further 091 // noinspection ObjectEquality 092 if (cur == re) { 093 return cur; 094 } 095 096 // When we receive RemoteException which wraps IOException which has a cause as 097 // RemoteException we can get into infinite loop here; so if the cause of the exception 098 // is RemoteException, we shouldn't look further. 099 } else if (cur.getCause() != null && !(cur.getCause() instanceof RemoteException)) { 100 cur = cur.getCause(); 101 } else { 102 return cur; 103 } 104 } 105 106 return null; 107 } 108 109 // This list covers most connectivity exceptions but not all. 110 // For example, in SocketOutputStream a plain IOException is thrown at times when the channel is 111 // closed. 112 private static final ImmutableSet<Class<? extends Throwable>> CONNECTION_EXCEPTION_TYPES = 113 ImmutableSet.of(SocketTimeoutException.class, ConnectException.class, 114 ClosedChannelException.class, SyncFailedException.class, EOFException.class, 115 TimeoutException.class, TimeoutIOException.class, CallTimeoutException.class, 116 ConnectionClosingException.class, FailedServerException.class, 117 ConnectionClosedException.class); 118 119 /** 120 * For test only. Usually you should use the {@link #isConnectionException(Throwable)} method 121 * below. 122 */ 123 public static Set<Class<? extends Throwable>> getConnectionExceptionTypes() { 124 return CONNECTION_EXCEPTION_TYPES; 125 } 126 127 /** 128 * Check if the exception is something that indicates that we cannot contact/communicate with the 129 * server. 130 * @param e exception to check 131 * @return true when exception indicates that the client wasn't able to make contact with server 132 */ 133 public static boolean isConnectionException(Throwable e) { 134 if (e == null) { 135 return false; 136 } 137 for (Class<? extends Throwable> clazz : CONNECTION_EXCEPTION_TYPES) { 138 if (clazz.isAssignableFrom(e.getClass())) { 139 return true; 140 } 141 } 142 return false; 143 } 144 145 /** 146 * Translates exception for preemptive fast fail checks. 147 * @param t exception to check 148 * @return translated exception n 149 */ 150 public static Throwable translatePFFE(Throwable t) throws IOException { 151 if (t instanceof NoSuchMethodError) { 152 // We probably can't recover from this exception by retrying. 153 throw (NoSuchMethodError) t; 154 } 155 156 if (t instanceof NullPointerException) { 157 // The same here. This is probably a bug. 158 throw (NullPointerException) t; 159 } 160 161 if (t instanceof UndeclaredThrowableException) { 162 t = t.getCause(); 163 } 164 if (t instanceof RemoteException) { 165 t = ((RemoteException) t).unwrapRemoteException(); 166 } 167 if (t instanceof DoNotRetryIOException) { 168 throw (DoNotRetryIOException) t; 169 } 170 if (t instanceof Error) { 171 throw (Error) t; 172 } 173 return t; 174 } 175}