content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.master;
  
  import alluxio.conf.AlluxioConfiguration;
  import alluxio.conf.PropertyKey;
  import alluxio.exception.status.UnavailableException;
  import alluxio.master.SingleMasterInquireClient.SingleMasterConnectDetails;
  import alluxio.master.ZkMasterInquireClient.ZkMasterConnectDetails;
  import alluxio.security.user.UserState;
  import alluxio.uri.Authority;
  import alluxio.util.ConfigurationUtils;
  import alluxio.util.network.NetworkAddressUtils;
  import alluxio.util.network.NetworkAddressUtils.ServiceType;
  
  import java.net.InetSocketAddress;
  import java.util.List;
  import javax.annotation.concurrent.ThreadSafe;
  
  /**
   * Client for determining the primary master.
   */
  @ThreadSafe
  public interface MasterInquireClient {
    /**
     * @return the rpc address of the primary master. The implementation should perform retries if
     *         appropriate
     * @throws UnavailableException if the primary rpc address cannot be determined
     */
    InetSocketAddress getPrimaryRpcAddress() throws UnavailableException;
  
    /**
     * @return a list of all masters' RPC addresses
     * @throws UnavailableException if the master rpc addresses cannot be determined
     */
    List<InetSocketAddress> getMasterRpcAddresses() throws UnavailableException;
  
    /**
     * Returns canonical connect details representing how this client connects to the master.
     *
     * @return the connect details
     */
    ConnectDetails getConnectDetails();
  
    /**
     * Interface for representing master inquire connect details.
     *
     * Connect info should be unique so that if two inquire clients have the same connect info, they
     * connect to the same cluster.
     */
    interface ConnectDetails {
      /**
       * @return an authority string representing the connect details
       */
      Authority toAuthority();
  
      @Override
      boolean equals(Object obj);
  
      @Override
      int hashCode();
    }
  
    /**
     * Factory for getting a master inquire client.
     */
    class Factory {
      /**
       * @param conf configuration for creating the master inquire client
       * @param userState the user state for the client
       * @return a master inquire client
       */
      public static MasterInquireClient create(AlluxioConfiguration conf, UserState userState) {
        if (conf.getBoolean(PropertyKey.ZOOKEEPER_ENABLED)) {
          return ZkMasterInquireClient.getClient(conf.getString(PropertyKey.ZOOKEEPER_ADDRESS),
              conf.getString(PropertyKey.ZOOKEEPER_ELECTION_PATH),
              conf.getString(PropertyKey.ZOOKEEPER_LEADER_PATH),
              conf.getInt(PropertyKey.ZOOKEEPER_LEADER_INQUIRY_RETRY_COUNT),
              conf.getBoolean(PropertyKey.ZOOKEEPER_AUTH_ENABLED));
        } else {
          List<InetSocketAddress> addresses = ConfigurationUtils.getMasterRpcAddresses(conf);
          if (addresses.size() > 1) {
            return new PollingMasterInquireClient(addresses, conf, userState,
                alluxio.grpc.ServiceType.META_MASTER_CLIENT_SERVICE);
          } else {
            return new SingleMasterInquireClient(addresses.get(0));
          }
        }
      }
  
      /**
       * @param addresses the addresses to use for the client
       * @param conf configuration for creating the master inquire client
       * @param userState the user state for the client
       * @return a master inquire client using the addresses given
       */
      public static MasterInquireClient createForAddresses(
          List<InetSocketAddress> addresses, AlluxioConfiguration conf, UserState userState) {
        if (addresses.size() > 1) {
          return new PollingMasterInquireClient(addresses, conf, userState,
              alluxio.grpc.ServiceType.META_MASTER_CLIENT_SERVICE);
        } else {
          return new SingleMasterInquireClient(addresses.get(0));
        }
      }
  
      /**
       * @param conf configuration for creating the master inquire client
       * @param userState the user state for the client
       * @return a master inquire client
       */
      public static MasterInquireClient createForJobMaster(AlluxioConfiguration conf,
          UserState userState) {
        if (conf.getBoolean(PropertyKey.ZOOKEEPER_ENABLED)) {
          return ZkMasterInquireClient.getClient(conf.getString(PropertyKey.ZOOKEEPER_ADDRESS),
              conf.getString(PropertyKey.ZOOKEEPER_JOB_ELECTION_PATH),
              conf.getString(PropertyKey.ZOOKEEPER_JOB_LEADER_PATH),
              conf.getInt(PropertyKey.ZOOKEEPER_LEADER_INQUIRY_RETRY_COUNT),
              conf.getBoolean(PropertyKey.ZOOKEEPER_AUTH_ENABLED));
        } else {
          List<InetSocketAddress> addresses = ConfigurationUtils.getJobMasterRpcAddresses(conf);
          if (addresses.size() > 1) {
            return new PollingMasterInquireClient(addresses, conf, userState,
                alluxio.grpc.ServiceType.JOB_MASTER_CLIENT_SERVICE);
          } else {
            return new SingleMasterInquireClient(addresses.get(0));
          }
        }
      }
  
      /**
       * @param conf configuration for creating the master inquire client
       * @return the connect string represented by the configuration
       */
      public static ConnectDetails getConnectDetails(AlluxioConfiguration conf) {
        if (conf.getBoolean(PropertyKey.ZOOKEEPER_ENABLED)) {
          return new ZkMasterConnectDetails(conf.getString(PropertyKey.ZOOKEEPER_ADDRESS),
              conf.getString(PropertyKey.ZOOKEEPER_LEADER_PATH));
        } else if (ConfigurationUtils.getMasterRpcAddresses(conf).size() > 1) {
          return new PollingMasterInquireClient.MultiMasterConnectDetails(
              ConfigurationUtils.getMasterRpcAddresses(conf));
        } else {
          return new SingleMasterConnectDetails(
              NetworkAddressUtils.getConnectAddress(ServiceType.MASTER_RPC, conf));
        }
      }
  
      private Factory() {
      } // Not intended for instantiation.
    }
  }
  