CASSANDRASC-90 Token-ranges endpoint fix to unwrap token-ranges by the partitioner's boundary for a single node clusters
Patch by Arjun Ashok; Reviewed by Francisco Guerrero, Yifan Cai for CASSANDRASC-90
diff --git a/CHANGES.txt b/CHANGES.txt
index d61a23f..ad51d93 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,6 @@
1.0.0
-----
+ * Fix Sidecar TokenRangeReplicas endpoint to unwrap the token-range by partitioner's range for a single node clusters (CASSANDRASC-90)
* Expose TTL option for the create snapshot endpoint (CASSANDRASC-85)
* Allow DriverUtils to be pluggable (CASSANDRASC-88)
* Add JMX health checks during the periodic health checks (CASSANDRASC-87)
diff --git a/adapters/base/src/main/java/org/apache/cassandra/sidecar/adapters/base/TokenRangeReplicas.java b/adapters/base/src/main/java/org/apache/cassandra/sidecar/adapters/base/TokenRangeReplicas.java
index 43fe5d8..a46437c 100644
--- a/adapters/base/src/main/java/org/apache/cassandra/sidecar/adapters/base/TokenRangeReplicas.java
+++ b/adapters/base/src/main/java/org/apache/cassandra/sidecar/adapters/base/TokenRangeReplicas.java
@@ -69,7 +69,7 @@
Partitioner partitioner,
Set<String> replicaSet)
{
- if (start.compareTo(end) > 0)
+ if (start.compareTo(end) >= 0)
{
return unwrapRange(start, end, partitioner, replicaSet);
}
@@ -216,10 +216,11 @@
*/
public static List<TokenRangeReplicas> normalize(List<TokenRangeReplicas> ranges)
{
-
if (ranges.stream().noneMatch(r -> r.partitioner.minToken.compareTo(r.start()) == 0))
{
- LOGGER.warn("{} based minToken does not exist in the token ranges", Partitioner.class.getName());
+ LOGGER.warn("{} based minToken does not exist in the token ranges", ranges.stream()
+ .findFirst()
+ .get().partitioner.name());
}
return deoverlap(ranges);
diff --git a/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BaseTokenRangeIntegrationTest.java b/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BaseTokenRangeIntegrationTest.java
index 250bdee..bc86a8b 100644
--- a/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BaseTokenRangeIntegrationTest.java
+++ b/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BaseTokenRangeIntegrationTest.java
@@ -37,6 +37,7 @@
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.junit5.VertxTestContext;
+import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.distributed.UpgradeableCluster;
import org.apache.cassandra.distributed.api.IInstanceConfig;
import org.apache.cassandra.distributed.api.TokenSupplier;
@@ -275,6 +276,8 @@
assertThat(mappingResponse).isNotNull();
assertThat(mappingResponse.readReplicas()).isNotNull();
assertThat(mappingResponse.writeReplicas()).isNotNull();
+ validateRanges(mappingResponse.writeReplicas());
+ validateRanges(mappingResponse.readReplicas());
TokenRangeReplicasResponse.ReplicaInfo readReplica = mappingResponse.readReplicas().get(0);
assertThat(readReplica.replicasByDatacenter()).isNotNull().hasSize(dcReplication.size());
TokenRangeReplicasResponse.ReplicaInfo writeReplica = mappingResponse.writeReplicas().get(0);
@@ -291,4 +294,17 @@
.isGreaterThanOrEqualTo(replicationFactor);
}
}
+
+ private void validateRanges(List<TokenRangeReplicasResponse.ReplicaInfo> replicaRanges)
+ {
+ // Ranges should not be empty
+ replicaRanges.forEach(r -> assertThat(r.start()).isNotEqualTo(r.end()));
+ // Ranges should include partitioner start and end
+ assertThat(replicaRanges.stream()
+ .map(TokenRangeReplicasResponse.ReplicaInfo::start)
+ .anyMatch(s -> s.equals(Murmur3Partitioner.MINIMUM.toString()))).isTrue();
+ assertThat(replicaRanges.stream()
+ .map(TokenRangeReplicasResponse.ReplicaInfo::end)
+ .anyMatch(s -> s.equals(Long.toString(Murmur3Partitioner.MAXIMUM)))).isTrue();
+ }
}
diff --git a/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BasicRf1Test.java b/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BasicRf1Test.java
index 4a63ef1..bd507dd 100644
--- a/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BasicRf1Test.java
+++ b/src/test/integration/org/apache/cassandra/sidecar/routes/tokenrange/BasicRf1Test.java
@@ -50,4 +50,17 @@
context.completeNow();
});
}
+
+ @CassandraIntegrationTest()
+ void retrieveMappingSingleNodeRf1(VertxTestContext context) throws Exception
+ {
+ createTestKeyspace();
+ retrieveMappingWithKeyspace(context, TEST_KEYSPACE, response -> {
+ assertThat(response.statusCode()).isEqualTo(HttpResponseStatus.OK.code());
+ TokenRangeReplicasResponse mappingResponse = response.bodyAsJson(TokenRangeReplicasResponse.class);
+ assertMappingResponseOK(mappingResponse, 1, Collections.singleton("datacenter1"));
+ context.completeNow();
+ });
+ }
+
}