content: /*
   * 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.cassandra.net;
  
  import java.net.UnknownHostException;
  import java.util.Collections;
  import java.util.concurrent.ConcurrentMap;
  
  import org.cliffc.high_scale_lib.NonBlockingHashMap;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import org.apache.cassandra.locator.InetAddressAndPort;
  
  /**
   * Map of hosts to their known current messaging versions.
   */
  public class EndpointMessagingVersions
  {
      public volatile int minClusterVersion = MessagingService.current_version;
      private static final Logger logger = LoggerFactory.getLogger(EndpointMessagingVersions.class);
  
      // protocol versions of the other nodes in the cluster
      private final ConcurrentMap<InetAddressAndPort, Integer> versions = new NonBlockingHashMap<>();
  
      /**
       * @return the last version associated with address, or @param version if this is the first such version
       */
      public int set(InetAddressAndPort endpoint, int version)
      {
          logger.trace("Setting version {} for {}", version, endpoint);
  
          Integer v = versions.put(endpoint, version);
          minClusterVersion = Collections.min(versions.values());
          return v == null ? version : v;
      }
  
      public void reset(InetAddressAndPort endpoint)
      {
          logger.trace("Resetting version for {}", endpoint);
          versions.remove(endpoint);
          if (!versions.values().isEmpty())
              minClusterVersion = Collections.min(versions.values());
      }
  
      /**
       * Returns the messaging-version as announced by the given node but capped
       * to the min of the version as announced by the node and {@link MessagingService#current_version}.
       */
      public int get(InetAddressAndPort endpoint)
      {
          Integer v = versions.get(endpoint);
          if (v == null)
          {
              // we don't know the version. assume current. we'll know soon enough if that was incorrect.
              logger.trace("Assuming current protocol version for {}", endpoint);
              return MessagingService.current_version;
          }
          else
              return Math.min(v, MessagingService.current_version);
      }
  
      public int get(String endpoint) throws UnknownHostException
      {
          return get(InetAddressAndPort.getByName(endpoint));
      }
  
      /**
       * Returns the messaging-version exactly as announced by the given endpoint.
       */
      public int getRaw(InetAddressAndPort endpoint)
      {
          Integer v = versions.get(endpoint);
          if (v == null)
              throw new IllegalStateException("getRawVersion() was called without checking knowsVersion() result first");
          return v;
      }
  
      public boolean knows(InetAddressAndPort endpoint)
      {
          return versions.containsKey(endpoint);
      }
  }
  