All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.ipc.ProtocolSignature Maven / Gradle / Ivy

The newest version!
/**
 * 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 org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableFactories;
import org.apache.hadoop.io.WritableFactory;

import com.google.common.annotations.VisibleForTesting;

public class ProtocolSignature implements Writable {
  static {               // register a ctor
    WritableFactories.setFactory
      (ProtocolSignature.class,
       new WritableFactory() {
         @Override
        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 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 
     PROTOCOL_FINGERPRINT_CACHE = 
       new HashMap();
  
  @VisibleForTesting
  public static void resetCache() {
    PROTOCOL_FINGERPRINT_CACHE.clear();
  }
  
  /**
   * 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  protocol, long serverVersion) {
    String protocolName = RPC.getProtocolName(protocol);
    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 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;
  }
  
  public static ProtocolSignature getProtocolSignature(String protocolName,
      long version) throws ClassNotFoundException {
    Class protocol = Class.forName(protocolName);
    return getSigFingerprint(protocol, version).signature;
  }
  
  /**
   * 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 inter;
    try {
      inter = (Class)Class.forName(protocol);
    } catch (Exception e) {
      throw new IOException(e);
    }
    long serverVersion = server.getProtocolVersion(protocol, clientVersion);
    return ProtocolSignature.getProtocolSignature(
        clientMethodsHash, serverVersion, inter);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy