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

Reply via email to