/**
 * 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.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;

import junit.framework.Assert;

import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.KerberosInfo;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenInfo;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSelector;
import org.apache.hadoop.security.token.delegation.TestDelegationToken.TestDelegationTokenIdentifier;
import org.apache.hadoop.security.token.delegation.TestDelegationToken.TestDelegationTokenSecretManager;
import org.apache.hadoop.util.Time;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;

/**
 * MiniRPCBenchmark measures time to establish an RPC connection 
 * to a secure RPC server.
 * It sequentially establishes connections the specified number of times, 
 * and calculates the average time taken to connect.
 * The time to connect includes the server side authentication time.
 * The benchmark supports three authentication methods:
 * <ol>
 * <li>simple - no authentication. In order to enter this mode 
 * the configuration file <tt>core-site.xml</tt> should specify
 * <tt>hadoop.security.authentication = simple</tt>.
 * This is the default mode.</li>
 * <li>kerberos - kerberos authentication. In order to enter this mode 
 * the configuration file <tt>core-site.xml</tt> should specify
 * <tt>hadoop.security.authentication = kerberos</tt> and 
 * the argument string should provide qualifying
 * <tt>keytabFile</tt> and <tt>userName</tt> parameters.
 * <li>delegation token - authentication using delegation token.
 * In order to enter this mode the benchmark should provide all the
 * mentioned parameters for kerberos authentication plus the
 * <tt>useToken</tt> argument option.
 * </ol>
 * Input arguments:
 * <ul>
 * <li>numIterations - number of connections to establish</li>
 * <li>keytabFile - keytab file for kerberos authentication</li>
 * <li>userName - principal name for kerberos authentication</li>
 * <li>useToken - should be specified for delegation token authentication</li>
 * <li>logLevel - logging level, see {@link Level}</li>
 * </ul>
 */
public class MiniRPCBenchmark {
  private static final String KEYTAB_FILE_KEY = "test.keytab.file";
  private static final String USER_NAME_KEY = "test.user.name";
  private static final String MINI_USER = "miniUser";
  private static final String RENEWER = "renewer";
  private static final String GROUP_NAME_1 = "MiniGroup1";
  private static final String GROUP_NAME_2 = "MiniGroup2";
  private static final String[] GROUP_NAMES = 
                                    new String[] {GROUP_NAME_1, GROUP_NAME_2};

  private UserGroupInformation currentUgi;
  private Level logLevel;

  MiniRPCBenchmark(Level l) {
    currentUgi = null;
    logLevel = l;
  }

  public static class TestDelegationTokenSelector extends 
  AbstractDelegationTokenSelector<TestDelegationTokenIdentifier>{

    protected TestDelegationTokenSelector() {
      super(new Text("MY KIND"));
    }    
  }
  
  @KerberosInfo(
      serverPrincipal=USER_NAME_KEY)
  @TokenInfo(TestDelegationTokenSelector.class)
  public static interface MiniProtocol extends VersionedProtocol {
    public static final long versionID = 1L;

    /**
     * Get a Delegation Token.
     */
    public Token<TestDelegationTokenIdentifier> getDelegationToken(Text renewer) 
        throws IOException;
  }

  /**
   * Primitive RPC server, which
   * allows clients to connect to it.
   */
  static class MiniServer implements MiniProtocol {
    private static final String DEFAULT_SERVER_ADDRESS = "0.0.0.0";

    private TestDelegationTokenSecretManager secretManager;
    private Server rpcServer;

    @Override // VersionedProtocol
    public long getProtocolVersion(String protocol, 
                                   long clientVersion) throws IOException {
      if (protocol.equals(MiniProtocol.class.getName()))
        return versionID;
      throw new IOException("Unknown protocol: " + protocol);
    }

    @Override // VersionedProtocol
    public ProtocolSignature getProtocolSignature(String protocol, 
                                   long clientVersion,
                                   int clientMethodsHashCode) throws IOException {
      if (protocol.equals(MiniProtocol.class.getName()))
        return new ProtocolSignature(versionID, null);
      throw new IOException("Unknown protocol: " + protocol);
    }

    @Override // MiniProtocol
    public Token<TestDelegationTokenIdentifier> getDelegationToken(Text renewer) 
    throws IOException {
      String owner = UserGroupInformation.getCurrentUser().getUserName();
      String realUser = 
        UserGroupInformation.getCurrentUser().getRealUser() == null ? "":
        UserGroupInformation.getCurrentUser().getRealUser().getUserName();
      TestDelegationTokenIdentifier tokenId = 
        new TestDelegationTokenIdentifier(
            new Text(owner), renewer, new Text(realUser));
      return new Token<TestDelegationTokenIdentifier>(tokenId, secretManager);
    }

    /** Start RPC server */
    MiniServer(Configuration conf, String user, String keytabFile)
    throws IOException {
      UserGroupInformation.setConfiguration(conf);
      UserGroupInformation.loginUserFromKeytab(user, keytabFile);
      secretManager = 
        new TestDelegationTokenSecretManager(24*60*60*1000,
            7*24*60*60*1000,24*60*60*1000,3600000);
      secretManager.startThreads();
      rpcServer = new RPC.Builder(conf).setProtocol(MiniProtocol.class)
          .setInstance(this).setBindAddress(DEFAULT_SERVER_ADDRESS).setPort(0)
          .setNumHandlers(1).setVerbose(false).setSecretManager(secretManager)
          .build();
      rpcServer.start();
    }

    /** Stop RPC server */
    void stop() {
      if(rpcServer != null) rpcServer.stop();
      rpcServer = null;
    }

    /** Get RPC server address */
    InetSocketAddress getAddress() {
      if(rpcServer == null) return null;
      return NetUtils.getConnectAddress(rpcServer);
    }
  }

  long connectToServer(Configuration conf, InetSocketAddress addr)
  throws IOException {
    MiniProtocol client = null;
    try {
      long start = Time.now();
      client = (MiniProtocol) RPC.getProxy(MiniProtocol.class,
          MiniProtocol.versionID, addr, conf);
      long end = Time.now();
      return end - start;
    } finally {
      RPC.stopProxy(client);
    }
  }

  void connectToServerAndGetDelegationToken(
      final Configuration conf, final InetSocketAddress addr) throws IOException {
    MiniProtocol client = null;
    try {
      UserGroupInformation current = UserGroupInformation.getCurrentUser();
      UserGroupInformation proxyUserUgi = 
        UserGroupInformation.createProxyUserForTesting(
            MINI_USER, current, GROUP_NAMES);
      
      try {
        client =  proxyUserUgi.doAs(new PrivilegedExceptionAction<MiniProtocol>() {
          @Override
          public MiniProtocol run() throws IOException {
            MiniProtocol p = (MiniProtocol) RPC.getProxy(MiniProtocol.class,
                MiniProtocol.versionID, addr, conf);
            Token<TestDelegationTokenIdentifier> token;
            token = p.getDelegationToken(new Text(RENEWER));
            currentUgi = UserGroupInformation.createUserForTesting(MINI_USER, 
                GROUP_NAMES);
            SecurityUtil.setTokenService(token, addr);
            currentUgi.addToken(token);
            return p;
          }
        });
      } catch (InterruptedException e) {
        Assert.fail(Arrays.toString(e.getStackTrace()));
      }
    } finally {
      RPC.stopProxy(client);
    }
  }

  long connectToServerUsingDelegationToken(
      final Configuration conf, final InetSocketAddress addr) throws IOException {
    MiniProtocol client = null;
    try {
      long start = Time.now();
      try {
        client = currentUgi.doAs(new PrivilegedExceptionAction<MiniProtocol>() {
          @Override
          public MiniProtocol run() throws IOException {
            return (MiniProtocol) RPC.getProxy(MiniProtocol.class,
                MiniProtocol.versionID, addr, conf);
          }
        });
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      long end = Time.now();
      return end - start;
    } finally {
      RPC.stopProxy(client);
    }
  }

  static void setLoggingLevel(Level level) {
    LogManager.getLogger(Server.class.getName()).setLevel(level);
    ((Log4JLogger)Server.AUDITLOG).getLogger().setLevel(level);
    LogManager.getLogger(Client.class.getName()).setLevel(level);
  }

  /**
   * Run MiniBenchmark with MiniServer as the RPC server.
   * 
   * @param conf - configuration
   * @param count - connect this many times
   * @param keytabKey - key for keytab file in the configuration
   * @param userNameKey - key for user name in the configuration
   * @return average time to connect
   * @throws IOException
   */
  long runMiniBenchmark(Configuration conf,
                        int count,
                        String keytabKey,
                        String userNameKey) throws IOException {
    // get login information
    String user = System.getProperty("user.name");
    if(userNameKey != null)
      user = conf.get(userNameKey, user);
    String keytabFile = null;
    if(keytabKey != null)
      keytabFile = conf.get(keytabKey, keytabFile);
    MiniServer miniServer = null;
    try {
      // start the server
      miniServer = new MiniServer(conf, user, keytabFile);
      InetSocketAddress addr = miniServer.getAddress();

      connectToServer(conf, addr);
      // connect to the server count times
      setLoggingLevel(logLevel);
      long elapsed = 0L;
      for(int idx = 0; idx < count; idx ++) {
        elapsed += connectToServer(conf, addr);
      }
      return elapsed;
    } finally {
      if(miniServer != null) miniServer.stop();
    }
  }

  /**
   * Run MiniBenchmark using delegation token authentication.
   * 
   * @param conf - configuration
   * @param count - connect this many times
   * @param keytabKey - key for keytab file in the configuration
   * @param userNameKey - key for user name in the configuration
   * @return average time to connect
   * @throws IOException
   */
  long runMiniBenchmarkWithDelegationToken(Configuration conf,
                                           int count,
                                           String keytabKey,
                                           String userNameKey)
  throws IOException {
    // get login information
    String user = System.getProperty("user.name");
    if(userNameKey != null)
      user = conf.get(userNameKey, user);
    String keytabFile = null;
    if(keytabKey != null)
      keytabFile = conf.get(keytabKey, keytabFile);
    MiniServer miniServer = null;
    UserGroupInformation.setConfiguration(conf);
    String shortUserName =
      UserGroupInformation.createRemoteUser(user).getShortUserName();
    try {
      conf.setStrings(ProxyUsers.getProxySuperuserGroupConfKey(shortUserName),
          GROUP_NAME_1);
      configureSuperUserIPAddresses(conf, shortUserName);
      // start the server
      miniServer = new MiniServer(conf, user, keytabFile);
      InetSocketAddress addr = miniServer.getAddress();

      connectToServerAndGetDelegationToken(conf, addr);
      // connect to the server count times
      setLoggingLevel(logLevel);
      long elapsed = 0L;
      for(int idx = 0; idx < count; idx ++) {
        elapsed += connectToServerUsingDelegationToken(conf, addr);
      }
      return elapsed;
    } finally {
      if(miniServer != null) miniServer.stop();
    }
  }

  static void printUsage() {
    System.err.println(
        "Usage: MiniRPCBenchmark <numIterations> [<keytabFile> [<userName> " +
        "[useToken|useKerberos [<logLevel>]]]]");
    System.exit(-1);
  }

  public static void main(String[] args) throws Exception {
    System.out.println("Benchmark: RPC session establishment.");
    if(args.length < 1)
      printUsage();

    Configuration conf = new Configuration();
    int count = Integer.parseInt(args[0]);
    if(args.length > 1)
      conf.set(KEYTAB_FILE_KEY, args[1]);
    if(args.length > 2)
      conf.set(USER_NAME_KEY, args[2]);
    boolean useDelegationToken = false;
    if(args.length > 3)
      useDelegationToken = args[3].equalsIgnoreCase("useToken");
    Level l = Level.ERROR;
    if(args.length > 4)
      l = Level.toLevel(args[4]);

    MiniRPCBenchmark mb = new MiniRPCBenchmark(l);
    long elapsedTime = 0;
    if(useDelegationToken) {
      System.out.println(
          "Running MiniRPCBenchmark with delegation token authentication.");
      elapsedTime = mb.runMiniBenchmarkWithDelegationToken(
                              conf, count, KEYTAB_FILE_KEY, USER_NAME_KEY);
    } else {
      String auth = SecurityUtil.getAuthenticationMethod(conf).toString();
      System.out.println(
          "Running MiniRPCBenchmark with " + auth + " authentication.");
      elapsedTime = mb.runMiniBenchmark(
                              conf, count, KEYTAB_FILE_KEY, USER_NAME_KEY);
    }
    System.out.println(org.apache.hadoop.util.VersionInfo.getVersion());
    System.out.println("Number  of  connects: " + count);
    System.out.println("Average connect time: " + ((double)elapsedTime/count));
  }
  
  private void configureSuperUserIPAddresses(Configuration conf,
      String superUserShortName) throws IOException {
    ArrayList<String> ipList = new ArrayList<String>();
    Enumeration<NetworkInterface> netInterfaceList = NetworkInterface
        .getNetworkInterfaces();
    while (netInterfaceList.hasMoreElements()) {
      NetworkInterface inf = netInterfaceList.nextElement();
      Enumeration<InetAddress> addrList = inf.getInetAddresses();
      while (addrList.hasMoreElements()) {
        InetAddress addr = addrList.nextElement();
        ipList.add(addr.getHostAddress());
      }
    }
    StringBuilder builder = new StringBuilder();
    for (String ip : ipList) {
      builder.append(ip);
      builder.append(',');
    }
    builder.append("127.0.1.1,");
    builder.append(InetAddress.getLocalHost().getCanonicalHostName());
    conf.setStrings(ProxyUsers.getProxySuperuserIpConfKey(superUserShortName),
        builder.toString());
  }
}
