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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.ipc
;
20 import java
.io
.IOException
;
21 import java
.lang
.reflect
.Constructor
;
22 import java
.security
.AccessController
;
23 import java
.security
.PrivilegedAction
;
25 import org
.apache
.hadoop
.conf
.Configuration
;
26 import org
.apache
.hadoop
.hbase
.DoNotRetryIOException
;
27 import org
.apache
.hadoop
.hbase
.HBaseConfiguration
;
28 import org
.apache
.hadoop
.hbase
.util
.DynamicClassLoader
;
29 import org
.apache
.hadoop
.ipc
.RemoteException
;
30 import org
.apache
.yetus
.audience
.InterfaceAudience
;
33 * A {@link RemoteException} with some extra information. If source exception
34 * was a {@link org.apache.hadoop.hbase.DoNotRetryIOException},
35 * {@link #isDoNotRetry()} will return true.
36 * <p>A {@link RemoteException} hosts exceptions we got from the server.
38 @SuppressWarnings("serial")
39 @InterfaceAudience.Public
40 public class RemoteWithExtrasException
extends RemoteException
{
41 private final String hostname
;
42 private final int port
;
43 private final boolean doNotRetry
;
46 * Dynamic class loader to load filter/comparators
48 private final static class ClassLoaderHolder
{
49 private final static ClassLoader CLASS_LOADER
;
52 ClassLoader parent
= RemoteWithExtrasException
.class.getClassLoader();
53 Configuration conf
= HBaseConfiguration
.create();
54 CLASS_LOADER
= AccessController
.doPrivileged((PrivilegedAction
<ClassLoader
>)
55 () -> new DynamicClassLoader(conf
, parent
)
60 public RemoteWithExtrasException(String className
, String msg
, final boolean doNotRetry
) {
61 this(className
, msg
, null, -1, doNotRetry
);
64 public RemoteWithExtrasException(String className
, String msg
, final String hostname
,
65 final int port
, final boolean doNotRetry
) {
66 super(className
, msg
);
67 this.hostname
= hostname
;
69 this.doNotRetry
= doNotRetry
;
73 public IOException
unwrapRemoteException() {
76 // try to load a exception class from where the HBase classes are loaded or from Dynamic
78 realClass
= Class
.forName(getClassName(), false, ClassLoaderHolder
.CLASS_LOADER
);
79 } catch (ClassNotFoundException cnfe
) {
81 // cause could be a hadoop exception, try to load from hadoop classpath
82 realClass
= Class
.forName(getClassName(), false, super.getClass().getClassLoader());
83 } catch (ClassNotFoundException e
) {
84 return new DoNotRetryIOException(
85 "Unable to load exception received from server:" + e
.getMessage(), this);
89 return instantiateException(realClass
.asSubclass(IOException
.class));
90 } catch (Exception e
) {
91 return new DoNotRetryIOException(
92 "Unable to instantiate exception received from server:" + e
.getMessage(), this);
96 private IOException
instantiateException(Class
<?
extends IOException
> cls
) throws Exception
{
97 Constructor
<?
extends IOException
> cn
= cls
.getConstructor(String
.class);
98 cn
.setAccessible(true);
99 IOException ex
= cn
.newInstance(this.getMessage());
105 * @return null if not set
107 public String
getHostname() {
108 return this.hostname
;
112 * @return -1 if not set
114 public int getPort() {
119 * @return True if origin exception was a do not retry type.
121 public boolean isDoNotRetry() {
122 return this.doNotRetry
;