hadoop ProtocolSignature 源码

  • 2022-10-20
  • 浏览 (209)

haddop ProtocolSignature 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/ProtocolSignature.java

/**
 * 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 org.apache.hadoop.classification.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<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
   */
  private final static HashMap<String, ProtocolSigFingerprint> 
     PROTOCOL_FINGERPRINT_CACHE = 
       new HashMap<String, ProtocolSigFingerprint>();
  
  @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<? 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;
  }
  
  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<? 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);
  }
}

相关信息

hadoop 源码目录

相关文章

hadoop AlignmentContext 源码

hadoop AsyncCallLimitExceededException 源码

hadoop CallQueueManager 源码

hadoop CallerContext 源码

hadoop Client 源码

hadoop ClientCache 源码

hadoop ClientId 源码

hadoop CostProvider 源码

hadoop DecayRpcScheduler 源码

hadoop DecayRpcSchedulerMXBean 源码

0  赞