This is an automated email from the ASF dual-hosted git repository. ifesdjeen pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push: new 7623e4678b The result of applying a metadata snapshot via ForceSnapshot should return the correct set of modified keys 7623e4678b is described below commit 7623e4678b8ef131434f1de3522c6425c092dff9 Author: Alex Petrov <oleksandr.pet...@gmail.com> AuthorDate: Mon Mar 25 10:25:50 2024 +0100 The result of applying a metadata snapshot via ForceSnapshot should return the correct set of modified keys Patch by Alex Petrov; reviewed by Marcus Eriksson for CASSANDRA-19128. --- .../org/apache/cassandra/tcm/MetadataKeys.java | 47 +++++ .../cassandra/tcm/ownership/PlacementDeltas.java | 22 +++ .../tcm/transformations/CustomTransformation.java | 44 +++++ .../tcm/transformations/ForceSnapshot.java | 4 +- .../cassandra/tcm/transformations/PrepareMove.java | 6 + .../test/log/ClusterMetadataTestHelper.java | 3 +- .../distributed/test/log/MetadataKeysTest.java | 220 +++++++++++++++++++++ .../apache/cassandra/harry/gen/EntropySource.java | 5 +- .../org/apache/cassandra/harry/gen/Generators.java | 42 +++- .../org/apache/cassandra/tcm/log/LocalLogTest.java | 10 +- 10 files changed, 388 insertions(+), 15 deletions(-) diff --git a/src/java/org/apache/cassandra/tcm/MetadataKeys.java b/src/java/org/apache/cassandra/tcm/MetadataKeys.java index fda509186b..8028007815 100644 --- a/src/java/org/apache/cassandra/tcm/MetadataKeys.java +++ b/src/java/org/apache/cassandra/tcm/MetadataKeys.java @@ -18,10 +18,17 @@ package org.apache.cassandra.tcm; +import java.util.HashSet; import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; import com.google.common.collect.ImmutableSet; +import org.apache.cassandra.tcm.extensions.ExtensionKey; +import org.apache.cassandra.tcm.extensions.ExtensionValue; + public class MetadataKeys { public static final String CORE_NS = MetadataKeys.class.getPackage().getName().toLowerCase(Locale.ROOT); @@ -52,4 +59,44 @@ public class MetadataKeys return new MetadataKey(b.toString()); } + public static ImmutableSet<MetadataKey> diffKeys(ClusterMetadata before, ClusterMetadata after) + { + ImmutableSet.Builder<MetadataKey> builder = new ImmutableSet.Builder<>(); + diffKeys(before, after, builder); + return builder.build(); + } + + private static void diffKeys(ClusterMetadata before, ClusterMetadata after, ImmutableSet.Builder<MetadataKey> builder) + { + checkKey(before, after, builder, cm -> cm.schema, MetadataKeys.SCHEMA); + checkKey(before, after, builder, cm -> cm.directory, MetadataKeys.NODE_DIRECTORY); + checkKey(before, after, builder, cm -> cm.tokenMap, MetadataKeys.TOKEN_MAP); + checkKey(before, after, builder, cm -> cm.placements, MetadataKeys.DATA_PLACEMENTS); + checkKey(before, after, builder, cm -> cm.lockedRanges, MetadataKeys.LOCKED_RANGES); + checkKey(before, after, builder, cm -> cm.inProgressSequences, MetadataKeys.IN_PROGRESS_SEQUENCES); + + Set<ExtensionKey<?,?>> added = new HashSet<>(after.extensions.keySet()); + for (Map.Entry<ExtensionKey<?, ?>, ExtensionValue<?>> entry : before.extensions.entrySet()) + { + ExtensionKey<?, ?> key = entry.getKey(); + added.remove(key); + + if (after.extensions.containsKey(key)) + checkKey(before, after, builder, cm -> cm.extensions.get(key), key); + else + builder.add(key); + } + + for (ExtensionKey<?, ?> key : added) + builder.add(key); + } + + private static void checkKey(ClusterMetadata before, ClusterMetadata after, ImmutableSet.Builder<MetadataKey> builder, Function<ClusterMetadata, MetadataValue<?>> extract, MetadataKey key) + { + MetadataValue<?> vBefore = extract.apply(before); + MetadataValue<?> vAfter = extract.apply(after); + + if (!vBefore.equals(vAfter)) + builder.add(key); + } } diff --git a/src/java/org/apache/cassandra/tcm/ownership/PlacementDeltas.java b/src/java/org/apache/cassandra/tcm/ownership/PlacementDeltas.java index 6b5b817984..6ba80a854b 100644 --- a/src/java/org/apache/cassandra/tcm/ownership/PlacementDeltas.java +++ b/src/java/org/apache/cassandra/tcm/ownership/PlacementDeltas.java @@ -77,6 +77,28 @@ public class PlacementDeltas extends ReplicationMap<PlacementDeltas.PlacementDel return builder.build(); } + @Override + public boolean isEmpty() + { + if (super.isEmpty()) + return true; + + for (Map.Entry<ReplicationParams, PlacementDelta> e : map.entrySet()) + { + if (!e.getValue().reads.removals.isEmpty()) + return false; + if (!e.getValue().reads.additions.isEmpty()) + return false; + + if (!e.getValue().writes.removals.isEmpty()) + return false; + if (!e.getValue().writes.additions.isEmpty()) + return false; + } + + return true; + } + public static PlacementDeltas empty() { return EMPTY; diff --git a/src/java/org/apache/cassandra/tcm/transformations/CustomTransformation.java b/src/java/org/apache/cassandra/tcm/transformations/CustomTransformation.java index a1eb9ab5cd..bcacba652d 100644 --- a/src/java/org/apache/cassandra/tcm/transformations/CustomTransformation.java +++ b/src/java/org/apache/cassandra/tcm/transformations/CustomTransformation.java @@ -44,6 +44,7 @@ public class CustomTransformation implements Transformation { registerExtension(PokeString.NAME, new PokeString.TransformSerializer()); registerExtension(PokeInt.NAME, new PokeInt.TransformSerializer()); + registerExtension(ClearInt.NAME, new ClearInt.TransformSerializer()); } public CustomTransformation(String extension, Transformation child) @@ -291,4 +292,47 @@ public class CustomTransformation implements Transformation } } } + + public static class ClearInt implements Transformation + { + + public static final String NAME = ClearInt.class.getName(); + + public static final ClearInt instance = new ClearInt(); + + private ClearInt() {} + public Kind kind() + { + return Kind.CUSTOM; + } + + public Result execute(ClusterMetadata prev) + { + return Transformation.success(prev.transformer().without(PokeInt.METADATA_KEY), LockedRanges.AffectedRanges.EMPTY); + } + + public String toString() + { + return "clearInt"; + } + + public static class TransformSerializer implements AsymmetricMetadataSerializer<Transformation, ClearInt> + { + private TransformSerializer() {} + + public void serialize(Transformation t, DataOutputPlus out, Version version) throws IOException + { + } + + public ClearInt deserialize(DataInputPlus in, Version version) throws IOException + { + return instance; + } + + public long serializedSize(Transformation t, Version version) + { + return 0; + } + } + } } \ No newline at end of file diff --git a/src/java/org/apache/cassandra/tcm/transformations/ForceSnapshot.java b/src/java/org/apache/cassandra/tcm/transformations/ForceSnapshot.java index be9fde80db..b0987cd535 100644 --- a/src/java/org/apache/cassandra/tcm/transformations/ForceSnapshot.java +++ b/src/java/org/apache/cassandra/tcm/transformations/ForceSnapshot.java @@ -49,9 +49,9 @@ public class ForceSnapshot implements Transformation return Kind.FORCE_SNAPSHOT; } - public Result execute(ClusterMetadata metadata) + public Result execute(ClusterMetadata prev) { - return new Success(baseState, LockedRanges.AffectedRanges.EMPTY, MetadataKeys.CORE_METADATA); + return new Success(baseState, LockedRanges.AffectedRanges.EMPTY, MetadataKeys.diffKeys(prev, baseState)); } public String toString() diff --git a/src/java/org/apache/cassandra/tcm/transformations/PrepareMove.java b/src/java/org/apache/cassandra/tcm/transformations/PrepareMove.java index 71fc3bf667..fdd82c3a6c 100644 --- a/src/java/org/apache/cassandra/tcm/transformations/PrepareMove.java +++ b/src/java/org/apache/cassandra/tcm/transformations/PrepareMove.java @@ -67,6 +67,12 @@ public class PrepareMove implements Transformation this.streamData = streamData; } + @VisibleForTesting + public NodeId nodeId() + { + return nodeId; + } + @Override public String toString() { diff --git a/test/distributed/org/apache/cassandra/distributed/test/log/ClusterMetadataTestHelper.java b/test/distributed/org/apache/cassandra/distributed/test/log/ClusterMetadataTestHelper.java index 684033d534..52126cd7ec 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/log/ClusterMetadataTestHelper.java +++ b/test/distributed/org/apache/cassandra/distributed/test/log/ClusterMetadataTestHelper.java @@ -87,7 +87,6 @@ import org.apache.cassandra.tcm.transformations.Register; import org.apache.cassandra.tcm.transformations.cms.AdvanceCMSReconfiguration; import org.apache.cassandra.tcm.transformations.cms.PrepareCMSReconfiguration; import org.apache.cassandra.utils.ByteBufferUtil; -import org.apache.cassandra.tcm.transformations.cms.Initialize; import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.Throwables; @@ -125,6 +124,7 @@ public class ClusterMetadataTestHelper { ClusterMetadata current = new ClusterMetadata(DatabaseDescriptor.getPartitioner()); LocalLog log = LocalLog.logSpec() + .withInitialState(current) .createLog(); ResettableClusterMetadataService service = new ResettableClusterMetadataService(new UniformRangePlacement(), MetadataSnapshots.NO_OP, @@ -134,7 +134,6 @@ public class ClusterMetadataTestHelper true); log.readyUnchecked(); log.bootstrap(FBUtilities.getBroadcastAddressAndPort()); - service.commit(new Initialize(current)); QueryProcessor.registerStatementInvalidatingListener(); service.mark(); return service; diff --git a/test/distributed/org/apache/cassandra/distributed/test/log/MetadataKeysTest.java b/test/distributed/org/apache/cassandra/distributed/test/log/MetadataKeysTest.java new file mode 100644 index 0000000000..04acd2369a --- /dev/null +++ b/test/distributed/org/apache/cassandra/distributed/test/log/MetadataKeysTest.java @@ -0,0 +1,220 @@ +/* + * 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.distributed.test.log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.dht.Murmur3Partitioner; +import org.apache.cassandra.harry.gen.EntropySource; +import org.apache.cassandra.harry.gen.Generator; +import org.apache.cassandra.harry.gen.Generators; +import org.apache.cassandra.harry.gen.rng.JdkRandomEntropySource; +import org.apache.cassandra.harry.sut.TokenPlacementModel; +import org.apache.cassandra.locator.InetAddressAndPort; +import org.apache.cassandra.tcm.AtomicLongBackedProcessor; +import org.apache.cassandra.tcm.ClusterMetadata; +import org.apache.cassandra.tcm.ClusterMetadataService; +import org.apache.cassandra.tcm.MetadataKey; +import org.apache.cassandra.tcm.MetadataKeys; +import org.apache.cassandra.tcm.Transformation; +import org.apache.cassandra.tcm.membership.Location; +import org.apache.cassandra.tcm.membership.NodeAddresses; +import org.apache.cassandra.tcm.membership.NodeId; +import org.apache.cassandra.tcm.membership.NodeState; +import org.apache.cassandra.tcm.membership.NodeVersion; +import org.apache.cassandra.tcm.ownership.PlacementProvider; +import org.apache.cassandra.tcm.sequences.BootstrapAndJoin; +import org.apache.cassandra.tcm.sequences.LeaveStreams; +import org.apache.cassandra.tcm.sequences.Move; +import org.apache.cassandra.tcm.sequences.UnbootstrapAndLeave; +import org.apache.cassandra.tcm.transformations.CustomTransformation; +import org.apache.cassandra.tcm.transformations.PrepareJoin; +import org.apache.cassandra.tcm.transformations.PrepareLeave; +import org.apache.cassandra.tcm.transformations.PrepareMove; +import org.apache.cassandra.tcm.transformations.Register; + +public class MetadataKeysTest extends CMSTestBase +{ + static + { + DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); + } + + @Test + public void metadataKeysChangeTest() throws Exception + { + Generator<Register> genRegister = new Generators.InetAddrAndPortGenerator() + .zip(Generators.pick("datacenter1", "datacenter2"), + Generators.pick("rack1", "rack2"), + (InetAddressAndPort addr, String dc, String rack) -> { + return new Register(new NodeAddresses(addr), + new Location(dc, rack), + NodeVersion.CURRENT); + }); + EntropySource rng = new JdkRandomEntropySource(1l); + + try (CMSTestBase.CMSSut sut = new CMSTestBase.CMSSut(AtomicLongBackedProcessor::new, false, new TokenPlacementModel.SimpleReplicationFactor(3))) + { + Register register = genRegister.generate(rng); + checkDiff(sut.service, register); + sut.service.commit(register); + + { + PrepareJoin prepareJoin = prepareJoinGenerator(sut.service.metadata(), sut.service.placementProvider()).generate(rng); + checkDiff(sut.service, prepareJoin); + sut.service.commit(prepareJoin); + + BootstrapAndJoin bootstrapAndJoin = (BootstrapAndJoin) sut.service.metadata().inProgressSequences.get(prepareJoin.nodeId()); + checkDiff(sut.service, bootstrapAndJoin.startJoin); + sut.service.commit(bootstrapAndJoin.startJoin); + + checkDiff(sut.service, bootstrapAndJoin.midJoin); + sut.service.commit(bootstrapAndJoin.midJoin); + + checkDiff(sut.service, bootstrapAndJoin.finishJoin); + sut.service.commit(bootstrapAndJoin.finishJoin); + } + + { + PrepareMove prepareMove = prepareMoveGenerator(sut.service.metadata(), sut.service.placementProvider()).generate(rng); + checkDiff(sut.service, prepareMove); + sut.service.commit(prepareMove); + + Move bootstrapAndMove = (Move) sut.service.metadata().inProgressSequences.get(prepareMove.nodeId()); + checkDiff(sut.service, bootstrapAndMove.startMove); + sut.service.commit(bootstrapAndMove.startMove); + + checkDiff(sut.service, bootstrapAndMove.midMove); + sut.service.commit(bootstrapAndMove.midMove); + + checkDiff(sut.service, bootstrapAndMove.finishMove); + sut.service.commit(bootstrapAndMove.finishMove); + } + + { + PrepareLeave prepareLeave = prepareLeaveGenerator(sut.service.metadata(), sut.service.placementProvider()).generate(rng); + checkDiff(sut.service, prepareLeave); + sut.service.commit(prepareLeave); + + UnbootstrapAndLeave bootstrapAndLeave = (UnbootstrapAndLeave) sut.service.metadata().inProgressSequences.get(prepareLeave.nodeId()); + checkDiff(sut.service, bootstrapAndLeave.startLeave); + sut.service.commit(bootstrapAndLeave.startLeave); + + checkDiff(sut.service, bootstrapAndLeave.midLeave); + sut.service.commit(bootstrapAndLeave.midLeave); + + checkDiff(sut.service, bootstrapAndLeave.finishLeave); + sut.service.commit(bootstrapAndLeave.finishLeave); + } + } + } + + @Test + public void metadataKeysExtensionTest() throws Exception + { + try (CMSTestBase.CMSSut sut = new CMSTestBase.CMSSut(AtomicLongBackedProcessor::new, false, new TokenPlacementModel.SimpleReplicationFactor(3))) + { + Transformation transformation; + transformation = new CustomTransformation.PokeInt(1); + checkDiff(sut.service, transformation, Collections.singleton(CustomTransformation.PokeInt.METADATA_KEY)); + sut.service.commit(transformation); + + transformation = new CustomTransformation.PokeInt(2); + checkDiff(sut.service, transformation, Collections.singleton(CustomTransformation.PokeInt.METADATA_KEY)); + sut.service.commit(transformation); + + transformation = CustomTransformation.ClearInt.instance; + checkDiff(sut.service, transformation, Collections.singleton(CustomTransformation.PokeInt.METADATA_KEY)); + sut.service.commit(transformation); + } + } + + private static void checkDiff(ClusterMetadataService cms, Transformation transformation) + { + ClusterMetadata before = cms.metadata(); + Transformation.Result result = transformation.execute(before); + ClusterMetadata after = result.success().metadata; + Assert.assertEquals(result.success().affectedMetadata, MetadataKeys.diffKeys(before, after)); + } + + private static void checkDiff(ClusterMetadataService cms, Transformation transformation, Set<MetadataKey> expected) + { + ClusterMetadata before = cms.metadata(); + Transformation.Result result = transformation.execute(before); + ClusterMetadata after = result.success().metadata; + Assert.assertEquals(expected, result.success().affectedMetadata); + Assert.assertEquals(result.success().affectedMetadata, MetadataKeys.diffKeys(before, after)); + } + + public Generator<PrepareJoin> prepareJoinGenerator(ClusterMetadata metadata, PlacementProvider placementProvider) + { + List<NodeId> pickFrom = new ArrayList<>(); + for (Map.Entry<NodeId, NodeState> e : metadata.directory.states.entrySet()) + { + if (e.getValue().equals(NodeState.REGISTERED)) + pickFrom.add(e.getKey()); + } + + return Generators.pick(pickFrom).zip(new LongGenerator().map(Murmur3Partitioner.LongToken::new), + (node, token) -> new PrepareJoin(node, Collections.singleton(token), placementProvider, true, false)); + } + + public Generator<PrepareLeave> prepareLeaveGenerator(ClusterMetadata metadata, PlacementProvider placementProvider) + { + List<NodeId> pickFrom = new ArrayList<>(); + for (Map.Entry<NodeId, NodeState> e : metadata.directory.states.entrySet()) + { + if (e.getValue().equals(NodeState.JOINED)) + pickFrom.add(e.getKey()); + } + + return Generators.pick(pickFrom).map((node) -> new PrepareLeave(node, true, placementProvider, LeaveStreams.Kind.UNBOOTSTRAP)); + } + + public Generator<PrepareMove> prepareMoveGenerator(ClusterMetadata metadata, PlacementProvider placementProvider) + { + List<NodeId> pickFrom = new ArrayList<>(); + for (Map.Entry<NodeId, NodeState> e : metadata.directory.states.entrySet()) + { + if (e.getValue().equals(NodeState.JOINED)) + pickFrom.add(e.getKey()); + } + + return Generators.pick(pickFrom).zip(new LongGenerator().map(Murmur3Partitioner.LongToken::new), + (node, token) -> new PrepareMove(node, Collections.singleton(token), placementProvider, false)); + } + + private static final class LongGenerator implements Generator<Long> + { + + @Override + public Long generate(EntropySource rng) + { + return rng.next(); + } + } +} diff --git a/test/harry/main/org/apache/cassandra/harry/gen/EntropySource.java b/test/harry/main/org/apache/cassandra/harry/gen/EntropySource.java index bda37a9070..d6087893bc 100644 --- a/test/harry/main/org/apache/cassandra/harry/gen/EntropySource.java +++ b/test/harry/main/org/apache/cassandra/harry/gen/EntropySource.java @@ -19,7 +19,8 @@ package org.apache.cassandra.harry.gen; import com.google.common.annotations.VisibleForTesting; -import org.apache.cassandra.harry.gen.rng.PcgRSUFast; + +import org.apache.cassandra.harry.gen.rng.JdkRandomEntropySource; /** * Random generator interface that offers: @@ -89,7 +90,7 @@ public interface EntropySource static EntropySource forTests(long seed) { System.out.println("Seed: " + seed); - return new PcgRSUFast(seed, 1); + return new JdkRandomEntropySource(seed); } } diff --git a/test/harry/main/org/apache/cassandra/harry/gen/Generators.java b/test/harry/main/org/apache/cassandra/harry/gen/Generators.java index 6b46ea079d..ed966a96ed 100644 --- a/test/harry/main/org/apache/cassandra/harry/gen/Generators.java +++ b/test/harry/main/org/apache/cassandra/harry/gen/Generators.java @@ -18,6 +18,8 @@ package org.apache.cassandra.harry.gen; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -25,13 +27,47 @@ import java.util.List; import java.util.Set; import java.util.function.Supplier; +import org.apache.cassandra.locator.InetAddressAndPort; + public class Generators { + public static class InetAddrAndPortGenerator implements Generator<InetAddressAndPort> + { + private final int port; + public InetAddrAndPortGenerator() + { + this(9042); + } + + public InetAddrAndPortGenerator(int port) + { + this.port = port; + } + + @Override + public InetAddressAndPort generate(EntropySource rng) + { + int orig = rng.nextInt(); + byte[] bytes = new byte[]{ (byte) (orig & 0xff), + (byte) (orig << 8 & 0xff), + (byte) (orig << 16 & 0xff), + (byte) (orig << 24 & 0xff) }; + try + { + return InetAddressAndPort.getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port); + } + catch (UnknownHostException e) + { + throw new RuntimeException(e); + } + } + } + public static <T> Generator<T> pick(List<T> ts) { - return (rng) -> { - return ts.get(rng.nextInt(0, ts.size() - 1)); - }; + if (ts.isEmpty()) + throw new IllegalStateException("Can't pick from an empty list"); + return (rng) -> ts.get(rng.nextInt(0, ts.size())); } public static <T> Generator<T> pick(T... ts) diff --git a/test/unit/org/apache/cassandra/tcm/log/LocalLogTest.java b/test/unit/org/apache/cassandra/tcm/log/LocalLogTest.java index bcbe663736..816c491f1a 100644 --- a/test/unit/org/apache/cassandra/tcm/log/LocalLogTest.java +++ b/test/unit/org/apache/cassandra/tcm/log/LocalLogTest.java @@ -37,8 +37,6 @@ import org.junit.Test; import org.apache.cassandra.concurrent.ExecutorPlus; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.db.marshal.IntegerType; -import org.apache.cassandra.dht.LocalPartitioner; import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.tcm.ClusterMetadata; import org.apache.cassandra.tcm.Epoch; @@ -105,7 +103,7 @@ public class LocalLogTest entries.add(new Entry(Entry.Id.NONE, Epoch.create(11), - new ForceSnapshot(new ClusterMetadata(new LocalPartitioner(IntegerType.instance)).forceEpoch(Epoch.create(11))))); + new ForceSnapshot(new ClusterMetadata(Murmur3Partitioner.instance).forceEpoch(Epoch.create(11))))); Collections.shuffle(entries); log.append(entries); @@ -133,13 +131,13 @@ public class LocalLogTest entries.add(new Entry(Entry.Id.NONE, Epoch.create(11), - new ForceSnapshot(new ClusterMetadata(new LocalPartitioner(IntegerType.instance)).forceEpoch(Epoch.create(11))))); + new ForceSnapshot(new ClusterMetadata(Murmur3Partitioner.instance).forceEpoch(Epoch.create(11))))); entries.add(new Entry(Entry.Id.NONE, Epoch.create(21), - new ForceSnapshot(new ClusterMetadata(new LocalPartitioner(IntegerType.instance)).forceEpoch(Epoch.create(21))))); + new ForceSnapshot(new ClusterMetadata(Murmur3Partitioner.instance).forceEpoch(Epoch.create(21))))); entries.add(new Entry(Entry.Id.NONE, Epoch.create(31), - new ForceSnapshot(new ClusterMetadata(new LocalPartitioner(IntegerType.instance)).forceEpoch(Epoch.create(31))))); + new ForceSnapshot(new ClusterMetadata(Murmur3Partitioner.instance).forceEpoch(Epoch.create(31))))); Collections.shuffle(entries); log.append(entries); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org