1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.ipc;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.lang.reflect.Method;
25 import java.util.Arrays;
26 import java.util.HashMap;
27
28 import org.apache.hadoop.io.Writable;
29 import org.apache.hadoop.io.WritableFactories;
30 import org.apache.hadoop.io.WritableFactory;
31
32 public class ProtocolSignature implements Writable {
33 static {
34 WritableFactories.setFactory
35 (ProtocolSignature.class,
36 new WritableFactory() {
37 public Writable newInstance() { return new ProtocolSignature(); }
38 });
39 }
40
41 private long version;
42 private int[] methods = null;
43
44
45
46
47 public ProtocolSignature() {
48 }
49
50
51
52
53
54
55
56 public ProtocolSignature(long version, int[] methodHashcodes) {
57 this.version = version;
58 this.methods = methodHashcodes;
59 }
60
61 public long getVersion() {
62 return version;
63 }
64
65 public int[] getMethods() {
66 return methods;
67 }
68
69 @Override
70 public void readFields(DataInput in) throws IOException {
71 version = in.readLong();
72 boolean hasMethods = in.readBoolean();
73 if (hasMethods) {
74 int numMethods = in.readInt();
75 methods = new int[numMethods];
76 for (int i=0; i<numMethods; i++) {
77 methods[i] = in.readInt();
78 }
79 }
80 }
81
82 @Override
83 public void write(DataOutput out) throws IOException {
84 out.writeLong(version);
85 if (methods == null) {
86 out.writeBoolean(false);
87 } else {
88 out.writeBoolean(true);
89 out.writeInt(methods.length);
90 for (int method : methods) {
91 out.writeInt(method);
92 }
93 }
94 }
95
96
97
98
99
100
101
102
103 static int getFingerprint(Method method) {
104 int hashcode = method.getName().hashCode();
105 hashcode = hashcode + 31*method.getReturnType().getName().hashCode();
106 for (Class<?> type : method.getParameterTypes()) {
107 hashcode = 31*hashcode ^ type.getName().hashCode();
108 }
109 return hashcode;
110 }
111
112
113
114
115
116
117
118 private static int[] getFingerprints(Method[] methods) {
119 if (methods == null) {
120 return null;
121 }
122 int[] hashCodes = new int[methods.length];
123 for (int i = 0; i<methods.length; i++) {
124 hashCodes[i] = getFingerprint(methods[i]);
125 }
126 return hashCodes;
127 }
128
129
130
131
132
133
134
135
136
137 static int getFingerprint(Method[] methods) {
138 return getFingerprint(getFingerprints(methods));
139 }
140
141
142
143
144
145
146
147
148
149 static int getFingerprint(int[] hashcodes) {
150 Arrays.sort(hashcodes);
151 return Arrays.hashCode(hashcodes);
152
153 }
154 private static class ProtocolSigFingerprint {
155 private ProtocolSignature signature;
156 private int fingerprint;
157
158 ProtocolSigFingerprint(ProtocolSignature sig, int fingerprint) {
159 this.signature = sig;
160 this.fingerprint = fingerprint;
161 }
162 }
163
164
165
166
167 final private static HashMap<String, ProtocolSigFingerprint>
168 PROTOCOL_FINGERPRINT_CACHE =
169 new HashMap<String, ProtocolSigFingerprint>();
170
171
172
173
174
175
176
177
178 private static ProtocolSigFingerprint getSigFingerprint(
179 Class <? extends VersionedProtocol> protocol, long serverVersion) {
180 String protocolName = protocol.getName();
181 synchronized (PROTOCOL_FINGERPRINT_CACHE) {
182 ProtocolSigFingerprint sig = PROTOCOL_FINGERPRINT_CACHE.get(protocolName);
183 if (sig == null) {
184 int[] serverMethodHashcodes = getFingerprints(protocol.getMethods());
185 sig = new ProtocolSigFingerprint(
186 new ProtocolSignature(serverVersion, serverMethodHashcodes),
187 getFingerprint(serverMethodHashcodes));
188 PROTOCOL_FINGERPRINT_CACHE.put(protocolName, sig);
189 }
190 return sig;
191 }
192 }
193
194
195
196
197
198
199
200
201
202 static ProtocolSignature getProtocolSignature(
203 int clientMethodsHashCode,
204 long serverVersion,
205 Class<? extends VersionedProtocol> protocol) {
206
207 ProtocolSigFingerprint sig = getSigFingerprint(protocol, serverVersion);
208
209
210 if (clientMethodsHashCode == sig.fingerprint) {
211 return new ProtocolSignature(serverVersion, null);
212 }
213
214 return sig.signature;
215 }
216
217
218
219
220
221
222
223
224
225
226
227 @SuppressWarnings("unchecked")
228 public static ProtocolSignature getProtocolSignature(VersionedProtocol server,
229 String protocol,
230 long clientVersion, int clientMethodsHash) throws IOException {
231 Class<? extends VersionedProtocol> inter;
232 try {
233 inter = (Class<? extends VersionedProtocol>)Class.forName(protocol);
234 } catch (Exception e) {
235 throw new IOException(e);
236 }
237 long serverVersion = server.getProtocolVersion(protocol, clientVersion);
238 return ProtocolSignature.getProtocolSignature(
239 clientMethodsHash, serverVersion, inter);
240 }
241 }