Uploaded image for project: 'Cassandra'
  1. Cassandra
  2. CASSANDRA-18999

Gossiper::hasMajorVersion3Nodes returns true when a cluster is upgrading patch version without Cassandra 3 nodes.

    XMLWordPrintableJSON

Details

    • Correctness - Transient Incorrect Response
    • Low
    • Low Hanging Fruit
    • Code Inspection
    • All
    • None
    • 4.0
    • Hide

      4.x: Added new test cases to GossiperTest.java which validate that the Gossiper works correctly given the behavior described in the ticket. 

       

      5.0: Removed Gossiper::hasMajorVersion3Nodes and all references to the function. 

      Show
      4.x: Added new test cases to GossiperTest.java which validate that the Gossiper works correctly given the behavior described in the ticket.    5.0: Removed Gossiper::hasMajorVersion3Nodes and all references to the function. 

    Description

      When working on https://issues.apache.org/jira/browse/CASSANDRA-18968 we found that Gossiper::hasMajorVersion3Nodes will return true when the cluster is undergoing an upgrade from a patch version even if the cluster has no Cassandra 3 nodes in it.

      This can be reproduced by running this Gossiper test:

          @Test
          public void testHasVersion3NodesShouldReturnFalseWhenNoVersion3NodesDetectedAndCassandra4UpgradeInProgress() throws Exception
          {
              Gossiper.instance.start(0);
              Gossiper.instance.expireUpgradeFromVersion();
      
              VersionedValue.VersionedValueFactory factory = new VersionedValue.VersionedValueFactory(null);
              EndpointState es = new EndpointState((HeartBeatState) null);
              es.addApplicationState(ApplicationState.RELEASE_VERSION, factory.releaseVersion(CURRENT_VERSION.toString()));
              Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.1"), es);
              Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.1"));
      
              es = new EndpointState((HeartBeatState) null);
              String previousPatchVersion = String.valueOf(CURRENT_VERSION.major) + '.' + (CURRENT_VERSION.minor) + '.' + (CURRENT_VERSION.patch - 1);
              es.addApplicationState(ApplicationState.RELEASE_VERSION, factory.releaseVersion(previousPatchVersion));
              Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.2"), es);
              Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.2"));
              assertFalse(Gossiper.instance.hasMajorVersion3Nodes());
          }
      

      This seems to be because of https://github.com/apache/cassandra/blob/cassandra-4.1/src/java/org/apache/cassandra/gms/Gossiper.java#L2360, where an upgrade in progress is possible but we are not upgrading from a lower family version (i.e from 4.1.1 to 4.1.2).

      From the comment in this function, it seems instead of the existing check, we would want to iterate over all known endpoints in gossip and return true if any of them do not have a version (similar to https://github.com/apache/cassandra/blob/cassandra-4.1/src/java/org/apache/cassandra/gms/Gossiper.java#L227-L236) 

      Attachments

        Issue Links

          Activity

            People

              isaacreath Isaac Reath
              isaacreath Isaac Reath
              Isaac Reath
              Paulo Motta, Stefan Miklosovic
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 1h 20m
                  1h 20m