This repository has been archived by the owner on Jan 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 361
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New files pulled from FB trunk refresh on 4/8/11
- Loading branch information
jgray
committed
Apr 9, 2011
1 parent
fe528a0
commit 8d633cd
Showing
24 changed files
with
3,809 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.apache.hadoop.ipc; | ||
|
||
import java.io.IOException; | ||
import java.lang.reflect.Method; | ||
import java.util.HashSet; | ||
|
||
|
||
/** | ||
* a class wraps around a server's proxy, | ||
* containing a list of its supported methods. | ||
* | ||
* A list of methods with a value of null indicates that the client and server | ||
* have the same protocol. | ||
*/ | ||
public class ProtocolProxy<T> { | ||
private Class<T> protocol; | ||
private T proxy; | ||
private HashSet<Integer> serverMethods = null; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param protocol protocol class | ||
* @param proxy its proxy | ||
* @param serverMethods a list of hash codes of the methods that it supports | ||
* @throws ClassNotFoundException | ||
*/ | ||
public ProtocolProxy(Class<T> protocol, T proxy, int[] serverMethods) { | ||
this.protocol = protocol; | ||
this.proxy = proxy; | ||
if (serverMethods != null) { | ||
this.serverMethods = new HashSet<Integer>(serverMethods.length); | ||
for (int method : serverMethods) { | ||
this.serverMethods.add(Integer.valueOf(method)); | ||
} | ||
} | ||
} | ||
|
||
/* | ||
* Get the proxy | ||
*/ | ||
public T getProxy() { | ||
return proxy; | ||
} | ||
|
||
/** | ||
* Check if a method is supported by the server or not | ||
* | ||
* @param methodName a method's name in String format | ||
* @param parameterTypes a method's parameter types | ||
* @return true if the method is supported by the server | ||
*/ | ||
public boolean isMethodSupported(String methodName, | ||
Class<?>... parameterTypes) | ||
throws IOException { | ||
if (serverMethods == null) { // client & server have the same protocol | ||
return true; | ||
} | ||
Method method; | ||
try { | ||
method = protocol.getDeclaredMethod(methodName, parameterTypes); | ||
} catch (SecurityException e) { | ||
throw new IOException(e); | ||
} catch (NoSuchMethodException e) { | ||
throw new IOException(e); | ||
} | ||
return serverMethods.contains( | ||
Integer.valueOf(ProtocolSignature.getFingerprint(method))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.apache.hadoop.ipc; | ||
|
||
import java.io.DataInput; | ||
import java.io.DataOutput; | ||
import java.io.IOException; | ||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import org.apache.hadoop.io.Writable; | ||
import org.apache.hadoop.io.WritableFactories; | ||
import org.apache.hadoop.io.WritableFactory; | ||
|
||
public class ProtocolSignature implements Writable { | ||
static { // register a ctor | ||
WritableFactories.setFactory | ||
(ProtocolSignature.class, | ||
new WritableFactory() { | ||
public Writable newInstance() { return new ProtocolSignature(); } | ||
}); | ||
} | ||
|
||
private long version; | ||
private int[] methods = null; // an array of method hash codes | ||
|
||
/** | ||
* default constructor | ||
*/ | ||
public ProtocolSignature() { | ||
} | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param version server version | ||
* @param methodHashcodes hash codes of the methods supported by server | ||
*/ | ||
public ProtocolSignature(long version, int[] methodHashcodes) { | ||
this.version = version; | ||
this.methods = methodHashcodes; | ||
} | ||
|
||
public long getVersion() { | ||
return version; | ||
} | ||
|
||
public int[] getMethods() { | ||
return methods; | ||
} | ||
|
||
@Override | ||
public void readFields(DataInput in) throws IOException { | ||
version = in.readLong(); | ||
boolean hasMethods = in.readBoolean(); | ||
if (hasMethods) { | ||
int numMethods = in.readInt(); | ||
methods = new int[numMethods]; | ||
for (int i=0; i<numMethods; i++) { | ||
methods[i] = in.readInt(); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void write(DataOutput out) throws IOException { | ||
out.writeLong(version); | ||
if (methods == null) { | ||
out.writeBoolean(false); | ||
} else { | ||
out.writeBoolean(true); | ||
out.writeInt(methods.length); | ||
for (int method : methods) { | ||
out.writeInt(method); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Calculate a method's hash code considering its method | ||
* name, returning type, and its parameter types | ||
* | ||
* @param method a method | ||
* @return its hash code | ||
*/ | ||
static int getFingerprint(Method method) { | ||
int hashcode = method.getName().hashCode(); | ||
hashcode = hashcode + 31*method.getReturnType().getName().hashCode(); | ||
for (Class<?> type : method.getParameterTypes()) { | ||
hashcode = 31*hashcode ^ type.getName().hashCode(); | ||
} | ||
return hashcode; | ||
} | ||
|
||
/** | ||
* Convert an array of Method into an array of hash codes | ||
* | ||
* @param methods | ||
* @return array of hash codes | ||
*/ | ||
private static int[] getFingerprints(Method[] methods) { | ||
if (methods == null) { | ||
return null; | ||
} | ||
int[] hashCodes = new int[methods.length]; | ||
for (int i = 0; i<methods.length; i++) { | ||
hashCodes[i] = getFingerprint(methods[i]); | ||
} | ||
return hashCodes; | ||
} | ||
|
||
/** | ||
* Get the hash code of an array of methods | ||
* Methods are sorted before hashcode is calculated. | ||
* So the returned value is irrelevant of the method order in the array. | ||
* | ||
* @param methods an array of methods | ||
* @return the hash code | ||
*/ | ||
static int getFingerprint(Method[] methods) { | ||
return getFingerprint(getFingerprints(methods)); | ||
} | ||
|
||
/** | ||
* Get the hash code of an array of hashcodes | ||
* Hashcodes are sorted before hashcode is calculated. | ||
* So the returned value is irrelevant of the hashcode order in the array. | ||
* | ||
* @param methods an array of methods | ||
* @return the hash code | ||
*/ | ||
static int getFingerprint(int[] hashcodes) { | ||
Arrays.sort(hashcodes); | ||
return Arrays.hashCode(hashcodes); | ||
|
||
} | ||
private static class ProtocolSigFingerprint { | ||
private ProtocolSignature signature; | ||
private int fingerprint; | ||
|
||
ProtocolSigFingerprint(ProtocolSignature sig, int fingerprint) { | ||
this.signature = sig; | ||
this.fingerprint = fingerprint; | ||
} | ||
} | ||
|
||
/** | ||
* A cache that maps a protocol's name to its signature & finger print | ||
*/ | ||
final private static HashMap<String, ProtocolSigFingerprint> | ||
PROTOCOL_FINGERPRINT_CACHE = | ||
new HashMap<String, ProtocolSigFingerprint>(); | ||
|
||
/** | ||
* Return a protocol's signature and finger print from cache | ||
* | ||
* @param protocol a protocol class | ||
* @param serverVersion protocol version | ||
* @return its signature and finger print | ||
*/ | ||
private static ProtocolSigFingerprint getSigFingerprint( | ||
Class <? extends VersionedProtocol> protocol, long serverVersion) { | ||
String protocolName = protocol.getName(); | ||
synchronized (PROTOCOL_FINGERPRINT_CACHE) { | ||
ProtocolSigFingerprint sig = PROTOCOL_FINGERPRINT_CACHE.get(protocolName); | ||
if (sig == null) { | ||
int[] serverMethodHashcodes = getFingerprints(protocol.getMethods()); | ||
sig = new ProtocolSigFingerprint( | ||
new ProtocolSignature(serverVersion, serverMethodHashcodes), | ||
getFingerprint(serverMethodHashcodes)); | ||
PROTOCOL_FINGERPRINT_CACHE.put(protocolName, sig); | ||
} | ||
return sig; | ||
} | ||
} | ||
|
||
/** | ||
* Get a server protocol's signature | ||
* | ||
* @param clientMethodsHashCode client protocol methods hashcode | ||
* @param serverVersion server protocol version | ||
* @param protocol protocol | ||
* @return the server's protocol signature | ||
*/ | ||
public static ProtocolSignature getProtocolSignature( | ||
int clientMethodsHashCode, | ||
long serverVersion, | ||
Class<? extends VersionedProtocol> protocol) { | ||
// try to get the finger print & signature from the cache | ||
ProtocolSigFingerprint sig = getSigFingerprint(protocol, serverVersion); | ||
|
||
// check if the client side protocol matches the one on the server side | ||
if (clientMethodsHashCode == sig.fingerprint) { | ||
return new ProtocolSignature(serverVersion, null); // null indicates a match | ||
} | ||
|
||
return sig.signature; | ||
} | ||
|
||
@Deprecated | ||
public static ProtocolSignature getProtocolSigature( | ||
VersionedProtocol server, String protocol, | ||
long clientVersion, int clientMethodsHash) throws IOException { | ||
return getProtocolSignature( | ||
server, protocol, clientVersion, clientMethodsHash); | ||
} | ||
|
||
/** | ||
* Get a server protocol's signature | ||
* | ||
* @param server server implementation | ||
* @param protocol server protocol | ||
* @param clientVersion client's version | ||
* @param clientMethodsHash client's protocol's hash code | ||
* @return the server protocol's signature | ||
* @throws IOException if any error occurs | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static ProtocolSignature getProtocolSignature(VersionedProtocol server, | ||
String protocol, | ||
long clientVersion, int clientMethodsHash) throws IOException { | ||
Class<? extends VersionedProtocol> inter; | ||
try { | ||
inter = (Class<? extends VersionedProtocol>)Class.forName(protocol); | ||
} catch (Exception e) { | ||
throw new IOException(e); | ||
} | ||
long serverVersion = server.getProtocolVersion(protocol, clientVersion); | ||
return ProtocolSignature.getProtocolSignature( | ||
clientMethodsHash, serverVersion, inter); | ||
} | ||
} |
Oops, something went wrong.