1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.errorhandling;
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.classification.InterfaceStability;
26 import org.apache.hadoop.hbase.protobuf.generated.ErrorHandlingProtos.ForeignExceptionMessage;
27 import org.apache.hadoop.hbase.protobuf.generated.ErrorHandlingProtos.GenericExceptionMessage;
28 import org.apache.hadoop.hbase.protobuf.generated.ErrorHandlingProtos.StackTraceElementMessage;
29
30 import com.google.protobuf.InvalidProtocolBufferException;
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @InterfaceAudience.Public
45 @InterfaceStability.Evolving
46 @SuppressWarnings("serial")
47 public class ForeignException extends IOException {
48
49
50
51
52 private final String source;
53
54
55
56
57
58
59
60 public ForeignException(String source, Throwable cause) {
61 super(cause);
62 assert source != null;
63 assert cause != null;
64 this.source = source;
65 }
66
67
68
69
70
71
72
73 public ForeignException(String source, String msg) {
74 super(new IllegalArgumentException(msg));
75 this.source = source;
76 }
77
78 public String getSource() {
79 return source;
80 }
81
82
83
84
85
86
87
88
89
90
91 public boolean isRemote() {
92 return getCause() instanceof ProxyThrowable;
93 }
94
95 @Override
96 public String toString() {
97 String className = getCause().getClass().getName() ;
98 return className + " via " + getSource() + ":" + getLocalizedMessage();
99 }
100
101
102
103
104
105
106 private static List<StackTraceElementMessage> toStackTraceElementMessages(
107 StackTraceElement[] trace) {
108
109 if (trace == null) return null;
110
111 List<StackTraceElementMessage> pbTrace =
112 new ArrayList<StackTraceElementMessage>(trace.length);
113 for (StackTraceElement elem : trace) {
114 StackTraceElementMessage.Builder stackBuilder = StackTraceElementMessage.newBuilder();
115 stackBuilder.setDeclaringClass(elem.getClassName());
116 stackBuilder.setFileName(elem.getFileName());
117 stackBuilder.setLineNumber(elem.getLineNumber());
118 stackBuilder.setMethodName(elem.getMethodName());
119 pbTrace.add(stackBuilder.build());
120 }
121 return pbTrace;
122 }
123
124
125
126
127 private static class ProxyThrowable extends Throwable {
128 ProxyThrowable(String msg, StackTraceElement[] trace) {
129 super(msg);
130 this.setStackTrace(trace);
131 }
132 }
133
134
135
136
137
138
139
140 public static byte[] serialize(String source, Throwable t) {
141 GenericExceptionMessage.Builder gemBuilder = GenericExceptionMessage.newBuilder();
142 gemBuilder.setClassName(t.getClass().getName());
143 if (t.getMessage() != null) {
144 gemBuilder.setMessage(t.getMessage());
145 }
146
147 List<StackTraceElementMessage> stack =
148 ForeignException.toStackTraceElementMessages(t.getStackTrace());
149 if (stack != null) {
150 gemBuilder.addAllTrace(stack);
151 }
152 GenericExceptionMessage payload = gemBuilder.build();
153 ForeignExceptionMessage.Builder exception = ForeignExceptionMessage.newBuilder();
154 exception.setGenericException(payload).setSource(source);
155 ForeignExceptionMessage eem = exception.build();
156 return eem.toByteArray();
157 }
158
159
160
161
162
163
164
165 public static ForeignException deserialize(byte[] bytes) throws InvalidProtocolBufferException {
166
167 ForeignExceptionMessage eem = ForeignExceptionMessage.parseFrom(bytes);
168 GenericExceptionMessage gem = eem.getGenericException();
169 StackTraceElement [] trace = ForeignException.toStackTrace(gem.getTraceList());
170 ProxyThrowable dfe = new ProxyThrowable(gem.getMessage(), trace);
171 ForeignException e = new ForeignException(eem.getSource(), dfe);
172 return e;
173 }
174
175
176
177
178
179
180
181
182 private static StackTraceElement[] toStackTrace(List<StackTraceElementMessage> traceList) {
183 if (traceList == null || traceList.size() == 0) {
184 return new StackTraceElement[0];
185 }
186 StackTraceElement[] trace = new StackTraceElement[traceList.size()];
187 for (int i = 0; i < traceList.size(); i++) {
188 StackTraceElementMessage elem = traceList.get(i);
189 trace[i] = new StackTraceElement(
190 elem.getDeclaringClass(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber());
191 }
192 return trace;
193 }
194 }