Skip to content

Commit

Permalink
Support querying LocalStrategy tables with any partitioner
Browse files Browse the repository at this point in the history
patch by Sam Tunnicliffe; reviewed by Stefan Miklosovic and Marcus Eriksson for CASSANDRA-19692
  • Loading branch information
beobal committed Jun 12, 2024
1 parent a09ab63 commit 63648c1
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
5.1
* Support querying LocalStrategy tables with any partitioner (CASSANDRA-19692)
* Relax slow_query_log_timeout for MultiNodeSAITest (CASSANDRA-19693)
* Audit Log entries are missing identity for mTLS connections (CASSANDRA-19669)
* Add support for the BETWEEN operator in WHERE clauses (CASSANDRA-19604)
Expand Down
29 changes: 22 additions & 7 deletions src/java/org/apache/cassandra/locator/LocalStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
*/
package org.apache.cassandra.locator;

import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.tcm.ClusterMetadata;
Expand All @@ -33,6 +34,8 @@
public class LocalStrategy extends SystemStrategy
{
private static final ReplicationFactor RF = ReplicationFactor.fullOnly(1);
private static final Map<IPartitioner, EntireRange> perPartitionerRanges = new IdentityHashMap<>();

public LocalStrategy(String keyspaceName, Map<String, String> configOptions)
{
super(keyspaceName, configOptions);
Expand All @@ -41,13 +44,13 @@ public LocalStrategy(String keyspaceName, Map<String, String> configOptions)
@Override
public EndpointsForRange calculateNaturalReplicas(Token token, ClusterMetadata metadata)
{
return EntireRange.localReplicas;
return getRange(token.getPartitioner()).localReplicas;
}

@Override
public DataPlacement calculateDataPlacement(Epoch epoch, List<Range<Token>> ranges, ClusterMetadata metadata)
{
return EntireRange.placement;
return getRange(ranges.get(0).left.getPartitioner()).placement;
}

@Override
Expand All @@ -56,16 +59,28 @@ public ReplicationFactor getReplicationFactor()
return RF;
}

private EntireRange getRange(IPartitioner partitioner)
{
return perPartitionerRanges.computeIfAbsent(partitioner, EntireRange::new);
}

/**
* For lazy initialisation. In some circumstances, we may want to instantiate LocalStrategy without initialising
* DatabaseDescriptor; FQL replay is one such usage as we initialise the KeyspaceMetadata objects, which now eagerly
* creates the replication strategy.
*/
static class EntireRange
{
public static final Range<Token> entireRange = new Range<>(DatabaseDescriptor.getPartitioner().getMinimumToken(), DatabaseDescriptor.getPartitioner().getMinimumToken());
public static final EndpointsForRange localReplicas = EndpointsForRange.of(new Replica(FBUtilities.getBroadcastAddressAndPort(), entireRange, true));
public static final DataPlacement placement = new DataPlacement(ReplicaGroups.builder().withReplicaGroup(VersionedEndpoints.forRange(Epoch.FIRST, localReplicas)).build(),
ReplicaGroups.builder().withReplicaGroup(VersionedEndpoints.forRange(Epoch.FIRST, localReplicas)).build());
public final Range<Token> entireRange;
public final EndpointsForRange localReplicas;
public final DataPlacement placement;

private EntireRange(IPartitioner partitioner)
{
entireRange = new Range<>(partitioner.getMinimumToken(), partitioner.getMinimumToken());
localReplicas = EndpointsForRange.of(new Replica(FBUtilities.getBroadcastAddressAndPort(), entireRange, true));
ReplicaGroups rg = ReplicaGroups.builder(1).withReplicaGroup(VersionedEndpoints.forRange(Epoch.FIRST, localReplicas)).build();
placement = new DataPlacement(rg, rg);
}
}
}
56 changes: 56 additions & 0 deletions test/unit/org/apache/cassandra/cql3/SystemKeyspaceQueryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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.cql3;

import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.utils.TimeUUID;

import static org.apache.cassandra.db.SystemKeyspace.BATCHES;
import static org.apache.cassandra.db.SystemKeyspace.LOCAL;
import static org.apache.cassandra.db.SystemKeyspace.METADATA_LOG;
import static org.apache.cassandra.db.SystemKeyspace.SNAPSHOT_TABLE_NAME;
import static org.apache.cassandra.schema.SchemaConstants.SYSTEM_KEYSPACE_NAME;

public class SystemKeyspaceQueryTest extends CQLTester
{
@BeforeClass
public static void setUp()
{
requireNetwork();
}

@Test
public void testSelectsWithDifferentPartitioners()
{
// Verify that querying tables which use ReversedLongLocalPartitioner doesn't cause an error
assertRowCountNet(executeNet(String.format("SELECT * FROM %s.%s WHERE epoch = 1",
SYSTEM_KEYSPACE_NAME, METADATA_LOG)), 0);
assertRowCountNet(executeNet(String.format("SELECT * FROM %s.%s WHERE epoch = 1",
SYSTEM_KEYSPACE_NAME, SNAPSHOT_TABLE_NAME)), 0);
// system.batches table uses LocalPartitioner
assertRowCountNet(executeNet(String.format("SELECT * FROM %s.%s WHERE id = %s",
SYSTEM_KEYSPACE_NAME, BATCHES,
TimeUUID.Generator.nextTimeUUID())), 0);
// Query a table using the global system partitioner
assertRowCountNet(executeNet(String.format("SELECT * FROM %s.%s WHERE key = 'invalidkey'",
SYSTEM_KEYSPACE_NAME, LOCAL)), 0);
}
}

0 comments on commit 63648c1

Please sign in to comment.