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