public ProtocolVersion highestCommon()

in core/src/main/java/com/datastax/oss/driver/internal/core/DefaultProtocolVersionRegistry.java [115:220]


  public ProtocolVersion highestCommon(Collection<Node> nodes) {
    if (nodes == null || nodes.isEmpty()) {
      throw new IllegalArgumentException("Expected at least one node");
    }

    // Start with all non-beta versions (beta versions are always forced, and we don't call this
    // method if the version was forced).
    Set<ProtocolVersion> candidates = new LinkedHashSet<>();
    for (ProtocolVersion version : allVersions) {
      if (!version.isBeta()) {
        candidates.add(version);
      }
    }
    // Keep an unfiltered copy in case we need to throw an exception below
    ImmutableList<ProtocolVersion> initialCandidates = ImmutableList.copyOf(candidates);

    // For each node, remove the versions it doesn't support
    for (Node node : nodes) {

      // We can't trust the Cassandra version reported by DSE to infer the maximum OSS protocol
      // supported. For example DSE 6 reports release_version 4.0-SNAPSHOT, but only supports OSS
      // protocol v4 (while Cassandra 4 will support v5). So we treat DSE separately.
      Version dseVersion = (Version) node.getExtras().get(DseNodeProperties.DSE_VERSION);
      if (dseVersion != null) {
        LOG.debug("[{}] Node {} reports DSE version {}", logPrefix, node.getEndPoint(), dseVersion);
        dseVersion = dseVersion.nextStable();
        if (dseVersion.compareTo(DSE_4_7_0) < 0) {
          throw new UnsupportedProtocolVersionException(
              node.getEndPoint(),
              String.format(
                  "Node %s reports DSE version %s, "
                      + "but the driver only supports 4.7.0 and above",
                  node.getEndPoint(), dseVersion),
              initialCandidates);
        } else if (dseVersion.compareTo(DSE_5_0_0) < 0) {
          // DSE 4.7.x, 4.8.x
          removeHigherThan(DefaultProtocolVersion.V3, null, candidates);
        } else if (dseVersion.compareTo(DSE_5_1_0) < 0) {
          // DSE 5.0
          removeHigherThan(DefaultProtocolVersion.V4, null, candidates);
        } else if (dseVersion.compareTo(DSE_6_0_0) < 0) {
          // DSE 5.1
          removeHigherThan(DefaultProtocolVersion.V4, DseProtocolVersion.DSE_V1, candidates);
        } else if (dseVersion.compareTo(DSE_7_0_0) < 0) {
          // DSE 6
          removeHigherThan(DefaultProtocolVersion.V4, DseProtocolVersion.DSE_V2, candidates);
        } else {
          // DSE 7.0
          removeHigherThan(DefaultProtocolVersion.V5, DseProtocolVersion.DSE_V2, candidates);
        }
      } else { // not DSE
        Version cassandraVersion = node.getCassandraVersion();
        if (cassandraVersion == null) {
          LOG.warn(
              "[{}] Node {} reports neither DSE version nor Cassandra version, "
                  + "ignoring it from optimal protocol version computation",
              logPrefix,
              node.getEndPoint());
          continue;
        }
        cassandraVersion = cassandraVersion.nextStable();
        LOG.debug(
            "[{}] Node {} reports Cassandra version {}",
            logPrefix,
            node.getEndPoint(),
            cassandraVersion);
        if (cassandraVersion.compareTo(Version.V2_1_0) < 0) {
          throw new UnsupportedProtocolVersionException(
              node.getEndPoint(),
              String.format(
                  "Node %s reports Cassandra version %s, "
                      + "but the driver only supports 2.1.0 and above",
                  node.getEndPoint(), cassandraVersion),
              ImmutableList.of(DefaultProtocolVersion.V3, DefaultProtocolVersion.V4));
        } else if (cassandraVersion.compareTo(Version.V2_2_0) < 0) {
          // 2.1.0
          removeHigherThan(DefaultProtocolVersion.V3, null, candidates);
        } else if (cassandraVersion.compareTo(Version.V4_0_0) < 0) {
          // 2.2, 3.x
          removeHigherThan(DefaultProtocolVersion.V4, null, candidates);
        } else {
          // 4.0
          removeHigherThan(DefaultProtocolVersion.V5, null, candidates);
        }
      }
    }

    // If we have versions left, return the highest one
    ProtocolVersion max = null;
    for (ProtocolVersion candidate : candidates) {
      if (max == null || max.getCode() < candidate.getCode()) {
        max = candidate;
      }
    }
    if (max == null) { // Note: with the current algorithm, this never happens
      throw new UnsupportedProtocolVersionException(
          null,
          String.format(
              "Could not determine a common protocol version, "
                  + "enable DEBUG logs for '%s' for more details",
              LOG.getName()),
          initialCandidates);
    } else {
      return max;
    }
  }