diff --git a/modules/accord b/modules/accord index 62b6d6883b..c7379e12bd 160000 --- a/modules/accord +++ b/modules/accord @@ -1 +1 @@ -Subproject commit 62b6d6883b689236efb375b6efa7f2350d8d771d +Subproject commit c7379e12bd8f8732004cb77264801fe157af1dbe diff --git a/src/java/org/apache/cassandra/config/AccordSpec.java b/src/java/org/apache/cassandra/config/AccordSpec.java index 469c949147..b81792df0c 100644 --- a/src/java/org/apache/cassandra/config/AccordSpec.java +++ b/src/java/org/apache/cassandra/config/AccordSpec.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; import accord.utils.Invariants; import com.fasterxml.jackson.annotation.JsonIgnore; import org.apache.cassandra.journal.Params; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.consensus.TransactionalMode; import static org.apache.cassandra.config.AccordSpec.QueueShardModel.THREAD_POOL_PER_SHARD; @@ -192,6 +193,7 @@ public class AccordSpec public DurationSpec periodicFlushLagBlock = new DurationSpec.IntMillisecondsBound("1500ms"); public DurationSpec.IntMillisecondsBound compactionPeriod = new DurationSpec.IntMillisecondsBound("60000ms"); private volatile long flushCombinedBlockPeriod = Long.MIN_VALUE; + public Version version = Version.DOWNGRADE_SAFE_VERSION; public void setFlushPeriod(DurationSpec newFlushPeriod) { @@ -265,12 +267,7 @@ public class AccordSpec @Override public int userVersion() { - /* - * NOTE: when accord journal version gets bumped, expose it via yaml. - * This way operators can force previous version on upgrade, temporarily, - * to allow easier downgrades if something goes wrong. - */ - return 1; + return version.version; } } } diff --git a/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java b/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java index 650e6ab982..b3813d4f20 100644 --- a/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java +++ b/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java @@ -43,7 +43,7 @@ import org.apache.cassandra.db.rows.Cell; import org.apache.cassandra.db.rows.ColumnData; import org.apache.cassandra.db.rows.ComplexColumnData; import org.apache.cassandra.db.rows.Row; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.ColumnMetadata; @@ -178,14 +178,14 @@ public final class ColumnCondition return operator.buildCQLString(columnsExpression, values); } - private interface BoundSerializer + public interface BoundSerializer { - default void serialize(T bound, DataOutputPlus out, int version) throws IOException {} - Bound deserialize(DataInputPlus in, int version, ColumnMetadata column, Operator operator, ByteBuffer value) throws IOException; - default long serializedSize(T condition, int version) { return 0; } + default void serialize(T bound, DataOutputPlus out) throws IOException {} + Bound deserialize(DataInputPlus in, ColumnMetadata column, Operator operator, ByteBuffer value) throws IOException; + default long serializedSize(T condition) { return 0; } } - enum BoundKind + public enum BoundKind { Simple(0, SimpleBound.serializer), ElementOrFieldAccess(1, ElementOrFieldAccessBound.serializer), @@ -193,7 +193,7 @@ public final class ColumnCondition private final int id; @SuppressWarnings("rawtypes") - private final BoundSerializer serializer; + public final BoundSerializer serializer; BoundKind(int id, BoundSerializer serializer) { @@ -201,7 +201,7 @@ public final class ColumnCondition this.serializer = serializer; } - static BoundKind valueOf(int id) + public static BoundKind valueOf(int id) { switch (id) { @@ -215,9 +215,9 @@ public final class ColumnCondition public static abstract class Bound { - protected final ColumnMetadata column; - protected final Operator operator; - protected final ByteBuffer value; + public final ColumnMetadata column; + public final Operator operator; + public final ByteBuffer value; protected Bound(ColumnMetadata column, Operator operator, ByteBuffer value) { @@ -231,42 +231,39 @@ public final class ColumnCondition */ public abstract boolean appliesTo(Row row); - protected abstract BoundKind kind(); + public abstract BoundKind kind(); - public static final IVersionedSerializer serializer = new IVersionedSerializer<>() - { + public static final UnversionedSerializer serializer = new UnversionedSerializer<>() { @Override - @SuppressWarnings("unchecked") - public void serialize(Bound bound, DataOutputPlus out, int version) throws IOException + public void serialize(Bound bound, DataOutputPlus out) throws IOException { - columnMetadataSerializer.serialize(bound.column, out, version); + columnMetadataSerializer.serialize(bound.column, out); bound.operator.writeToUnsignedVInt(out); - nullableByteBufferSerializer.serialize(bound.value, out, version); - BoundKind kind = bound.kind(); + nullableByteBufferSerializer.serialize(bound.value, out); + ColumnCondition.BoundKind kind = bound.kind(); out.writeUnsignedVInt32(kind.ordinal()); - kind.serializer.serialize(bound, out, version); + kind.serializer.serialize(bound, out); } @Override - public Bound deserialize(DataInputPlus in, int version) throws IOException + public Bound deserialize(DataInputPlus in) throws IOException { - ColumnMetadata column = columnMetadataSerializer.deserialize(in, version); + ColumnMetadata column = columnMetadataSerializer.deserialize(in); Operator operator = Operator.readFromUnsignedVInt(in); - ByteBuffer value = nullableByteBufferSerializer.deserialize(in, version); - BoundKind boundKind = BoundKind.valueOf(in.readUnsignedVInt32()); - return boundKind.serializer.deserialize(in, version, column, operator, value); + ByteBuffer value = nullableByteBufferSerializer.deserialize(in); + ColumnCondition.BoundKind boundKind = ColumnCondition.BoundKind.valueOf(in.readUnsignedVInt32()); + return boundKind.serializer.deserialize(in, column, operator, value); } @Override - @SuppressWarnings("unchecked") - public long serializedSize(Bound bound, int version) + public long serializedSize(Bound bound) { - BoundKind kind = bound.kind(); - return columnMetadataSerializer.serializedSize(bound.column, version) + ColumnCondition.BoundKind kind = bound.kind(); + return columnMetadataSerializer.serializedSize(bound.column) + bound.operator.sizeAsUnsignedVInt() - + nullableByteBufferSerializer.serializedSize(bound.value, version) + + nullableByteBufferSerializer.serializedSize(bound.value) + sizeofUnsignedVInt(kind.ordinal()) - + kind.serializer.serializedSize(bound, version); + + kind.serializer.serializedSize(bound); } }; } @@ -276,7 +273,7 @@ public final class ColumnCondition */ public static class SimpleBound extends Bound { - private static final BoundSerializer serializer = (in, version, column, operator, value) -> new SimpleBound(column, operator, value); + private static final BoundSerializer serializer = (in, column, operator, value) -> new SimpleBound(column, operator, value); public SimpleBound(ColumnMetadata column, Operator operator, ByteBuffer value) { @@ -301,7 +298,7 @@ public final class ColumnCondition } @Override - protected BoundKind kind() + public BoundKind kind() { return BoundKind.Simple; } @@ -345,22 +342,22 @@ public final class ColumnCondition private static final BoundSerializer serializer = new BoundSerializer<>() { @Override - public void serialize(ElementOrFieldAccessBound bound, DataOutputPlus out, int version) throws IOException + public void serialize(ElementOrFieldAccessBound bound, DataOutputPlus out) throws IOException { - nullableByteBufferSerializer.serialize(bound.keyOrIndex, out, version); + nullableByteBufferSerializer.serialize(bound.keyOrIndex, out); } @Override - public Bound deserialize(DataInputPlus in, int version, ColumnMetadata column, Operator operator, ByteBuffer value) throws IOException + public Bound deserialize(DataInputPlus in, ColumnMetadata column, Operator operator, ByteBuffer value) throws IOException { - ByteBuffer keyOrIndex = nullableByteBufferSerializer.deserialize(in, version); + ByteBuffer keyOrIndex = nullableByteBufferSerializer.deserialize(in); return new ElementOrFieldAccessBound(column, keyOrIndex, operator, value); } @Override - public long serializedSize(ElementOrFieldAccessBound condition, int version) + public long serializedSize(ElementOrFieldAccessBound condition) { - return nullableByteBufferSerializer.serializedSize(condition.keyOrIndex, version); + return nullableByteBufferSerializer.serializedSize(condition.keyOrIndex); } }; /** @@ -385,7 +382,7 @@ public final class ColumnCondition } @Override - protected BoundKind kind() + public BoundKind kind() { return BoundKind.ElementOrFieldAccess; } @@ -428,7 +425,7 @@ public final class ColumnCondition */ public static final class MultiCellBound extends Bound { - private static final BoundSerializer serializer = (in, version, column, operator, value) -> new MultiCellBound(column, operator, value); + private static final BoundSerializer serializer = (in, column, operator, value) -> new MultiCellBound(column, operator, value); public MultiCellBound(ColumnMetadata column, Operator operator, ByteBuffer value) { @@ -437,7 +434,7 @@ public final class ColumnCondition } @Override - protected BoundKind kind() + public BoundKind kind() { return BoundKind.MultiCell; } diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionIterator.java b/src/java/org/apache/cassandra/db/compaction/CompactionIterator.java index d37750c96d..1250c69fb0 100644 --- a/src/java/org/apache/cassandra/db/compaction/CompactionIterator.java +++ b/src/java/org/apache/cassandra/db/compaction/CompactionIterator.java @@ -95,6 +95,7 @@ import org.apache.cassandra.service.accord.JournalKey; import org.apache.cassandra.service.accord.api.AccordAgent; import org.apache.cassandra.service.accord.api.TokenKey; import org.apache.cassandra.service.accord.journal.AccordTopologyUpdate; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.paxos.PaxosRepairHistory; import org.apache.cassandra.service.paxos.uncommitted.PaxosRows; import org.apache.cassandra.utils.NoSpamLogger; @@ -845,7 +846,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte // Initialize topology serializer during compaction to avoid deserializing redundant epochs FlyweightSerializer topologySerializer; Object[] highestClustering = null; - final int userVersion; + final Version userVersion; long lastDescriptor = -1; int lastOffset = -1; @@ -853,7 +854,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte { service = (AccordService) serviceSupplier.get(); // TODO: test serialization version logic - userVersion = service.journalConfiguration().userVersion(); + userVersion = Version.fromVersion(service.journalConfiguration().userVersion()); this.agent = service.agent(); this.infos = service.getCompactionInfo(); @@ -900,7 +901,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte serializer.reserialize(key, builder, out, userVersion); newVersion.row(highestClustering) .add("record", out.asNewBuffer()) - .add("user_version", userVersion); + .add("user_version", userVersion.version); } catch (IOException e) { @@ -941,7 +942,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte Row.SimpleBuilder rowBuilder = newVersion.row(rows.get(rows.size() - 1).clustering().getBufferArray()); rowBuilder.add("record", commandBuilder.asByteBuffer(userVersion)) - .add("user_version", userVersion); + .add("user_version", userVersion.version); return newVersion.build().unfilteredIterator(); } @@ -987,7 +988,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte try (DataInputBuffer in = new DataInputBuffer(record, false)) { - int userVersion = Int32Type.instance.compose(row.getCell(versionColumn).buffer()); + Version userVersion = Version.fromVersion(Int32Type.instance.compose(row.getCell(versionColumn).buffer())); if (key.type == JournalKey.Type.TOPOLOGY_UPDATE) topologySerializer.deserialize(key, builder, in, userVersion); else diff --git a/src/java/org/apache/cassandra/index/accord/RouteIndexFormat.java b/src/java/org/apache/cassandra/index/accord/RouteIndexFormat.java index 33c17b84c2..b92bf69e85 100644 --- a/src/java/org/apache/cassandra/index/accord/RouteIndexFormat.java +++ b/src/java/org/apache/cassandra/index/accord/RouteIndexFormat.java @@ -43,23 +43,21 @@ import org.apache.cassandra.db.rows.Cell; import org.apache.cassandra.db.rows.Row; import org.apache.cassandra.db.rows.Unfiltered; import org.apache.cassandra.index.accord.IndexDescriptor.IndexComponent; -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.io.LocalVersionedSerializer; -import org.apache.cassandra.io.MessageVersionProvider; +import org.apache.cassandra.io.AsymmetricVersionedSerializer; +import org.apache.cassandra.io.EmbeddedAsymmetricVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.sstable.SSTableFlushObserver; import org.apache.cassandra.io.util.ChecksumedRandomAccessReader; import org.apache.cassandra.io.util.ChecksumedSequentialWriter; -import org.apache.cassandra.io.util.DataInputBuffer; -import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.FileHandle; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.serializers.UUIDSerializer; import org.apache.cassandra.service.accord.AccordJournal; import org.apache.cassandra.service.accord.AccordJournalTable; import org.apache.cassandra.service.accord.AccordKeyspace; -import org.apache.cassandra.service.accord.AccordSerializerVersion; import org.apache.cassandra.service.accord.JournalKey; import org.apache.cassandra.service.accord.serializers.KeySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ByteArrayUtil; import org.apache.cassandra.utils.Throwables; @@ -71,20 +69,15 @@ public class RouteIndexFormat { public static final Supplier CHECKSUM_SUPPLIER = CRC32C::new; - static final LocalVersionedSerializer> touches = localSerializer(KeySerializers.participants); - private static LocalVersionedSerializer localSerializer(IVersionedSerializer serializer) + static final EmbeddedAsymmetricVersionedSerializer, Participants, Version> touches = localSerializer(KeySerializers.participants); + private static EmbeddedAsymmetricVersionedSerializer localSerializer(UnversionedSerializer serializer) { - return new LocalVersionedSerializer<>(AccordSerializerVersion.CURRENT, AccordSerializerVersion.serializer, serializer); + return new EmbeddedAsymmetricVersionedSerializer<>(Version.DOWNGRADE_SAFE_VERSION, Version.Serializer.instance, AsymmetricVersionedSerializer.from(serializer)); } public static ByteBuffer serialize(Participants value) throws IOException { - int size = Math.toIntExact(touches.serializedSize(value)); - try (DataOutputBuffer buffer = new DataOutputBuffer(size)) - { - touches.serialize(value, buffer); - return buffer.buffer(true); - } + return touches.serialize(value); } static Participants deserializeTouches(ByteBuffer bytes) throws IOException @@ -92,11 +85,7 @@ public class RouteIndexFormat if (bytes == null || ByteBufferAccessor.instance.isEmpty(bytes)) return null; - try (DataInputBuffer in = new DataInputBuffer(bytes, true)) - { - MessageVersionProvider versionProvider = touches.deserializeVersion(in); - return KeySerializers.participants.deserialize(in, versionProvider.messageVersion()); - } + return touches.deserialize(bytes); } public interface Writer extends SSTableFlushObserver @@ -158,7 +147,7 @@ public class RouteIndexFormat if (!recordLive) return null; ByteBuffer record = recordCell.buffer(); - int user_version = Int32Type.instance.compose(user_versionCell.buffer()); + Version user_version = Version.fromVersion(Int32Type.instance.compose(user_versionCell.buffer())); AccordJournal.Builder builder = extract(txnId, record, user_version); StoreParticipants participants = builder.participants(); if (participants == null) @@ -178,10 +167,10 @@ public class RouteIndexFormat } } - public static AccordJournal.Builder extract(TxnId txnId, ByteBuffer record, int user_version) + public static AccordJournal.Builder extract(TxnId txnId, ByteBuffer record, Version userVersion) { AccordJournal.Builder builder = new AccordJournal.Builder(txnId, AccordJournal.Load.ALL); - AccordJournalTable.readBuffer(record, builder::deserializeNext, user_version); + AccordJournalTable.readBuffer(record, builder::deserializeNext, userVersion); return builder; } diff --git a/src/java/org/apache/cassandra/io/AsymmetricUnversionedSerializer.java b/src/java/org/apache/cassandra/io/AsymmetricUnversionedSerializer.java new file mode 100644 index 0000000000..eae92e087e --- /dev/null +++ b/src/java/org/apache/cassandra/io/AsymmetricUnversionedSerializer.java @@ -0,0 +1,77 @@ +/* + * 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.io; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.io.util.DataOutputPlus; + +public interface AsymmetricUnversionedSerializer +{ + void serialize(In t, DataOutputPlus out) throws IOException; + default ByteBuffer serialize(In t) throws IOException + { + int size = Math.toIntExact(serializedSize(t)); + try (DataOutputBuffer buffer = new DataOutputBuffer(size)) + { + serialize(t, buffer); + ByteBuffer bb = buffer.buffer(); + assert size == bb.remaining() : String.format("Expected to write %d but wrote %d", size, bb.remaining()); + return bb; + } + } + + default ByteBuffer serializeUnchecked(In t) + { + try + { + return serialize(t); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + Out deserialize(DataInputPlus in) throws IOException; + default Out deserialize(ByteBuffer buffer) throws IOException + { + try (DataInputBuffer in = new DataInputBuffer(buffer, true)) + { + return deserialize(in); + } + } + + default Out deserializeUnchecked(ByteBuffer buffer) + { + try + { + return deserialize(buffer); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + long serializedSize(In t); +} diff --git a/src/java/org/apache/cassandra/io/AsymmetricVersionedSerializer.java b/src/java/org/apache/cassandra/io/AsymmetricVersionedSerializer.java new file mode 100644 index 0000000000..2dac3a5777 --- /dev/null +++ b/src/java/org/apache/cassandra/io/AsymmetricVersionedSerializer.java @@ -0,0 +1,101 @@ +/* + * 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.io; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.io.util.DataOutputPlus; + +public interface AsymmetricVersionedSerializer +{ + void serialize(In t, DataOutputPlus out, Version version) throws IOException; + default ByteBuffer serialize(In t, Version version) throws IOException + { + int size = Math.toIntExact(serializedSize(t, version)); + try (DataOutputBuffer buffer = new DataOutputBuffer(size)) + { + serialize(t, buffer, version); + ByteBuffer bb = buffer.buffer(); + assert size == bb.remaining() : String.format("Expected to write %d but wrote %d", size, bb.remaining()); + return bb; + } + } + + default ByteBuffer serializeUnchecked(In t, Version version) + { + try + { + return serialize(t, version); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + Out deserialize(DataInputPlus in, Version version) throws IOException; + default Out deserialize(ByteBuffer buffer, Version version) throws IOException + { + try (DataInputBuffer in = new DataInputBuffer(buffer, true)) + { + return deserialize(in, version); + } + } + + default Out deserializeUnchecked(ByteBuffer buffer, Version version) + { + try + { + return deserialize(buffer, version); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + long serializedSize(In t, Version version); + + static AsymmetricVersionedSerializer from(AsymmetricUnversionedSerializer delegate) + { + return new AsymmetricVersionedSerializer<>() + { + @Override + public void serialize(In t, DataOutputPlus out, Version version) throws IOException + { + delegate.serialize(t, out); + } + + @Override + public Out deserialize(DataInputPlus in, Version version) throws IOException + { + return delegate.deserialize(in); + } + + @Override + public long serializedSize(In t, Version version) + { + return delegate.serializedSize(t); + } + }; + } +} diff --git a/src/java/org/apache/cassandra/io/EmbeddedAsymmetricVersionedSerializer.java b/src/java/org/apache/cassandra/io/EmbeddedAsymmetricVersionedSerializer.java new file mode 100644 index 0000000000..b3baec39ac --- /dev/null +++ b/src/java/org/apache/cassandra/io/EmbeddedAsymmetricVersionedSerializer.java @@ -0,0 +1,84 @@ +/* + * 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.io; + +import java.io.IOException; + +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputPlus; + +public class EmbeddedAsymmetricVersionedSerializer implements IVersionedAsymmetricSerializer, AsymmetricUnversionedSerializer +{ + private final Version version; + private final UnversionedSerializer versionSerializer; + private final AsymmetricVersionedSerializer delegate; + + public EmbeddedAsymmetricVersionedSerializer(Version version, + UnversionedSerializer versionSerializer, + AsymmetricVersionedSerializer delegate) + { + this.version = version; + this.versionSerializer = versionSerializer; + this.delegate = delegate; + } + + @Override + public void serialize(In t, DataOutputPlus out, int msgVersion) throws IOException + { + serialize(t, out); + } + + @Override + public void serialize(In t, DataOutputPlus out) throws IOException + { + versionSerializer.serialize(version, out); + delegate.serialize(t, out, version); + } + + @Override + public Out deserialize(DataInputPlus in, int msgVersion) throws IOException + { + return deserialize(in); + } + + @Override + public Out deserialize(DataInputPlus in) throws IOException + { + Version version = versionSerializer.deserialize(in); + return delegate.deserialize(in, version); + } + + public Version deserializeVersion(DataInputPlus in) throws IOException + { + return versionSerializer.deserialize(in); + } + + @Override + public long serializedSize(In t, int msgVersion) + { + return serializedSize(t); + } + + @Override + public long serializedSize(In t) + { + return versionSerializer.serializedSize(version) + + delegate.serializedSize(t, version); + } +} diff --git a/src/java/org/apache/cassandra/io/IVersionedAsymmetricSerializer.java b/src/java/org/apache/cassandra/io/IVersionedAsymmetricSerializer.java index ff89110e33..06469fa129 100644 --- a/src/java/org/apache/cassandra/io/IVersionedAsymmetricSerializer.java +++ b/src/java/org/apache/cassandra/io/IVersionedAsymmetricSerializer.java @@ -18,8 +18,12 @@ package org.apache.cassandra.io; import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import org.apache.cassandra.io.util.DataInputBuffer; import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.DataOutputPlus; public interface IVersionedAsymmetricSerializer @@ -34,6 +38,30 @@ public interface IVersionedAsymmetricSerializer */ void serialize(In t, DataOutputPlus out, int version) throws IOException; + default ByteBuffer serialize(In t, int version) throws IOException + { + int size = Math.toIntExact(serializedSize(t, version)); + try (DataOutputBuffer buffer = new DataOutputBuffer(size)) + { + serialize(t, buffer, version); + ByteBuffer bb = buffer.buffer(); + assert size == bb.remaining() : String.format("Expected to write %d but wrote %d", size, bb.remaining()); + return bb; + } + } + + default ByteBuffer serializeUnchecked(In t, int version) + { + try + { + return serialize(t, version); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + /** * Deserialize into the specified DataInputStream instance. * @param in DataInput from which deserialization needs to happen. @@ -43,6 +71,26 @@ public interface IVersionedAsymmetricSerializer */ Out deserialize(DataInputPlus in, int version) throws IOException; + default Out deserialize(ByteBuffer buffer, int version) throws IOException + { + try (DataInputBuffer in = new DataInputBuffer(buffer, true)) + { + return deserialize(in, version); + } + } + + default Out deserializeUnchecked(ByteBuffer buffer, int version) + { + try + { + return deserialize(buffer, version); + } + catch (IOException e) + { + throw new UncheckedIOException(e); + } + } + /** * Calculate serialized size of object without actually serializing. * @param t object to calculate serialized size diff --git a/src/java/org/apache/cassandra/io/IVersionedSerializer.java b/src/java/org/apache/cassandra/io/IVersionedSerializer.java index 6730ec0824..0e5a400ff1 100644 --- a/src/java/org/apache/cassandra/io/IVersionedSerializer.java +++ b/src/java/org/apache/cassandra/io/IVersionedSerializer.java @@ -17,6 +17,34 @@ */ package org.apache.cassandra.io; +import java.io.IOException; + +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputPlus; + public interface IVersionedSerializer extends IVersionedAsymmetricSerializer { + static IVersionedSerializer from(UnversionedSerializer delegate) + { + return new IVersionedSerializer() + { + @Override + public void serialize(T t, DataOutputPlus out, int version) throws IOException + { + delegate.serialize(t, out); + } + + @Override + public T deserialize(DataInputPlus in, int version) throws IOException + { + return delegate.deserialize(in); + } + + @Override + public long serializedSize(T t, int version) + { + return delegate.serializedSize(t); + } + }; + } } diff --git a/src/java/org/apache/cassandra/io/LocalVersionedSerializer.java b/src/java/org/apache/cassandra/io/LocalVersionedSerializer.java deleted file mode 100644 index cc1cdb2953..0000000000 --- a/src/java/org/apache/cassandra/io/LocalVersionedSerializer.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.io; - -import java.io.IOException; -import java.util.Objects; - -import org.apache.cassandra.io.util.DataInputPlus; -import org.apache.cassandra.io.util.DataOutputPlus; - -/** - * Serializer that stores the version within the buffer. Normal usage of {@link IVersionedSerializer} is to rely on - * {@link org.apache.cassandra.net.MessagingService#current_version} and messaging version numbers, but that implies - * that a messaging version bump is required if a change is made to this field; for some cases the serializer isn't - * dealing with messages and instead are blobs stored in a table, for these cases it may be better to rely on a field - * specific versioning that gets stored along the data. - */ -public class LocalVersionedSerializer -{ - private final MessageVersionProvider currentVersion; - private final IVersionedSerializer versionSerializer; - private final IVersionedSerializer serializer; - - public LocalVersionedSerializer(V currentVersion, - IVersionedSerializer versionSerializer, - IVersionedSerializer serializer) - { - // V is local to the constructor to validate at construction time things are fine, but don't want in the type - // sig of the class as it just gets verbose... - this.currentVersion = Objects.requireNonNull(currentVersion); - this.versionSerializer = (IVersionedSerializer) Objects.requireNonNull(versionSerializer); - this.serializer = Objects.requireNonNull(serializer); - } - - public MessageVersionProvider deserializeVersion(DataInputPlus in) throws IOException - { - return versionSerializer.deserialize(in, currentVersion.messageVersion()); - } - - public IVersionedSerializer serializer() - { - return serializer; - } - - /** - * Serialize the specified type into the specified DataOutputStream instance. - * - * @param t type that needs to be serialized - * @param out DataOutput into which serialization needs to happen. - * @throws IOException if serialization fails - */ - public void serialize(I t, DataOutputPlus out) throws IOException - { - versionSerializer.serialize(currentVersion, out, currentVersion.messageVersion()); - serializer.serialize(t, out, currentVersion.messageVersion()); - } - - /** - * Deserialize into the specified DataInputStream instance. - * - * @param in DataInput from which deserialization needs to happen. - * @return the type that was deserialized - * @throws IOException if deserialization fails - */ - public I deserialize(DataInputPlus in) throws IOException - { - MessageVersionProvider version = versionSerializer.deserialize(in, currentVersion.messageVersion()); - return serializer.deserialize(in, version.messageVersion()); - } - - /** - * Calculate serialized size of object without actually serializing. - * - * @param t object to calculate serialized size - * @return serialized size of object t - */ - public long serializedSize(I t) - { - long size = versionSerializer.serializedSize(currentVersion, currentVersion.messageVersion()); - size += serializer.serializedSize(t, currentVersion.messageVersion()); - return size; - } -} diff --git a/src/java/org/apache/cassandra/io/UnversionedSerializer.java b/src/java/org/apache/cassandra/io/UnversionedSerializer.java new file mode 100644 index 0000000000..2bf1f2013a --- /dev/null +++ b/src/java/org/apache/cassandra/io/UnversionedSerializer.java @@ -0,0 +1,23 @@ +/* + * 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.io; + +public interface UnversionedSerializer extends AsymmetricUnversionedSerializer +{ +} diff --git a/src/java/org/apache/cassandra/io/VersionedSerializer.java b/src/java/org/apache/cassandra/io/VersionedSerializer.java new file mode 100644 index 0000000000..e849753045 --- /dev/null +++ b/src/java/org/apache/cassandra/io/VersionedSerializer.java @@ -0,0 +1,23 @@ +/* + * 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.io; + +public interface VersionedSerializer extends AsymmetricVersionedSerializer +{ +} diff --git a/src/java/org/apache/cassandra/io/util/DataOutputPlus.java b/src/java/org/apache/cassandra/io/util/DataOutputPlus.java index 03b989574d..18b30263ee 100644 --- a/src/java/org/apache/cassandra/io/util/DataOutputPlus.java +++ b/src/java/org/apache/cassandra/io/util/DataOutputPlus.java @@ -132,11 +132,27 @@ public interface DataOutputPlus extends DataOutput } } + private static int numberOfBytes(long value) + { + return (64 + 7 - Long.numberOfLeadingZeros(value)) / 8; + } + /** * An efficient way to write the type {@code bytes} of a long * * @param register - the long value to be written - * @param bytes - the number of bytes the register occupies. Valid values are between 1 and 8 inclusive. + * @throws IOException + */ + default void writeLeastSignificantBytes(long register) throws IOException + { + writeLeastSignificantBytes(register, numberOfBytes(register)); + } + + /** + * An efficient way to write the type {@code bytes} of a long + * + * @param register - the long value to be written + * @param bytes - the number of bytes the register occupies. Valid values are between 0 and 8 inclusive. * @throws IOException */ default void writeLeastSignificantBytes(long register, int bytes) throws IOException diff --git a/src/java/org/apache/cassandra/net/MessagingService.java b/src/java/org/apache/cassandra/net/MessagingService.java index 2457f2dbce..ff5536d208 100644 --- a/src/java/org/apache/cassandra/net/MessagingService.java +++ b/src/java/org/apache/cassandra/net/MessagingService.java @@ -224,23 +224,6 @@ public class MessagingService extends MessagingServiceMBeanImpl implements Messa VERSION_50(13), VERSION_51(14); - public static final Version CURRENT; - - private static final Logger logger = LoggerFactory.getLogger(Version.class); - - static - { - if (DatabaseDescriptor.getStorageCompatibilityMode().isBefore(5)) - { - logger.warn("Starting in storage compatibility mode " + DatabaseDescriptor.getStorageCompatibilityMode()); - CURRENT = VERSION_40; - } - else - { - CURRENT = VERSION_51; - } - } - public static final Version MIN_ACCORD_VERSION = Version.VERSION_51; public final int value; @@ -250,6 +233,13 @@ public class MessagingService extends MessagingServiceMBeanImpl implements Messa this.value = value; } + public static Version current() + { + // this enum is leveraged in yaml config so can not touch DatabaseDescriptor to figure out + // what the "current" is, so need to leverage MessagingService's field as it uses DatabaseDescriptor + return current; + } + public static List supportedVersions() { List versions = Lists.newArrayList(); @@ -288,7 +278,8 @@ public class MessagingService extends MessagingServiceMBeanImpl implements Messa // we want to use a modified behavior for the tools and clients - that is, since they are not running a server, they // should not need to run in a compatibility mode. They should be able to connect to the server regardless whether // it uses messaving version 4 or 5 - public static final int current_version = DatabaseDescriptor.getStorageCompatibilityMode().isBefore(5) ? VERSION_40 : VERSION_51; + public static final Version current = DatabaseDescriptor.getStorageCompatibilityMode().isBefore(5) ? Version.VERSION_40 : Version.VERSION_51; + public static final int current_version = current.value; static AcceptVersions accept_messaging; static AcceptVersions accept_streaming; static diff --git a/src/java/org/apache/cassandra/net/NoPayload.java b/src/java/org/apache/cassandra/net/NoPayload.java index 3b2b1772a8..566b01df64 100644 --- a/src/java/org/apache/cassandra/net/NoPayload.java +++ b/src/java/org/apache/cassandra/net/NoPayload.java @@ -18,6 +18,7 @@ package org.apache.cassandra.net; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -50,4 +51,22 @@ public class NoPayload return 0; } }; + public static final UnversionedSerializer unversionedSerializer = new UnversionedSerializer() + { + public void serialize(NoPayload noPayload, DataOutputPlus out) + { + if (noPayload != NoPayload.noPayload) + throw new IllegalArgumentException(); + } + + public NoPayload deserialize(DataInputPlus in) + { + return noPayload; + } + + public long serializedSize(NoPayload noPayload) + { + return 0; + } + }; } diff --git a/src/java/org/apache/cassandra/net/Verb.java b/src/java/org/apache/cassandra/net/Verb.java index aadd094517..6d3e6f95db 100644 --- a/src/java/org/apache/cassandra/net/Verb.java +++ b/src/java/org/apache/cassandra/net/Verb.java @@ -55,6 +55,8 @@ import org.apache.cassandra.gms.GossipShutdown; import org.apache.cassandra.gms.GossipShutdownVerbHandler; import org.apache.cassandra.hints.HintMessage; import org.apache.cassandra.hints.HintVerbHandler; +import org.apache.cassandra.io.AsymmetricUnversionedSerializer; +import org.apache.cassandra.io.AsymmetricVersionedSerializer; import org.apache.cassandra.io.IVersionedAsymmetricSerializer; import org.apache.cassandra.repair.RepairMessageVerbHandler; import org.apache.cassandra.repair.messages.CleanupMessage; @@ -78,6 +80,7 @@ import org.apache.cassandra.schema.SchemaPushVerbHandler; import org.apache.cassandra.schema.SchemaVersionVerbHandler; import org.apache.cassandra.service.EchoVerbHandler; import org.apache.cassandra.service.SnapshotVerbHandler; +import org.apache.cassandra.service.accord.AccordSerializers; import org.apache.cassandra.service.accord.AccordService; import org.apache.cassandra.service.accord.AccordSyncPropagator; import org.apache.cassandra.service.accord.AccordSyncPropagator.Notification; @@ -104,6 +107,7 @@ import org.apache.cassandra.service.accord.serializers.GetDurableBeforeSerialize import org.apache.cassandra.service.accord.serializers.ReadDataSerializers; import org.apache.cassandra.service.accord.serializers.RecoverySerializers; import org.apache.cassandra.service.accord.serializers.SetDurableSerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.consensus.migration.ConsensusKeyMigrationState; import org.apache.cassandra.service.consensus.migration.ConsensusKeyMigrationState.ConsensusKeyMigrationFinished; import org.apache.cassandra.service.paxos.Commit; @@ -202,7 +206,7 @@ public enum Verb PAXOS_PREPARE_RSP (93, P2, writeTimeout, REQUEST_RESPONSE, () -> PrepareResponse.serializer, RESPONSE_HANDLER ), PAXOS_PREPARE_REQ (33, P2, writeTimeout, MUTATION, () -> Commit.serializer, () -> PrepareVerbHandler.instance, PAXOS_PREPARE_RSP ), - PAXOS_PROPOSE_RSP (94, P2, writeTimeout, REQUEST_RESPONSE, () -> BooleanSerializer.serializer, RESPONSE_HANDLER ), + PAXOS_PROPOSE_RSP (94, P2, writeTimeout, REQUEST_RESPONSE, () -> BooleanSerializer.messagingSerializer, RESPONSE_HANDLER ), PAXOS_PROPOSE_REQ (34, P2, writeTimeout, MUTATION, () -> Commit.serializer, () -> ProposeVerbHandler.instance, PAXOS_PROPOSE_RSP ), PAXOS_COMMIT_RSP (95, P2, writeTimeout, REQUEST_RESPONSE, () -> NoPayload.serializer, RESPONSE_HANDLER ), PAXOS_COMMIT_REQ (35, P2, writeTimeout, MUTATION, () -> Agreed.serializer, () -> PaxosCommit.requestHandler, PAXOS_COMMIT_RSP ), @@ -311,62 +315,63 @@ public enum Verb DATA_MOVEMENT_EXECUTED_REQ (817, P1, rpcTimeout, MISC, () -> DataMovement.Status.serializer, () -> DataMovements.instance, DATA_MOVEMENT_EXECUTED_RSP ), // accord - ACCORD_SIMPLE_RSP (119, P2, writeTimeout, IMMEDIATE, () -> EnumSerializer.simpleReply, AccordService::responseHandlerOrNoop ), - ACCORD_PRE_ACCEPT_RSP (120, P2, writeTimeout, IMMEDIATE, () -> PreacceptSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_PRE_ACCEPT_REQ (121, P2, writeTimeout, IMMEDIATE, () -> PreacceptSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_PRE_ACCEPT_RSP ), - ACCORD_ACCEPT_RSP (122, P2, writeTimeout, IMMEDIATE, () -> AcceptSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_ACCEPT_REQ (123, P2, writeTimeout, IMMEDIATE, () -> AcceptSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_ACCEPT_RSP ), - ACCORD_NOT_ACCEPT_REQ (124, P2, writeTimeout, IMMEDIATE, () -> AcceptSerializers.notAccept, AccordService::requestHandlerOrNoop, ACCORD_ACCEPT_RSP ), - ACCORD_READ_RSP (125, P2, readTimeout, IMMEDIATE, () -> ReadDataSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_READ_REQ (126, P2, readTimeout, IMMEDIATE, () -> ReadDataSerializers.readData, AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), - ACCORD_STABLE_THEN_READ_REQ (127, P2, writeTimeout, IMMEDIATE, () -> ReadDataSerializers.stableThenRead, AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), - ACCORD_COMMIT_REQ (128, P2, writeTimeout, IMMEDIATE, () -> CommitSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), - ACCORD_COMMIT_INVALIDATE_REQ (129, P2, writeTimeout, IMMEDIATE, () -> CommitSerializers.invalidate, AccordService::requestHandlerOrNoop ), - ACCORD_APPLY_RSP (130, P2, writeTimeout, IMMEDIATE, () -> ApplySerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_APPLY_REQ (131, P2, writeTimeout, IMMEDIATE, () -> ApplySerializers.request, AccordService::requestHandlerOrNoop, ACCORD_APPLY_RSP ), - ACCORD_APPLY_AND_WAIT_REQ (132, P2, writeTimeout, IMMEDIATE, () -> ReadDataSerializers.readData, AccordService::requestHandlerOrNoop, ACCORD_READ_RSP), - ACCORD_BEGIN_RECOVER_RSP (133, P2, writeTimeout, IMMEDIATE, () -> RecoverySerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_BEGIN_RECOVER_REQ (134, P2, writeTimeout, IMMEDIATE, () -> RecoverySerializers.request, AccordService::requestHandlerOrNoop, ACCORD_BEGIN_RECOVER_RSP ), - ACCORD_BEGIN_INVALIDATE_RSP (135, P2, writeTimeout, IMMEDIATE, () -> BeginInvalidationSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_BEGIN_INVALIDATE_REQ (136, P2, writeTimeout, IMMEDIATE, () -> BeginInvalidationSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_BEGIN_INVALIDATE_RSP ), - ACCORD_AWAIT_RSP (137, P2, writeTimeout, IMMEDIATE, () -> AwaitSerializers.syncReply, AccordService::responseHandlerOrNoop ), - ACCORD_AWAIT_REQ (138, P2, writeTimeout, IMMEDIATE, () -> AwaitSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_AWAIT_RSP ), - ACCORD_AWAIT_ASYNC_RSP_REQ (139, P2, writeTimeout, IMMEDIATE, () -> AwaitSerializers.asyncReply, AccordService::requestHandlerOrNoop ), - ACCORD_WAIT_UNTIL_APPLIED_REQ (140, P2, writeTimeout, IMMEDIATE, () -> ReadDataSerializers.waitUntilApplied, AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), - ACCORD_RECOVER_AWAIT_RSP (141, P2, writeTimeout, IMMEDIATE, () -> AwaitSerializers.recoverReply, AccordService::responseHandlerOrNoop ), - ACCORD_RECOVER_AWAIT_REQ (142, P2, writeTimeout, IMMEDIATE, () -> AwaitSerializers.recoverRequest, AccordService::requestHandlerOrNoop, ACCORD_RECOVER_AWAIT_RSP), - ACCORD_INFORM_DURABLE_REQ (143, P2, writeTimeout, IMMEDIATE, () -> InformDurableSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), - ACCORD_CHECK_STATUS_RSP (144, P2, writeTimeout, IMMEDIATE, () -> CheckStatusSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_CHECK_STATUS_REQ (145, P2, writeTimeout, IMMEDIATE, () -> CheckStatusSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_CHECK_STATUS_RSP ), - ACCORD_FETCH_DATA_RSP (146, P2, writeTimeout, IMMEDIATE, () -> FetchSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_FETCH_DATA_REQ (147, P2, writeTimeout, IMMEDIATE, () -> FetchSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_FETCH_DATA_RSP ), - ACCORD_GET_EPHMRL_READ_DEPS_RSP (148, P2, readTimeout, IMMEDIATE, () -> GetEphmrlReadDepsSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_GET_EPHMRL_READ_DEPS_REQ (149, P2, readTimeout, IMMEDIATE, () -> GetEphmrlReadDepsSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_GET_EPHMRL_READ_DEPS_RSP), - ACCORD_GET_LATEST_DEPS_RSP (150, P2, readTimeout, IMMEDIATE, () -> LatestDepsSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_GET_LATEST_DEPS_REQ (151, P2, readTimeout, IMMEDIATE, () -> LatestDepsSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_GET_LATEST_DEPS_RSP), - ACCORD_GET_MAX_CONFLICT_RSP (152, P2, readTimeout, IMMEDIATE, () -> GetMaxConflictSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_GET_MAX_CONFLICT_REQ (153, P2, readTimeout, IMMEDIATE, () -> GetMaxConflictSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_GET_MAX_CONFLICT_RSP), - ACCORD_GET_DURABLE_BEFORE_RSP (154, P2, readTimeout, IMMEDIATE, () -> GetDurableBeforeSerializers.reply, AccordService::responseHandlerOrNoop ), - ACCORD_GET_DURABLE_BEFORE_REQ (155, P2, readTimeout, IMMEDIATE, () -> GetDurableBeforeSerializers.request, AccordService::requestHandlerOrNoop, ACCORD_GET_DURABLE_BEFORE_RSP ), - ACCORD_SET_SHARD_DURABLE_REQ (156, P2, rpcTimeout, MISC, () -> SetDurableSerializers.shardDurable, AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), - ACCORD_SET_GLOBALLY_DURABLE_REQ (157, P2, rpcTimeout, MISC, () -> SetDurableSerializers.globallyDurable,AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), + ACCORD_SIMPLE_RSP (119, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(EnumSerializer.simpleReply), AccordService::responseHandlerOrNoop ), + ACCORD_PRE_ACCEPT_RSP (120, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(PreacceptSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_PRE_ACCEPT_REQ (121, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(PreacceptSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_PRE_ACCEPT_RSP ), + ACCORD_ACCEPT_RSP (122, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AcceptSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_ACCEPT_REQ (123, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AcceptSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_ACCEPT_RSP ), + ACCORD_NOT_ACCEPT_REQ (124, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AcceptSerializers.notAccept), AccordService::requestHandlerOrNoop, ACCORD_ACCEPT_RSP ), + ACCORD_READ_RSP (125, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(ReadDataSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_READ_REQ (126, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(ReadDataSerializers.readData), AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), + ACCORD_STABLE_THEN_READ_REQ (127, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(ReadDataSerializers.stableThenRead), AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), + ACCORD_COMMIT_REQ (128, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(CommitSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), + ACCORD_COMMIT_INVALIDATE_REQ (129, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(CommitSerializers.invalidate), AccordService::requestHandlerOrNoop ), + ACCORD_APPLY_RSP (130, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(ApplySerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_APPLY_REQ (131, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(ApplySerializers.request), AccordService::requestHandlerOrNoop, ACCORD_APPLY_RSP ), + ACCORD_APPLY_AND_WAIT_REQ (132, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(ReadDataSerializers.readData), AccordService::requestHandlerOrNoop, ACCORD_READ_RSP), + ACCORD_BEGIN_RECOVER_RSP (133, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(RecoverySerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_BEGIN_RECOVER_REQ (134, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(RecoverySerializers.request), AccordService::requestHandlerOrNoop, ACCORD_BEGIN_RECOVER_RSP ), + ACCORD_BEGIN_INVALIDATE_RSP (135, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(BeginInvalidationSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_BEGIN_INVALIDATE_REQ (136, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(BeginInvalidationSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_BEGIN_INVALIDATE_RSP ), + ACCORD_AWAIT_RSP (137, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AwaitSerializers.syncReply), AccordService::responseHandlerOrNoop ), + ACCORD_AWAIT_REQ (138, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AwaitSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_AWAIT_RSP ), + ACCORD_AWAIT_ASYNC_RSP_REQ (139, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AwaitSerializers.asyncReply), AccordService::requestHandlerOrNoop ), + ACCORD_WAIT_UNTIL_APPLIED_REQ (140, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(ReadDataSerializers.waitUntilApplied), AccordService::requestHandlerOrNoop, ACCORD_READ_RSP ), + ACCORD_RECOVER_AWAIT_RSP (141, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AwaitSerializers.recoverReply), AccordService::responseHandlerOrNoop ), + ACCORD_RECOVER_AWAIT_REQ (142, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AwaitSerializers.recoverRequest), AccordService::requestHandlerOrNoop, ACCORD_RECOVER_AWAIT_RSP), + ACCORD_INFORM_DURABLE_REQ (143, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(InformDurableSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), + ACCORD_CHECK_STATUS_RSP (144, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(CheckStatusSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_CHECK_STATUS_REQ (145, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(CheckStatusSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_CHECK_STATUS_RSP ), + ACCORD_FETCH_DATA_RSP (146, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(FetchSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_FETCH_DATA_REQ (147, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(FetchSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_FETCH_DATA_RSP ), + ACCORD_GET_EPHMRL_READ_DEPS_RSP (148, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetEphmrlReadDepsSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_GET_EPHMRL_READ_DEPS_REQ (149, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetEphmrlReadDepsSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_GET_EPHMRL_READ_DEPS_RSP), + ACCORD_GET_LATEST_DEPS_RSP (150, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(LatestDepsSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_GET_LATEST_DEPS_REQ (151, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(LatestDepsSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_GET_LATEST_DEPS_RSP), + ACCORD_GET_MAX_CONFLICT_RSP (152, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetMaxConflictSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_GET_MAX_CONFLICT_REQ (153, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetMaxConflictSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_GET_MAX_CONFLICT_RSP), + ACCORD_GET_DURABLE_BEFORE_RSP (154, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetDurableBeforeSerializers.reply), AccordService::responseHandlerOrNoop ), + ACCORD_GET_DURABLE_BEFORE_REQ (155, P2, readTimeout, IMMEDIATE, () -> accordEmbedded(GetDurableBeforeSerializers.request), AccordService::requestHandlerOrNoop, ACCORD_GET_DURABLE_BEFORE_RSP ), + ACCORD_SET_SHARD_DURABLE_REQ (156, P2, rpcTimeout, MISC, () -> accordEmbedded(SetDurableSerializers.shardDurable), AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), + ACCORD_SET_GLOBALLY_DURABLE_REQ (157, P2, rpcTimeout, MISC, () -> accordEmbedded(SetDurableSerializers.globallyDurable),AccordService::requestHandlerOrNoop, ACCORD_SIMPLE_RSP ), - ACCORD_SYNC_NOTIFY_RSP (158, P2, writeTimeout, MISC, () -> EnumSerializer.simpleReply, RESPONSE_HANDLER), - ACCORD_SYNC_NOTIFY_REQ (159, P2, writeTimeout, MISC, () -> Notification.serializer, () -> AccordSyncPropagator.verbHandler, ACCORD_SYNC_NOTIFY_RSP ), + ACCORD_SYNC_NOTIFY_RSP (158, P2, writeTimeout, MISC, () -> accordEmbedded(EnumSerializer.simpleReply), RESPONSE_HANDLER), + ACCORD_SYNC_NOTIFY_REQ (159, P2, writeTimeout, MISC, () -> accordEmbedded(Notification.serializer), () -> AccordSyncPropagator.verbHandler, ACCORD_SYNC_NOTIFY_RSP ), - CONSENSUS_KEY_MIGRATION (160, P1, writeTimeout, MISC, () -> ConsensusKeyMigrationFinished.serializer,() -> ConsensusKeyMigrationState.consensusKeyMigrationFinishedHandler), + CONSENSUS_KEY_MIGRATION (160, P1, writeTimeout, MISC, () -> accordEmbedded(ConsensusKeyMigrationFinished.serializer),() -> ConsensusKeyMigrationState.consensusKeyMigrationFinishedHandler), - ACCORD_INTEROP_READ_RSP (161, P2, writeTimeout, IMMEDIATE, () -> AccordInteropRead.replySerializer, AccordService::responseHandlerOrNoop), - ACCORD_INTEROP_READ_REQ (162, P2, writeTimeout, IMMEDIATE, () -> AccordInteropRead.requestSerializer, AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_RSP), - ACCORD_INTEROP_STABLE_THEN_READ_REQ(163, P2, writeTimeout, IMMEDIATE, () -> AccordInteropStableThenRead.requestSerializer, AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_RSP), - ACCORD_INTEROP_READ_REPAIR_RSP (164, P2, writeTimeout, IMMEDIATE, () -> AccordInteropReadRepair.replySerializer, AccordService::responseHandlerOrNoop), - ACCORD_INTEROP_READ_REPAIR_REQ (165, P2, writeTimeout, IMMEDIATE, () -> AccordInteropReadRepair.requestSerializer, AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_REPAIR_RSP), - ACCORD_INTEROP_APPLY_REQ (166, P2, writeTimeout, IMMEDIATE, () -> AccordInteropApply.serializer, AccordService::requestHandlerOrNoop, ACCORD_APPLY_RSP), - ACCORD_FETCH_WATERMARKS_RSP (167, P0, shortTimeout, FETCH_METADATA, () -> WatermarkCollector.serializer, RESPONSE_HANDLER), + ACCORD_INTEROP_READ_RSP (161, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropRead.replySerializer), AccordService::responseHandlerOrNoop), + ACCORD_INTEROP_READ_REQ (162, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropRead.requestSerializer), AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_RSP), + ACCORD_INTEROP_STABLE_THEN_READ_REQ(163, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropStableThenRead.requestSerializer), AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_RSP), + ACCORD_INTEROP_READ_REPAIR_RSP (164, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropReadRepair.replySerializer), AccordService::responseHandlerOrNoop), + ACCORD_INTEROP_READ_REPAIR_REQ (165, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropReadRepair.requestSerializer), AccordService::requestHandlerOrNoop, ACCORD_INTEROP_READ_REPAIR_RSP), + ACCORD_INTEROP_APPLY_REQ (166, P2, writeTimeout, IMMEDIATE, () -> accordEmbedded(AccordInteropApply.serializer), AccordService::requestHandlerOrNoop, ACCORD_APPLY_RSP), + ACCORD_FETCH_WATERMARKS_RSP (167, P0, shortTimeout, FETCH_METADATA, () -> accordEmbedded(WatermarkCollector.serializer), RESPONSE_HANDLER), + // NoPayload can not be prefixed with accord version as it is special cased in C* messaging ACCORD_FETCH_WATERMARKS_REQ (168, P0, shortTimeout, FETCH_METADATA, () -> NoPayload.serializer, AccordService::watermarkHandlerOrNoop, ACCORD_FETCH_WATERMARKS_RSP), - ACCORD_FETCH_TOPOLOGY_RSP (169, P0, shortTimeout, FETCH_METADATA, () -> FetchTopologies.responseSerializer, RESPONSE_HANDLER), - ACCORD_FETCH_TOPOLOGY_REQ (170, P0, shortTimeout, FETCH_METADATA, () -> FetchTopologies.serializer, () -> FetchTopologies.handler, ACCORD_FETCH_TOPOLOGY_RSP), + ACCORD_FETCH_TOPOLOGY_RSP (169, P0, shortTimeout, FETCH_METADATA, () -> accordEmbedded(FetchTopologies.responseSerializer), RESPONSE_HANDLER), + ACCORD_FETCH_TOPOLOGY_REQ (170, P0, shortTimeout, FETCH_METADATA, () -> accordEmbedded(FetchTopologies.serializer), () -> FetchTopologies.handler, ACCORD_FETCH_TOPOLOGY_RSP), // generic failure response FAILURE_RSP (99, P0, noTimeout, REQUEST_RESPONSE, () -> RequestFailure.serializer, RESPONSE_HANDLER ), @@ -632,6 +637,16 @@ public enum Verb { return CUSTOM_VERB_START - id; } + + private static IVersionedAsymmetricSerializer accordEmbedded(AsymmetricVersionedSerializer delegate) + { + return AccordSerializers.embedded(Version.CLUSTER_SAFE_VERSION, delegate); + } + + private static IVersionedAsymmetricSerializer accordEmbedded(AsymmetricUnversionedSerializer delegate) + { + return accordEmbedded(AsymmetricVersionedSerializer.from(delegate)); + } } @SuppressWarnings("unused") diff --git a/src/java/org/apache/cassandra/service/accord/AbstractAccordSegmentCompactor.java b/src/java/org/apache/cassandra/service/accord/AbstractAccordSegmentCompactor.java index c49f727cee..aa00a3d43d 100644 --- a/src/java/org/apache/cassandra/service/accord/AbstractAccordSegmentCompactor.java +++ b/src/java/org/apache/cassandra/service/accord/AbstractAccordSegmentCompactor.java @@ -41,6 +41,7 @@ import org.apache.cassandra.service.accord.AccordJournalValueSerializers.Flyweig import org.apache.cassandra.utils.NoSpamLogger; import static java.util.concurrent.TimeUnit.MINUTES; +import org.apache.cassandra.service.accord.serializers.Version; /** * Segment compactor: takes static segments and compacts them into a single SSTable. @@ -50,10 +51,10 @@ public abstract class AbstractAccordSegmentCompactor implements SegmentCompac protected static final Logger logger = LoggerFactory.getLogger(AbstractAccordSegmentCompactor.class); private static final NoSpamLogger.NoSpamLogStatement unknownTable = NoSpamLogger.getStatement(logger, "Unknown (probably dropped) TableId {} reading {}; skipping record", 1L, MINUTES); - protected final int userVersion; + protected final Version userVersion; protected final ColumnFamilyStore cfs; - public AbstractAccordSegmentCompactor(int userVersion, ColumnFamilyStore cfs) + public AbstractAccordSegmentCompactor(Version userVersion, ColumnFamilyStore cfs) { this.userVersion = userVersion; this.cfs = cfs; @@ -115,6 +116,8 @@ public abstract class AbstractAccordSegmentCompactor implements SegmentCompac firstOffset = lastOffset = -1; } + Version realVersion = Version.fromVersion(reader.descriptor.userVersion); + boolean advanced; do { @@ -131,7 +134,7 @@ public abstract class AbstractAccordSegmentCompactor implements SegmentCompac reader.offset() < lastOffset, "Offsets were accessed out of order: %d was accessed after %s", reader.offset(), lastOffset); } - serializer.deserialize(key, builder, in, reader.descriptor.userVersion); + serializer.deserialize(key, builder, in, realVersion); lastDescriptor = reader.descriptor.timestamp; lastOffset = reader.offset(); if (firstDescriptor == -1) @@ -196,7 +199,7 @@ public abstract class AbstractAccordSegmentCompactor implements SegmentCompac serializer.reserialize(key, builder, out, userVersion); partitionBuilder.row(descriptor, offset) .add("record", out.asNewBuffer()) - .add("user_version", userVersion); + .add("user_version", userVersion.version); } writer().append(partitionBuilder.build().unfilteredIterator()); } diff --git a/src/java/org/apache/cassandra/service/accord/AccordCache.java b/src/java/org/apache/cassandra/service/accord/AccordCache.java index 7b7a4390fd..704ed31881 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordCache.java +++ b/src/java/org/apache/cassandra/service/accord/AccordCache.java @@ -62,13 +62,13 @@ import org.apache.cassandra.metrics.AccordCacheMetrics; import org.apache.cassandra.metrics.CacheAccessMetrics; import org.apache.cassandra.service.accord.AccordCacheEntry.Status; import org.apache.cassandra.service.accord.events.CacheEvents; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.NoSpamLogger; import org.apache.cassandra.utils.NoSpamLogger.NoSpamLogStatement; import org.apache.cassandra.utils.ObjectSizes; import static accord.utils.Invariants.illegalState; import static accord.utils.Invariants.require; -import static org.apache.cassandra.net.MessagingService.current_version; import static org.apache.cassandra.service.accord.AccordCacheEntry.Status.EVICTED; import static org.apache.cassandra.service.accord.AccordCacheEntry.Status.LOADED; import static org.apache.cassandra.service.accord.AccordCacheEntry.Status.MODIFIED; @@ -1212,7 +1212,7 @@ public class AccordCache implements CacheSize try { - return AccordJournal.asSerializedChange(null, value, current_version); + return AccordJournal.asSerializedChange(null, value, Version.LATEST); } catch (IOException e) { @@ -1229,7 +1229,7 @@ public class AccordCache implements CacheSize buffer.mark(); try (DataInputBuffer buf = new DataInputBuffer(buffer, false)) { - builder.deserializeNext(buf, current_version); + builder.deserializeNext(buf, Version.LATEST); return builder.construct(commandStore.unsafeGetRedundantBefore()); } catch (UnknownTableException e) diff --git a/src/java/org/apache/cassandra/service/accord/AccordFastPath.java b/src/java/org/apache/cassandra/service/accord/AccordFastPath.java index ac04488d13..71150355dd 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordFastPath.java +++ b/src/java/org/apache/cassandra/service/accord/AccordFastPath.java @@ -252,7 +252,7 @@ public class AccordFastPath implements MetadataValue out.writeInt(map.size()); for (Map.Entry entry : map.entrySet()) { - TopologySerializers.nodeId.serialize(entry.getKey(), out, version); + TopologySerializers.nodeId.serialize(entry.getKey(), out); NodeInfo.serializer.serialize(entry.getValue(), out, version); } } @@ -271,7 +271,7 @@ public class AccordFastPath implements MetadataValue ImmutableMap.Builder builder = ImmutableMap.builder(); for (int i=0; i long size = TypeSizes.INT_SIZE; for (Map.Entry entry : map.entrySet()) { - size += TopologySerializers.nodeId.serializedSize(entry.getKey(), version); + size += TopologySerializers.nodeId.serializedSize(entry.getKey()); size += NodeInfo.serializer.serializedSize(entry.getValue(), version); } return size; diff --git a/src/java/org/apache/cassandra/service/accord/AccordFetchCoordinator.java b/src/java/org/apache/cassandra/service/accord/AccordFetchCoordinator.java index b9ec97b68a..d413c75c79 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordFetchCoordinator.java +++ b/src/java/org/apache/cassandra/service/accord/AccordFetchCoordinator.java @@ -50,7 +50,8 @@ import accord.utils.Invariants; import accord.utils.async.AsyncChain; import accord.utils.async.AsyncChains; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -58,7 +59,9 @@ import org.apache.cassandra.locator.RangesAtEndpoint; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.schema.TableMetadata; import org.apache.cassandra.service.accord.serializers.CommandSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.streaming.PreviewKind; import org.apache.cassandra.streaming.StreamCoordinator; import org.apache.cassandra.streaming.StreamManager; @@ -92,47 +95,47 @@ public class AccordFetchCoordinator extends AbstractFetchCoordinator implements this.hasData = hasData; } - static final IVersionedSerializer serializer = new IVersionedSerializer<>() + static final UnversionedSerializer serializer = new UnversionedSerializer<>() { - public void serialize(SessionInfo info, DataOutputPlus out, int version) throws IOException + public void serialize(SessionInfo info, DataOutputPlus out) throws IOException { - TimeUUID.Serializer.instance.serialize(info.planId, out, version); + TimeUUID.Serializer.instance.serialize(info.planId, out); out.writeBoolean(info.hasData); } - public SessionInfo deserialize(DataInputPlus in, int version) throws IOException + public SessionInfo deserialize(DataInputPlus in) throws IOException { - return new SessionInfo(TimeUUID.Serializer.instance.deserialize(in, version), in.readBoolean()); + return new SessionInfo(TimeUUID.Serializer.instance.deserialize(in), in.readBoolean()); } - public long serializedSize(SessionInfo info, int version) + public long serializedSize(SessionInfo info) { - return TimeUUID.Serializer.instance.serializedSize(info.planId, version) + TypeSizes.BOOL_SIZE; + return TimeUUID.Serializer.instance.serializedSize(info.planId) + TypeSizes.BOOL_SIZE; } }; } - public static final IVersionedSerializer serializer = new IVersionedSerializer<>() + public static final UnversionedSerializer serializer = new UnversionedSerializer<>() { @Override - public void serialize(StreamData data, DataOutputPlus out, int version) throws IOException + public void serialize(StreamData data, DataOutputPlus out) throws IOException { - serializeMap(data.streams, out, version, TokenRange.serializer, SessionInfo.serializer); + serializeMap(data.streams, out, TokenRange.serializer, SessionInfo.serializer); } @Override - public StreamData deserialize(DataInputPlus in, int version) throws IOException + public StreamData deserialize(DataInputPlus in) throws IOException { - return new StreamData(ImmutableMap.copyOf(deserializeMap(in, version, + return new StreamData(ImmutableMap.copyOf(deserializeMap(in, TokenRange.serializer, SessionInfo.serializer))); } @Override - public long serializedSize(StreamData data, int version) + public long serializedSize(StreamData data) { - return serializedMapSize(data.streams, version, TokenRange.serializer, SessionInfo.serializer); + return serializedMapSize(data.streams, TokenRange.serializer, SessionInfo.serializer); } }; @@ -214,24 +217,24 @@ public class AccordFetchCoordinator extends AbstractFetchCoordinator implements public static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(StreamingRead read, DataOutputPlus out, int version) throws IOException + public void serialize(StreamingRead read, DataOutputPlus out, Version version) throws IOException { - InetAddressAndPort.Serializer.inetAddressAndPortSerializer.serialize(read.to, out, version); - KeySerializers.ranges.serialize(read.ranges, out, version); + InetAddressAndPort.Serializer.inetAddressAndPortSerializer.serialize(read.to, out, version.messageVersion()); + KeySerializers.ranges.serialize(read.ranges, out); } @Override - public StreamingRead deserialize(DataInputPlus in, int version) throws IOException + public StreamingRead deserialize(DataInputPlus in, Version version) throws IOException { - return new StreamingRead(InetAddressAndPort.Serializer.inetAddressAndPortSerializer.deserialize(in, version), - KeySerializers.ranges.deserialize(in, version)); + return new StreamingRead(InetAddressAndPort.Serializer.inetAddressAndPortSerializer.deserialize(in, version.messageVersion()), + KeySerializers.ranges.deserialize(in)); } @Override - public long serializedSize(StreamingRead read, int version) + public long serializedSize(StreamingRead read, Version version) { - return InetAddressAndPort.Serializer.inetAddressAndPortSerializer.serializedSize(read.to, version) - + KeySerializers.ranges.serializedSize(read.ranges, version); + return InetAddressAndPort.Serializer.inetAddressAndPortSerializer.serializedSize(read.to, version.messageVersion()) + + KeySerializers.ranges.serializedSize(read.ranges); } }; @@ -302,47 +305,47 @@ public class AccordFetchCoordinator extends AbstractFetchCoordinator implements public static class StreamingTxn { - private static final IVersionedSerializer read = new CastingSerializer<>(StreamingRead.class, - StreamingRead.serializer); + private static final VersionedSerializer read = CastingSerializer.create(StreamingRead.class, + StreamingRead.serializer); - private static final IVersionedSerializer query = new IVersionedSerializer<>() + private static final UnversionedSerializer query = new UnversionedSerializer<>() { @Override - public void serialize(Query t, DataOutputPlus out, int version) + public void serialize(Query t, DataOutputPlus out) { Invariants.requireArgument(t == noopQuery); } @Override - public Query deserialize(DataInputPlus in, int version) + public Query deserialize(DataInputPlus in) { return noopQuery; } @Override - public long serializedSize(Query t, int version) + public long serializedSize(Query t) { Invariants.requireArgument(t == noopQuery); return 0; } }; - private static final IVersionedSerializer update = new IVersionedSerializer<>() + private static final IVersionedSerializer update = new IVersionedSerializer() { @Override - public void serialize(Update t, DataOutputPlus out, int version) + public void serialize(Update t, DataOutputPlus out, Version version) { Invariants.requireArgument(t == null); } @Override - public Update deserialize(DataInputPlus in, int version) + public Update deserialize(DataInputPlus in, Version version) { return null; } @Override - public long serializedSize(Update t, int version) + public long serializedSize(Update t, Version version) { Invariants.requireArgument(t == null); return 0; diff --git a/src/java/org/apache/cassandra/service/accord/AccordJournal.java b/src/java/org/apache/cassandra/service/accord/AccordJournal.java index f856e99ec3..0ac5c87807 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordJournal.java +++ b/src/java/org/apache/cassandra/service/accord/AccordJournal.java @@ -75,6 +75,7 @@ import org.apache.cassandra.service.accord.serializers.CommandSerializers; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; import org.apache.cassandra.service.accord.serializers.DepsSerializers; import org.apache.cassandra.service.accord.serializers.ResultSerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.accord.serializers.WaitingOnSerializer; import org.apache.cassandra.utils.CloseableIterator; import org.apache.cassandra.utils.ExecutorUtils; @@ -123,6 +124,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier public AccordJournal(Params params, AccordAgent agent, File directory, ColumnFamilyStore cfs) { this.agent = agent; + Version userVersion = Version.fromVersion(params.userVersion()); this.journal = new Journal<>("AccordJournal", directory, params, JournalKey.SUPPORT, // In Accord, we are using streaming serialization, i.e. Reader/Writer interfaces instead of materializing objects new ValueSerializer<>() @@ -139,14 +141,14 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier throw new UnsupportedOperationException(); } }, - compactor(cfs, params)); - this.journalTable = new AccordJournalTable<>(journal, JournalKey.SUPPORT, cfs, params.userVersion()); + compactor(cfs, userVersion)); + this.journalTable = new AccordJournalTable<>(journal, JournalKey.SUPPORT, cfs, userVersion); this.params = params; } - protected SegmentCompactor compactor(ColumnFamilyStore cfs, Params params) + protected SegmentCompactor compactor(ColumnFamilyStore cfs, Version userVersion) { - return new AccordSegmentCompactor<>(params.userVersion(), cfs) { + return new AccordSegmentCompactor<>(userVersion, cfs) { @Nullable @Override public Collection> compact(Collection> staticSegments) @@ -395,7 +397,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier private RecordPointer appendInternal(JournalKey key, T write) { AccordJournalValueSerializers.FlyweightSerializer serializer = (AccordJournalValueSerializers.FlyweightSerializer) key.type.serializer; - return journal.asyncWrite(key, (out, userVersion) -> serializer.serialize(key, write, out, userVersion)); + return journal.asyncWrite(key, (out, userVersion) -> serializer.serialize(key, write, out, Version.fromVersion(userVersion))); } @VisibleForTesting @@ -473,7 +475,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier } } - public static @Nullable ByteBuffer asSerializedChange(Command before, Command after, int userVersion) throws IOException + public static @Nullable ByteBuffer asSerializedChange(Command before, Command after, Version userVersion) throws IOException { try (DataOutputBuffer out = new DataOutputBuffer()) { @@ -525,11 +527,16 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier @Override public void write(DataOutputPlus out, int userVersion) throws IOException + { + write(out, Version.fromVersion(userVersion)); + } + + public void write(DataOutputPlus out, Version userVersion) throws IOException { serialize(after, flags, out, userVersion); } - private static void serialize(Command command, int flags, DataOutputPlus out, int userVersion) throws IOException + private static void serialize(Command command, int flags, DataOutputPlus out, Version userVersion) throws IOException { Invariants.require(flags != 0); out.writeInt(flags); @@ -562,10 +569,10 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier out.writeByte(command.durability().ordinal()); break; case ACCEPTED: - CommandSerializers.ballot.serialize(command.acceptedOrCommitted(), out, userVersion); + CommandSerializers.ballot.serialize(command.acceptedOrCommitted(), out); break; case PROMISED: - CommandSerializers.ballot.serialize(command.promised(), out, userVersion); + CommandSerializers.ballot.serialize(command.promised(), out); break; case PARTICIPANTS: CommandSerializers.participants.serialize(command.participants(), out, userVersion); @@ -574,7 +581,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier CommandSerializers.partialTxn.serialize(command.partialTxn(), out, userVersion); break; case PARTIAL_DEPS: - DepsSerializers.partialDeps.serialize(command.partialDeps(), out, userVersion); + DepsSerializers.partialDeps.serialize(command.partialDeps(), out); break; case WAITING_ON: Command.WaitingOn waitingOn = command.waitingOn(); @@ -584,7 +591,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier CommandSerializers.writes.serialize(command.writes(), out, userVersion); break; case RESULT: - ResultSerializers.result.serialize(command.result(), out, userVersion); + ResultSerializers.result.serialize(command.result(), out); break; case CLEANUP: throw new IllegalStateException(); @@ -627,7 +634,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier { super(txnId, load); } - public ByteBuffer asByteBuffer(int userVersion) throws IOException + public ByteBuffer asByteBuffer(Version userVersion) throws IOException { try (DataOutputBuffer out = new DataOutputBuffer()) { @@ -636,7 +643,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier } } - public void serialize(DataOutputPlus out, int userVersion) throws IOException + public void serialize(DataOutputPlus out, Version userVersion) throws IOException { Invariants.require(mask == 0); Invariants.require(flags != 0); @@ -645,7 +652,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier serialize(flags, out, userVersion); } - private void serialize(int flags, DataOutputPlus out, int userVersion) throws IOException + private void serialize(int flags, DataOutputPlus out, Version userVersion) throws IOException { Invariants.require(flags != 0); out.writeInt(flags); @@ -682,11 +689,11 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier break; case ACCEPTED: Invariants.require(acceptedOrCommitted != null); - CommandSerializers.ballot.serialize(acceptedOrCommitted, out, userVersion); + CommandSerializers.ballot.serialize(acceptedOrCommitted, out); break; case PROMISED: Invariants.require(promised != null); - CommandSerializers.ballot.serialize(promised, out, userVersion); + CommandSerializers.ballot.serialize(promised, out); break; case PARTICIPANTS: Invariants.require(participants != null); @@ -698,11 +705,11 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier break; case PARTIAL_DEPS: Invariants.require(partialDeps != null); - DepsSerializers.partialDeps.serialize(partialDeps, out, userVersion); + DepsSerializers.partialDeps.serialize(partialDeps, out); break; case WAITING_ON: Invariants.require(waitingOn != null); - ((WaitingOnSerializer.Provider)waitingOn).reserialize(out, userVersion); + ((WaitingOnSerializer.Provider)waitingOn).reserialize(out); break; case WRITES: Invariants.require(writes != null); @@ -710,13 +717,13 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier break; case RESULT: Invariants.require(result != null); - ResultSerializers.result.serialize(result, out, userVersion); + ResultSerializers.result.serialize(result, out); break; } } } - public void deserializeNext(DataInputPlus in, int userVersion) throws IOException + public void deserializeNext(DataInputPlus in, Version userVersion) throws IOException { Invariants.require(txnId != null); int readFlags = in.readInt(); @@ -742,7 +749,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier this.flags |= readFlags & (~readFlags << 16); } - private void deserialize(Field field, DataInputPlus in, int userVersion) throws IOException + private void deserialize(Field field, DataInputPlus in, Version userVersion) throws IOException { switch (field) { @@ -762,10 +769,10 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier durability = Durability.values()[in.readByte()]; break; case ACCEPTED: - acceptedOrCommitted = CommandSerializers.ballot.deserialize(in, userVersion); + acceptedOrCommitted = CommandSerializers.ballot.deserialize(in); break; case PROMISED: - promised = CommandSerializers.ballot.deserialize(in, userVersion); + promised = CommandSerializers.ballot.deserialize(in); break; case PARTICIPANTS: participants = CommandSerializers.participants.deserialize(in, userVersion); @@ -774,7 +781,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier partialTxn = CommandSerializers.partialTxn.deserialize(in, userVersion); break; case PARTIAL_DEPS: - partialDeps = DepsSerializers.partialDeps.deserialize(in, userVersion); + partialDeps = DepsSerializers.partialDeps.deserialize(in); break; case WAITING_ON: waitingOn = WaitingOnSerializer.deserializeProvider(txnId, in); @@ -788,12 +795,12 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier cleanup = newCleanup; break; case RESULT: - result = ResultSerializers.result.deserialize(in, userVersion); + result = ResultSerializers.result.deserialize(in); break; } } - private static void skip(TxnId txnId, Field field, DataInputPlus in, int userVersion) throws IOException + private static void skip(TxnId txnId, Field field, DataInputPlus in, Version userVersion) throws IOException { switch (field) { @@ -824,7 +831,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier break; case PARTIAL_DEPS: // TODO (expected): skip - DepsSerializers.partialDeps.deserialize(in, userVersion); + DepsSerializers.partialDeps.deserialize(in); break; case WAITING_ON: WaitingOnSerializer.skip(txnId, in); @@ -835,7 +842,7 @@ public class AccordJournal implements accord.api.Journal, RangeSearcher.Supplier break; case RESULT: // TODO (expected): skip - ResultSerializers.result.deserialize(in, userVersion); + ResultSerializers.result.deserialize(in); break; } } diff --git a/src/java/org/apache/cassandra/service/accord/AccordJournalTable.java b/src/java/org/apache/cassandra/service/accord/AccordJournalTable.java index 9278c216da..ed1594b30e 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordJournalTable.java +++ b/src/java/org/apache/cassandra/service/accord/AccordJournalTable.java @@ -73,6 +73,7 @@ import org.apache.cassandra.journal.KeySupport; import org.apache.cassandra.journal.RecordConsumer; import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.service.accord.api.TokenKey; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.CloseableIterator; import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.JVMStabilityInspector; @@ -98,9 +99,9 @@ public class AccordJournalTable implements RangeSearche */ @Nullable private final RouteInMemoryIndex index; - private final int accordJournalVersion; + private final Version accordJournalVersion; - public AccordJournalTable(Journal journal, KeySupport keySupport, ColumnFamilyStore cfs, int accordJournalVersion) + public AccordJournalTable(Journal journal, KeySupport keySupport, ColumnFamilyStore cfs, Version accordJournalVersion) { this.journal = journal; this.cfs = cfs; @@ -150,7 +151,7 @@ public class AccordJournalTable implements RangeSearche public interface Reader { - void read(DataInputPlus input, int userVersion) throws IOException; + void read(DataInputPlus input, Version userVersion) throws IOException; } private class RecordConsumerAdapter implements RecordConsumer @@ -174,7 +175,7 @@ public class AccordJournalTable implements RangeSearche prevPosition = -1; Invariants.require(prevPosition == -1 || position < prevPosition, "Records should always be iterated over in a reverse order, but %s was seen after %s", position, prevPosition); - readBuffer(buffer, reader, userVersion); + readBuffer(buffer, reader, Version.fromVersion(userVersion)); prevSegment = segment; prevPosition = position; } @@ -486,7 +487,7 @@ public class AccordJournalTable implements RangeSearche } } - public static void readBuffer(ByteBuffer buffer, Reader reader, int userVersion) + public static void readBuffer(ByteBuffer buffer, Reader reader, Version userVersion) { try (DataInputBuffer in = new DataInputBuffer(buffer, false)) { diff --git a/src/java/org/apache/cassandra/service/accord/AccordJournalValueSerializers.java b/src/java/org/apache/cassandra/service/accord/AccordJournalValueSerializers.java index 0ca7cfcf28..25e37e0b0b 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordJournalValueSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/AccordJournalValueSerializers.java @@ -30,9 +30,9 @@ import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.service.accord.journal.AccordTopologyUpdate; import org.apache.cassandra.service.accord.serializers.CommandStoreSerializers; +import org.apache.cassandra.service.accord.serializers.Version; import static accord.api.Journal.Load.ALL; import static accord.local.CommandStores.RangesForEpoch; @@ -42,16 +42,15 @@ import static accord.local.CommandStores.RangesForEpoch; // TODO (required): versioning public class AccordJournalValueSerializers { - private static final int messagingVersion = MessagingService.VERSION_40; public interface FlyweightSerializer { IMAGE mergerFor(JournalKey key); - void serialize(JournalKey key, ENTRY from, DataOutputPlus out, int userVersion) throws IOException; + void serialize(JournalKey key, ENTRY from, DataOutputPlus out, Version userVersion) throws IOException; - void reserialize(JournalKey key, IMAGE from, DataOutputPlus out, int userVersion) throws IOException; + void reserialize(JournalKey key, IMAGE from, DataOutputPlus out, Version userVersion) throws IOException; - void deserialize(JournalKey key, IMAGE into, DataInputPlus in, int userVersion) throws IOException; + void deserialize(JournalKey key, IMAGE into, DataInputPlus in, Version userVersion) throws IOException; } public static class CommandDiffSerializer @@ -64,7 +63,7 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, AccordJournal.Writer writer, DataOutputPlus out, int userVersion) + public void serialize(JournalKey key, AccordJournal.Writer writer, DataOutputPlus out, Version userVersion) { try { @@ -77,7 +76,7 @@ public class AccordJournalValueSerializers } @Override - public void reserialize(JournalKey key, AccordJournal.Builder from, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, AccordJournal.Builder from, DataOutputPlus out, Version userVersion) throws IOException { from.serialize(out, // In CompactionIterator, we are dealing with relatively recent records, so we do not pass redundant before here. @@ -86,7 +85,7 @@ public class AccordJournalValueSerializers } @Override - public void deserialize(JournalKey journalKey, AccordJournal.Builder into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey journalKey, AccordJournal.Builder into, DataInputPlus in, Version userVersion) throws IOException { into.deserializeNext(in, userVersion); } @@ -142,7 +141,7 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, RedundantBefore entry, DataOutputPlus out, int userVersion) + public void serialize(JournalKey key, RedundantBefore entry, DataOutputPlus out, Version userVersion) { try { @@ -152,7 +151,7 @@ public class AccordJournalValueSerializers return; } out.writeInt(1); - CommandStoreSerializers.redundantBefore.serialize(entry, out, messagingVersion); + CommandStoreSerializers.redundantBefore.serialize(entry, out); } catch (IOException e) { @@ -161,20 +160,20 @@ public class AccordJournalValueSerializers } @Override - public void reserialize(JournalKey key, IdentityAccumulator from, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, IdentityAccumulator from, DataOutputPlus out, Version userVersion) throws IOException { serialize(key, from.get(), out, userVersion); } @Override - public void deserialize(JournalKey journalKey, IdentityAccumulator into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey journalKey, IdentityAccumulator into, DataInputPlus in, Version userVersion) throws IOException { if (in.readInt() == 0) { into.update(RedundantBefore.EMPTY); return; } - into.update(CommandStoreSerializers.redundantBefore.deserialize(in, messagingVersion)); + into.update(CommandStoreSerializers.redundantBefore.deserialize(in)); } } @@ -201,11 +200,11 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, DurableBefore entry, DataOutputPlus out, int userVersion) + public void serialize(JournalKey key, DurableBefore entry, DataOutputPlus out, Version userVersion) { try { - CommandStoreSerializers.durableBefore.serialize(entry, out, messagingVersion); + CommandStoreSerializers.durableBefore.serialize(entry, out); } catch (IOException e) { @@ -214,17 +213,17 @@ public class AccordJournalValueSerializers } @Override - public void reserialize(JournalKey key, DurableBeforeAccumulator from, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, DurableBeforeAccumulator from, DataOutputPlus out, Version userVersion) throws IOException { serialize(key, from.get(), out, userVersion); } @Override - public void deserialize(JournalKey journalKey, DurableBeforeAccumulator into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey journalKey, DurableBeforeAccumulator into, DataInputPlus in, Version userVersion) throws IOException { // TODO: maybe using local serializer is not the best call here, but how do we distinguish // between messaging and disk versioning? - into.update(CommandStoreSerializers.durableBefore.deserialize(in, messagingVersion)); + into.update(CommandStoreSerializers.durableBefore.deserialize(in)); } } @@ -238,21 +237,21 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, NavigableMap entry, DataOutputPlus out, int userVersion) throws IOException + public void serialize(JournalKey key, NavigableMap entry, DataOutputPlus out, Version userVersion) throws IOException { - CommandStoreSerializers.bootstrapBeganAt.serialize(entry, out, messagingVersion); + CommandStoreSerializers.bootstrapBeganAt.serialize(entry, out); } @Override - public void reserialize(JournalKey key, IdentityAccumulator> image, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, IdentityAccumulator> image, DataOutputPlus out, Version userVersion) throws IOException { serialize(key, image.get(), out, userVersion); } @Override - public void deserialize(JournalKey key, IdentityAccumulator> into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey key, IdentityAccumulator> into, DataInputPlus in, Version userVersion) throws IOException { - into.update(CommandStoreSerializers.bootstrapBeganAt.deserialize(in, messagingVersion)); + into.update(CommandStoreSerializers.bootstrapBeganAt.deserialize(in)); } } @@ -266,21 +265,21 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, NavigableMap from, DataOutputPlus out, int userVersion) throws IOException + public void serialize(JournalKey key, NavigableMap from, DataOutputPlus out, Version userVersion) throws IOException { - CommandStoreSerializers.safeToRead.serialize(from, out, messagingVersion); + CommandStoreSerializers.safeToRead.serialize(from, out); } @Override - public void reserialize(JournalKey key, IdentityAccumulator> from, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, IdentityAccumulator> from, DataOutputPlus out, Version userVersion) throws IOException { serialize(key, from.get(), out, userVersion); } @Override - public void deserialize(JournalKey key, IdentityAccumulator> into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey key, IdentityAccumulator> into, DataInputPlus in, Version userVersion) throws IOException { - into.update(CommandStoreSerializers.safeToRead.deserialize(in, messagingVersion)); + into.update(CommandStoreSerializers.safeToRead.deserialize(in)); } } @@ -294,21 +293,21 @@ public class AccordJournalValueSerializers } @Override - public void serialize(JournalKey key, RangesForEpoch from, DataOutputPlus out, int userVersion) throws IOException + public void serialize(JournalKey key, RangesForEpoch from, DataOutputPlus out, Version userVersion) throws IOException { - AccordTopologyUpdate.RangesForEpochSerializer.instance.serialize(from, out, userVersion); + AccordTopologyUpdate.RangesForEpochSerializer.instance.serialize(from, out); } @Override - public void reserialize(JournalKey key, Accumulator from, DataOutputPlus out, int userVersion) throws IOException + public void reserialize(JournalKey key, Accumulator from, DataOutputPlus out, Version userVersion) throws IOException { - serialize(key, from.get(), out, messagingVersion); + serialize(key, from.get(), out, userVersion); } @Override - public void deserialize(JournalKey key, Accumulator into, DataInputPlus in, int userVersion) throws IOException + public void deserialize(JournalKey key, Accumulator into, DataInputPlus in, Version userVersion) throws IOException { - into.update(AccordTopologyUpdate.RangesForEpochSerializer.instance.deserialize(in, userVersion)); + into.update(AccordTopologyUpdate.RangesForEpochSerializer.instance.deserialize(in)); } } } \ No newline at end of file diff --git a/src/java/org/apache/cassandra/service/accord/AccordSegmentCompactor.java b/src/java/org/apache/cassandra/service/accord/AccordSegmentCompactor.java index 68a41489e3..f92eca8cf8 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordSegmentCompactor.java +++ b/src/java/org/apache/cassandra/service/accord/AccordSegmentCompactor.java @@ -22,6 +22,7 @@ import org.apache.cassandra.db.SerializationHeader; import org.apache.cassandra.db.rows.EncodingStats; import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.SSTableTxnWriter; +import org.apache.cassandra.service.accord.serializers.Version; /** * Segment compactor: takes static segments and compacts them into a single SSTable. @@ -30,7 +31,7 @@ public class AccordSegmentCompactor extends AbstractAccordSegmentCompactor { private SSTableTxnWriter writer; - public AccordSegmentCompactor(int userVersion, ColumnFamilyStore cfs) + public AccordSegmentCompactor(Version userVersion, ColumnFamilyStore cfs) { super(userVersion, cfs); } diff --git a/src/java/org/apache/cassandra/service/accord/AccordSerializerVersion.java b/src/java/org/apache/cassandra/service/accord/AccordSerializerVersion.java deleted file mode 100644 index c0c03c8d93..0000000000 --- a/src/java/org/apache/cassandra/service/accord/AccordSerializerVersion.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.service.accord; - -import java.io.IOException; - -import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.io.MessageVersionProvider; -import org.apache.cassandra.io.util.DataInputPlus; -import org.apache.cassandra.io.util.DataOutputPlus; -import org.apache.cassandra.net.MessagingService; - -public enum AccordSerializerVersion implements MessageVersionProvider -{ - // If MessagingService version bumps, this mapping does not need to be updated; only updates needed are those that - // include accord serializer changes. - V1(1, MessagingService.VERSION_40); - - public static final AccordSerializerVersion CURRENT = V1; - public static final Serializer serializer = new Serializer(); - - public final int version; - public final int msgVersion; - - AccordSerializerVersion(int version, int msgVersion) - { - this.version = version; - this.msgVersion = msgVersion; - } - - public static AccordSerializerVersion fromVersion(int version) - { - switch (version) - { - case 1: - return V1; - default: - throw new IllegalArgumentException(); - } - } - - public static AccordSerializerVersion fromMessageVersion(int version) - { - AccordSerializerVersion[] versions = values(); - for (int i = versions.length - 1; i >= 0; i--) - { - AccordSerializerVersion v = versions[i]; - // If network version bumped (12 to 13), the accord serializers may not have been changed; use the largest - // version smaller than or equal to this version - if (v.msgVersion <= version) - return v; - } - throw new IllegalArgumentException("Attempted to use message version " + version + " which is smaller than " + versions[0] + " can handle (" + versions[0].msgVersion + ")"); - } - - @Override - public int messageVersion() - { - return msgVersion; - } - - public static class Serializer implements IVersionedSerializer - { - @Override - public void serialize(AccordSerializerVersion t, DataOutputPlus out, int version) throws IOException - { - serialize(t, out); - } - - public void serialize(AccordSerializerVersion t, DataOutputPlus out) throws IOException - { - out.writeUnsignedVInt32(t.version); - } - - @Override - public AccordSerializerVersion deserialize(DataInputPlus in, int version) throws IOException - { - return deserialize(in); - } - - public AccordSerializerVersion deserialize(DataInputPlus in) throws IOException - { - return fromVersion(in.readUnsignedVInt32()); - } - - @Override - public long serializedSize(AccordSerializerVersion t, int version) - { - return serializedSize(t); - } - - public long serializedSize(AccordSerializerVersion t) - { - return TypeSizes.sizeofUnsignedVInt(t.version); - } - } -} diff --git a/src/java/org/apache/cassandra/service/accord/AccordSerializers.java b/src/java/org/apache/cassandra/service/accord/AccordSerializers.java index 08fa244c18..ee6fb4ee65 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/AccordSerializers.java @@ -20,7 +20,6 @@ package org.apache.cassandra.service.accord; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.List; import org.apache.cassandra.cql3.terms.MultiElements; import org.apache.cassandra.cql3.terms.Term; @@ -36,16 +35,17 @@ import org.apache.cassandra.db.marshal.SetType; import org.apache.cassandra.db.marshal.ValueAccessor; import org.apache.cassandra.db.partitions.PartitionUpdate; import org.apache.cassandra.db.rows.DeserializationHelper; -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.AsymmetricVersionedSerializer; +import org.apache.cassandra.io.EmbeddedAsymmetricVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; -import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.DataOutputPlus; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.schema.TableMetadata; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ByteBufferUtil; import static org.apache.cassandra.db.TypeSizes.sizeof; @@ -56,41 +56,9 @@ import static org.apache.cassandra.db.marshal.CollectionType.Kind.SET; public class AccordSerializers { - public static ByteBuffer serialize(T item, IVersionedSerializer serializer) + public static EmbeddedAsymmetricVersionedSerializer embedded(Version version, AsymmetricVersionedSerializer serializer) { - int version = MessagingService.current_version; - long size = serializer.serializedSize(item, version) + sizeofUnsignedVInt(version); - try (DataOutputBuffer out = new DataOutputBuffer((int) size)) - { - out.writeUnsignedVInt32(version); - serializer.serialize(item, out, version); - return out.buffer(false); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - public static ByteBuffer[] serialize(List items, IVersionedSerializer serializer) - { - ByteBuffer[] result = new ByteBuffer[items.size()]; - for (int i = 0, mi = items.size(); i < mi; i++) - result[i] = serialize(items.get(i), serializer); - return result; - } - - public static T deserialize(ByteBuffer bytes, IVersionedSerializer serializer) - { - try (DataInputBuffer in = new DataInputBuffer(bytes, true)) - { - int version = in.readUnsignedVInt32(); - return serializer.deserialize(in, version); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + return new EmbeddedAsymmetricVersionedSerializer<>(version, Version.Serializer.instance, serializer); } public static Term.Terminal deserializeCqlCollectionAsTerm(ByteBuffer buffer, AbstractType type) @@ -110,28 +78,28 @@ public class AccordSerializers public static final IVersionedSerializer partitionUpdateSerializer = new IVersionedSerializer() { @Override - public void serialize(PartitionUpdate upd, DataOutputPlus out, int version) throws IOException + public void serialize(PartitionUpdate upd, DataOutputPlus out, Version version) throws IOException { - PartitionUpdate.serializer.serialize(upd, out, version); + PartitionUpdate.serializer.serialize(upd, out, version.messageVersion()); } @Override - public PartitionUpdate deserialize(DataInputPlus in, int version) throws IOException + public PartitionUpdate deserialize(DataInputPlus in, Version version) throws IOException { - return PartitionUpdate.serializer.deserialize(in, version, DeserializationHelper.Flag.FROM_REMOTE); + return PartitionUpdate.serializer.deserialize(in, version.messageVersion(), DeserializationHelper.Flag.FROM_REMOTE); } @Override - public long serializedSize(PartitionUpdate upd, int version) + public long serializedSize(PartitionUpdate upd, Version version) { - return PartitionUpdate.serializer.serializedSize(upd, version); + return PartitionUpdate.serializer.serializedSize(upd, version.messageVersion()); } }; - public static final IVersionedSerializer columnMetadataSerializer = new IVersionedSerializer<>() + public static final UnversionedSerializer columnMetadataSerializer = new UnversionedSerializer() { @Override - public void serialize(ColumnMetadata column, DataOutputPlus out, int version) throws IOException + public void serialize(ColumnMetadata column, DataOutputPlus out) throws IOException { out.writeUTF(column.ksName); out.writeUTF(column.cfName); @@ -139,7 +107,7 @@ public class AccordSerializers } @Override - public ColumnMetadata deserialize(DataInputPlus in, int version) throws IOException + public ColumnMetadata deserialize(DataInputPlus in) throws IOException { String keyspace = in.readUTF(); String table = in.readUTF(); @@ -148,7 +116,7 @@ public class AccordSerializers } @Override - public long serializedSize(ColumnMetadata column, int version) + public long serializedSize(ColumnMetadata column) { long size = 0; size += sizeof(column.ksName); @@ -161,33 +129,33 @@ public class AccordSerializers public static final IVersionedSerializer tableMetadataSerializer = new IVersionedSerializer() { @Override - public void serialize(TableMetadata metadata, DataOutputPlus out, int version) throws IOException + public void serialize(TableMetadata metadata, DataOutputPlus out, Version version) throws IOException { metadata.id.serializeCompact(out); } @Override - public TableMetadata deserialize(DataInputPlus in, int version) throws IOException + public TableMetadata deserialize(DataInputPlus in, Version version) throws IOException { return Schema.instance.getTableMetadata(TableId.deserializeCompact(in)); } @Override - public long serializedSize(TableMetadata metadata, int version) + public long serializedSize(TableMetadata metadata, Version version) { return metadata.id.serializedCompactSize(); } }; - public static final IVersionedSerializer> clusteringSerializer = new IVersionedSerializer>() + public static final UnversionedSerializer> clusteringSerializer = new UnversionedSerializer>() { @Override - public void serialize(Clustering clustering, DataOutputPlus out, int version) throws IOException + public void serialize(Clustering clustering, DataOutputPlus out) throws IOException { doSerialize(clustering, out); } - public void doSerialize(Clustering clustering, DataOutputPlus out) throws IOException + private void doSerialize(Clustering clustering, DataOutputPlus out) throws IOException { if (clustering.kind() == ClusteringPrefix.Kind.STATIC_CLUSTERING) { @@ -206,7 +174,7 @@ public class AccordSerializers } @Override - public Clustering deserialize(DataInputPlus in, int version) throws IOException + public Clustering deserialize(DataInputPlus in) throws IOException { Clustering clustering; if (in.readBoolean()) @@ -229,41 +197,45 @@ public class AccordSerializers } @Override - public long serializedSize(Clustering clustering, int version) + public long serializedSize(Clustering clustering) { return computeSerializedSize(clustering); } private long computeSerializedSize(Clustering clustering) { - int size = sizeof(true) + sizeofUnsignedVInt(clustering.size()); - ValueAccessor accessor = clustering.accessor(); - for (int i = 0; i < clustering.size(); i++) + int size = sizeof(true); + if (clustering.kind() != ClusteringPrefix.Kind.STATIC_CLUSTERING) { - int valueSize = accessor.size(clustering.get(i)); - size += valueSize; - size += sizeofUnsignedVInt(valueSize); + size += sizeofUnsignedVInt(clustering.size()); + ValueAccessor accessor = clustering.accessor(); + for (int i = 0; i < clustering.size(); i++) + { + int valueSize = accessor.size(clustering.get(i)); + size += valueSize; + size += sizeofUnsignedVInt(valueSize); + } } return size; } }; - public static final IVersionedSerializer consistencyLevelSerializer = new IVersionedSerializer() + public static final UnversionedSerializer consistencyLevelSerializer = new UnversionedSerializer() { @Override - public void serialize(ConsistencyLevel t, DataOutputPlus out, int version) throws IOException + public void serialize(ConsistencyLevel t, DataOutputPlus out) throws IOException { out.writeByte(t.code); } @Override - public ConsistencyLevel deserialize(DataInputPlus in, int version) throws IOException + public ConsistencyLevel deserialize(DataInputPlus in) throws IOException { return ConsistencyLevel.fromCode(in.readByte()); } @Override - public long serializedSize(ConsistencyLevel t, int version) + public long serializedSize(ConsistencyLevel t) { return 1; } diff --git a/src/java/org/apache/cassandra/service/accord/AccordStaleReplicas.java b/src/java/org/apache/cassandra/service/accord/AccordStaleReplicas.java index f729759fe6..9d0a01bad1 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordStaleReplicas.java +++ b/src/java/org/apache/cassandra/service/accord/AccordStaleReplicas.java @@ -116,21 +116,21 @@ public class AccordStaleReplicas implements MetadataValue @Override public void serialize(AccordStaleReplicas replicas, DataOutputPlus out, Version version) throws IOException { - CollectionSerializers.serializeCollection(replicas.staleIds, out, version, TopologySerializers.nodeId); + CollectionSerializers.serializeCollection(replicas.staleIds, out, TopologySerializers.nodeId); Epoch.serializer.serialize(replicas.lastModified, out, version); } @Override public AccordStaleReplicas deserialize(DataInputPlus in, Version version) throws IOException { - return new AccordStaleReplicas(CollectionSerializers.deserializeSet(in, version, TopologySerializers.nodeId), + return new AccordStaleReplicas(CollectionSerializers.deserializeSet(in, TopologySerializers.nodeId), Epoch.serializer.deserialize(in, version)); } @Override public long serializedSize(AccordStaleReplicas replicas, Version version) { - return CollectionSerializers.serializedCollectionSize(replicas.staleIds, version, TopologySerializers.nodeId) + return CollectionSerializers.serializedCollectionSize(replicas.staleIds, TopologySerializers.nodeId) + Epoch.serializer.serializedSize(replicas.lastModified, version); } }; diff --git a/src/java/org/apache/cassandra/service/accord/AccordSyncPropagator.java b/src/java/org/apache/cassandra/service/accord/AccordSyncPropagator.java index 59edd7c8bb..5e857d618e 100644 --- a/src/java/org/apache/cassandra/service/accord/AccordSyncPropagator.java +++ b/src/java/org/apache/cassandra/service/accord/AccordSyncPropagator.java @@ -42,7 +42,7 @@ import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.exceptions.RequestFailure; import org.apache.cassandra.gms.Gossiper; import org.apache.cassandra.gms.IFailureDetector; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -363,33 +363,33 @@ public class AccordSyncPropagator public static class Notification { - public static final IVersionedSerializer serializer = new IVersionedSerializer<>() + public static final UnversionedSerializer serializer = new UnversionedSerializer() { @Override - public void serialize(Notification notification, DataOutputPlus out, int version) throws IOException + public void serialize(Notification notification, DataOutputPlus out) throws IOException { out.writeLong(notification.epoch); - CollectionSerializers.serializeCollection(notification.syncComplete, out, version, TopologySerializers.nodeId); - KeySerializers.ranges.serialize(notification.closed, out, version); - KeySerializers.ranges.serialize(notification.retired, out, version); + CollectionSerializers.serializeCollection(notification.syncComplete, out, TopologySerializers.nodeId); + KeySerializers.ranges.serialize(notification.closed, out); + KeySerializers.ranges.serialize(notification.retired, out); } @Override - public Notification deserialize(DataInputPlus in, int version) throws IOException + public Notification deserialize(DataInputPlus in) throws IOException { return new Notification(in.readLong(), - CollectionSerializers.deserializeList(in, version, TopologySerializers.nodeId), - KeySerializers.ranges.deserialize(in, version), - KeySerializers.ranges.deserialize(in, version)); + CollectionSerializers.deserializeList(in, TopologySerializers.nodeId), + KeySerializers.ranges.deserialize(in), + KeySerializers.ranges.deserialize(in)); } @Override - public long serializedSize(Notification notification, int version) + public long serializedSize(Notification notification) { return TypeSizes.LONG_SIZE - + CollectionSerializers.serializedCollectionSize(notification.syncComplete, version, TopologySerializers.nodeId) - + KeySerializers.ranges.serializedSize(notification.closed, version) - + KeySerializers.ranges.serializedSize(notification.retired, version); + + CollectionSerializers.serializedCollectionSize(notification.syncComplete, TopologySerializers.nodeId) + + KeySerializers.ranges.serializedSize(notification.closed) + + KeySerializers.ranges.serializedSize(notification.retired); } }; diff --git a/src/java/org/apache/cassandra/service/accord/FetchTopologies.java b/src/java/org/apache/cassandra/service/accord/FetchTopologies.java index 9cef181178..f9af39d2e2 100644 --- a/src/java/org/apache/cassandra/service/accord/FetchTopologies.java +++ b/src/java/org/apache/cassandra/service/accord/FetchTopologies.java @@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; import accord.topology.Topology; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.exceptions.RequestFailure; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -61,23 +61,23 @@ public class FetchTopologies private final long minEpoch; private final long maxEpoch; - public static final IVersionedSerializer serializer = new IVersionedSerializer<>() + public static final UnversionedSerializer serializer = new UnversionedSerializer<>() { @Override - public void serialize(FetchTopologies t, DataOutputPlus out, int version) throws IOException + public void serialize(FetchTopologies t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt(t.minEpoch); out.writeUnsignedVInt(t.maxEpoch); } @Override - public FetchTopologies deserialize(DataInputPlus in, int version) throws IOException + public FetchTopologies deserialize(DataInputPlus in) throws IOException { return new FetchTopologies(in.readUnsignedVInt(), in.readUnsignedVInt()); } @Override - public long serializedSize(FetchTopologies t, int version) + public long serializedSize(FetchTopologies t) { return TypeSizes.sizeofUnsignedVInt(t.minEpoch) + TypeSizes.sizeofUnsignedVInt(t.maxEpoch); @@ -90,11 +90,10 @@ public class FetchTopologies this.maxEpoch = maxEpoch; } - // TODO (required): messaging version after version patch - public static final IVersionedSerializer responseSerializer = new IVersionedSerializer<>() + public static final UnversionedSerializer responseSerializer = new UnversionedSerializer<>() { @Override - public void serialize(TopologyRange t, DataOutputPlus out, int version) throws IOException + public void serialize(TopologyRange t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt(t.min); out.writeUnsignedVInt(t.current); @@ -102,11 +101,11 @@ public class FetchTopologies out.writeUnsignedVInt32(t.topologies.size()); for (Topology topology : t.topologies) - TopologySerializers.topology.serialize(topology, out, version); + TopologySerializers.topology.serialize(topology, out); } @Override - public TopologyRange deserialize(DataInputPlus in, int version) throws IOException + public TopologyRange deserialize(DataInputPlus in) throws IOException { long min = in.readUnsignedVInt(); long current = in.readUnsignedVInt(); @@ -114,19 +113,19 @@ public class FetchTopologies int count = in.readUnsignedVInt32(); List topologies = new ArrayList<>(count); for (int i = 0; i < count; ++i) - topologies.add(TopologySerializers.topology.deserialize(in, version)); + topologies.add(TopologySerializers.topology.deserialize(in)); return new TopologyRange(min, current, firstNonEmpty, topologies); } @Override - public long serializedSize(TopologyRange t, int version) + public long serializedSize(TopologyRange t) { long size = TypeSizes.sizeofUnsignedVInt(t.min); size += TypeSizes.sizeofUnsignedVInt(t.current); size += TypeSizes.sizeofUnsignedVInt(t.firstNonEmpty); size += TypeSizes.sizeofUnsignedVInt(t.topologies.size()); for (Topology topology : t.topologies) - size += TopologySerializers.topology.serializedSize(topology, version); + size += TopologySerializers.topology.serializedSize(topology); return size; } }; diff --git a/src/java/org/apache/cassandra/service/accord/TokenRange.java b/src/java/org/apache/cassandra/service/accord/TokenRange.java index 4bd03281ea..3b546a74de 100644 --- a/src/java/org/apache/cassandra/service/accord/TokenRange.java +++ b/src/java/org/apache/cassandra/service/accord/TokenRange.java @@ -29,7 +29,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.dht.Token; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.TableId; @@ -120,33 +120,33 @@ public class TokenRange extends Range.EndInclusive public static final Serializer serializer = new Serializer(); - public static final class Serializer implements IVersionedSerializer + public static final class Serializer implements UnversionedSerializer { @Override - public void serialize(TokenRange range, DataOutputPlus out, int version) throws IOException + public void serialize(TokenRange range, DataOutputPlus out) throws IOException { - TokenKey.serializer.serialize(range.start(), out, version); - TokenKey.serializer.serialize(range.end(), out, version); + TokenKey.serializer.serialize(range.start(), out); + TokenKey.serializer.serialize(range.end(), out); } - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { - TokenKey.serializer.skip(in, version); - TokenKey.serializer.skip(in, version); + TokenKey.serializer.skip(in); + TokenKey.serializer.skip(in); } @Override - public TokenRange deserialize(DataInputPlus in, int version) throws IOException + public TokenRange deserialize(DataInputPlus in) throws IOException { - return TokenRange.create(TokenKey.serializer.deserialize(in, version), - TokenKey.serializer.deserialize(in, version)); + return TokenRange.create(TokenKey.serializer.deserialize(in), + TokenKey.serializer.deserialize(in)); } @Override - public long serializedSize(TokenRange range, int version) + public long serializedSize(TokenRange range) { - return TokenKey.serializer.serializedSize(range.start(), version) - + TokenKey.serializer.serializedSize(range.end(), version); + return TokenKey.serializer.serializedSize(range.start()) + + TokenKey.serializer.serializedSize(range.end()); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/WatermarkCollector.java b/src/java/org/apache/cassandra/service/accord/WatermarkCollector.java index 13e0d529ac..c4c3cb22cf 100644 --- a/src/java/org/apache/cassandra/service/accord/WatermarkCollector.java +++ b/src/java/org/apache/cassandra/service/accord/WatermarkCollector.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import com.google.common.annotations.VisibleForTesting; @@ -38,7 +39,7 @@ import accord.utils.Invariants; import accord.utils.async.AsyncResult; import org.agrona.collections.Int2ObjectHashMap; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -172,22 +173,38 @@ public class WatermarkCollector implements ConfigurationService.Listener this.retired = retired; this.synced = synced; } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Snapshot snapshot = (Snapshot) o; + return closed.equals(snapshot.closed) && retired.equals(snapshot.retired) && synced.equals(snapshot.synced); + } + + @Override + public int hashCode() + { + return Objects.hash(closed, retired, synced); + } } - public static final IVersionedSerializer serializer = new IVersionedSerializer<>() + public static final UnversionedSerializer serializer = new UnversionedSerializer<>() { - public void serialize(Snapshot t, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(Snapshot t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(t.closed.size()); for (Map.Entry e : t.closed.entrySet()) { - TokenRange.serializer.serialize((TokenRange) e.getKey(), out, version); + TokenRange.serializer.serialize((TokenRange) e.getKey(), out); out.writeUnsignedVInt(e.getValue()); } out.writeUnsignedVInt32(t.retired.size()); for (Map.Entry e : t.retired.entrySet()) { - TokenRange.serializer.serialize((TokenRange) e.getKey(), out, version); + TokenRange.serializer.serialize((TokenRange) e.getKey(), out); out.writeUnsignedVInt(e.getValue()); } out.writeUnsignedVInt32(t.synced.size()); @@ -199,20 +216,21 @@ public class WatermarkCollector implements ConfigurationService.Listener } // TODO (desired): we do not have to deserialize to report these values - public Snapshot deserialize(DataInputPlus in, int version) throws IOException + @Override + public Snapshot deserialize(DataInputPlus in) throws IOException { int closedSize = in.readUnsignedVInt32(); Map closed = new HashMap<>(); for (int i = 0; i < closedSize; i++) { - closed.put(TokenRange.serializer.deserialize(in, version), + closed.put(TokenRange.serializer.deserialize(in), in.readUnsignedVInt()); } int retiredSize = in.readUnsignedVInt32(); Map retired = new HashMap<>(); for (int i = 0; i < retiredSize; i++) { - retired.put(TokenRange.serializer.deserialize(in, version), + retired.put(TokenRange.serializer.deserialize(in), in.readUnsignedVInt()); } int syncedSize = in.readUnsignedVInt32(); @@ -225,19 +243,20 @@ public class WatermarkCollector implements ConfigurationService.Listener return new Snapshot(closed, retired, synced); } - public long serializedSize(Snapshot t, int version) + @Override + public long serializedSize(Snapshot t) { int size = 0; size += TypeSizes.sizeofUnsignedVInt(t.closed.size()); for (Map.Entry e : t.closed.entrySet()) { - size += TokenRange.serializer.serializedSize((TokenRange) e.getKey(), version); + size += TokenRange.serializer.serializedSize((TokenRange) e.getKey()); size += TypeSizes.sizeofUnsignedVInt(e.getValue()); } size += TypeSizes.sizeofUnsignedVInt(t.retired.size()); for (Map.Entry e : t.retired.entrySet()) { - size += TokenRange.serializer.serializedSize((TokenRange) e.getKey(), version); + size += TokenRange.serializer.serializedSize((TokenRange) e.getKey()); size += TypeSizes.sizeofUnsignedVInt(e.getValue()); } size += TypeSizes.sizeofUnsignedVInt(t.synced.size()); diff --git a/src/java/org/apache/cassandra/service/accord/api/AccordRoutableKey.java b/src/java/org/apache/cassandra/service/accord/api/AccordRoutableKey.java index b9c2613db5..8a2d5c1ce7 100644 --- a/src/java/org/apache/cassandra/service/accord/api/AccordRoutableKey.java +++ b/src/java/org/apache/cassandra/service/accord/api/AccordRoutableKey.java @@ -24,16 +24,16 @@ import javax.annotation.Nonnull; import accord.primitives.RoutableKey; import org.apache.cassandra.dht.Token; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.TableId; public abstract class AccordRoutableKey implements RoutableKey { - public interface AccordKeySerializer extends IVersionedSerializer + public interface AccordKeySerializer extends UnversionedSerializer { - void skip(DataInputPlus in, int version) throws IOException; + void skip(DataInputPlus in) throws IOException; } public interface AccordSearchableKeySerializer extends AccordKeySerializer @@ -42,15 +42,16 @@ public abstract class AccordRoutableKey implements RoutableKey int fixedKeyLengthForPrefix(Object prefix); int serializedSizeOfPrefix(Object prefix); int serializedSizeWithoutPrefix(K key); - void serializePrefix(Object prefix, DataOutputPlus out, int version) throws IOException; - void serializeWithoutPrefixOrLength(K key, DataOutputPlus out, int version) throws IOException; - Object deserializePrefix(DataInputPlus in, int version) throws IOException; - K deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException; + void serializePrefix(Object prefix, DataOutputPlus out) throws IOException; + void serializeWithoutPrefixOrLength(K key, DataOutputPlus out) throws IOException; + Object deserializePrefix(DataInputPlus in) throws IOException; + K deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException; } static final byte MAX_TABLE_SENTINEL = 0x48; static final byte NORMAL_SENTINEL = 0x28; static final byte BEFORE_TOKEN_SENTINEL = 0x24; + static final byte AFTER_TOKEN_SENTINEL = 0x2c; static final byte MIN_TABLE_SENTINEL = 0x18; static final int PREFIX_MASK = 0xF0; static final int SUFFIX_MASK = 0x0F; diff --git a/src/java/org/apache/cassandra/service/accord/api/PartitionKey.java b/src/java/org/apache/cassandra/service/accord/api/PartitionKey.java index f42166f890..2e47d0678f 100644 --- a/src/java/org/apache/cassandra/service/accord/api/PartitionKey.java +++ b/src/java/org/apache/cassandra/service/accord/api/PartitionKey.java @@ -128,7 +128,7 @@ public final class PartitionKey extends AccordRoutableKey implements Key private Serializer() {} @Override - public void serialize(PartitionKey key, DataOutputPlus out, int version) throws IOException + public void serialize(PartitionKey key, DataOutputPlus out) throws IOException { key.table().serializeCompact(out); ByteBufferUtil.writeWithShortLength(key.partitionKey().getKey(), out); @@ -149,14 +149,14 @@ public final class PartitionKey extends AccordRoutableKey implements Key } @Override - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { TableId.skipCompact(in); ByteBufferUtil.skipShortLength(in); } @Override - public PartitionKey deserialize(DataInputPlus in, int version) throws IOException + public PartitionKey deserialize(DataInputPlus in) throws IOException { TableId tableId = TableId.deserializeCompact(in).intern(); DecoratedKey key = getPartitioner().decorateKey(ByteBufferUtil.readWithShortLength(in)); @@ -176,11 +176,6 @@ public final class PartitionKey extends AccordRoutableKey implements Key } @Override - public long serializedSize(PartitionKey key, int version) - { - return serializedSize(key); - } - public long serializedSize(PartitionKey key) { return key.table().serializedCompactSize() + ByteBufferUtil.serializedSizeWithShortLength(key.partitionKey().getKey()); diff --git a/src/java/org/apache/cassandra/service/accord/api/TokenKey.java b/src/java/org/apache/cassandra/service/accord/api/TokenKey.java index 216a410ada..24aa2ac9bc 100644 --- a/src/java/org/apache/cassandra/service/accord/api/TokenKey.java +++ b/src/java/org/apache/cassandra/service/accord/api/TokenKey.java @@ -50,11 +50,6 @@ import static org.apache.cassandra.config.DatabaseDescriptor.getPartitioner; public final class TokenKey extends AccordRoutableKey implements RoutingKey, RangeFactory { - public enum RoutingKeyKind - { - TOKEN, SENTINEL, MIN_TOKEN - } - private static final long EMPTY_SIZE = ObjectSizes.measure(new TokenKey(null, null)); @Override @@ -66,7 +61,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran // we use the first 2 bits as a prefix, and the last 6 bits as a postfix comparison final byte sentinel; final Token token; - public TokenKey(TableId tableId, byte sentinel, Token token) + private TokenKey(TableId tableId, byte sentinel, Token token) { super(tableId); this.sentinel = sentinel; @@ -109,6 +104,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran @VisibleForTesting public TokenKey before() { + Invariants.require(!isTokenSentinel(), "Unable to call .before() when already a token sentinel: %s", this); int lowestBit = Integer.lowestOneBit(sentinel); Invariants.require(lowestBit != 1); byte newSentinel = (byte)((sentinel ^ lowestBit) | (lowestBit >>> 1)); @@ -119,6 +115,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran @VisibleForTesting public TokenKey after() { + Invariants.require(!isTokenSentinel(), "Unable to call .after() when already a token sentinel: %s", this); int lowestBit = Integer.lowestOneBit(sentinel); // we can't use 0xf as we would not be able to disambiguate with variable length byte encoding escape Invariants.require((lowestBit != 1) && (sentinel & 0xf) != 0xe); @@ -138,7 +135,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran if (isSentinel()) { if (isTableSentinel()) suffix = isMin() ? "-Inf" : "+Inf"; - else suffix = suffix + "(-epsilon)"; + if (isTokenSentinel()) suffix = (isBefore() ? "before(" : "after(") + suffix + ')'; } return suffix; } @@ -149,16 +146,6 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran return prefix() + ":" + printableSuffix(); } - public boolean isMin() - { - return sentinel == MIN_TABLE_SENTINEL; - } - - public boolean isMax() - { - return sentinel == MAX_TABLE_SENTINEL; - } - public long estimatedSizeOnHeap() { return EMPTY_SIZE + token().getHeapSize(); @@ -193,6 +180,20 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran return this; } + public boolean isMin() + { + //TODO (review): some code paths don't care if before/after are used, but some are not fully correct (range.isFullRange) +// return sentinel == MIN_TABLE_SENTINEL; + return (sentinel & PREFIX_MASK) == (MIN_TABLE_SENTINEL & PREFIX_MASK); + } + + public boolean isMax() + { + //TODO (review): some code paths don't care if before/after are used, but some are not fully correct (range.isFullRange) +// return sentinel == MAX_TABLE_SENTINEL; + return (sentinel & PREFIX_MASK) == (MAX_TABLE_SENTINEL & PREFIX_MASK); + } + public boolean isSentinel() { return sentinel != NORMAL_SENTINEL; @@ -208,6 +209,16 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran return (sentinel & SUFFIX_MASK) != (NORMAL_SENTINEL & SUFFIX_MASK); } + public boolean isBefore() + { + return (sentinel & SUFFIX_MASK) == (BEFORE_TOKEN_SENTINEL & SUFFIX_MASK); + } + + public boolean isAfter() + { + return (sentinel & SUFFIX_MASK) == (AFTER_TOKEN_SENTINEL & SUFFIX_MASK); + } + public static TokenKey min(TableId table, IPartitioner partitioner) { return new TokenKey(table, MIN_TABLE_SENTINEL, partitioner.getMinimumToken()); @@ -231,7 +242,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran // types are byte comparable only after any length component @Override - public long serializedSize(TokenKey key, int version) + public long serializedSize(TokenKey key) { IPartitioner partitioner = key.token.getPartitioner(); int size = 2 + key.table.serializedCompactComparableSize(); @@ -243,7 +254,7 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran } @Override - public void serialize(TokenKey key, DataOutputPlus out, int version) throws IOException + public void serialize(TokenKey key, DataOutputPlus out) throws IOException { IPartitioner partitioner = key.token.getPartitioner(); int fixedLength = partitioner.accordFixedLength(); @@ -253,30 +264,30 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran out.writeUnsignedVInt32(len); } key.table.serializeCompactComparable(out); - serializeWithoutPrefixOrLength(key, out, version); + serializeWithoutPrefixOrLength(key, out); } @Override - public TokenKey deserialize(DataInputPlus in, int version) throws IOException + public TokenKey deserialize(DataInputPlus in) throws IOException { - return deserialize(in, version, getPartitioner()); + return deserialize(in, getPartitioner()); } - public TokenKey deserialize(DataInputPlus in, int version, IPartitioner partitioner) throws IOException + public TokenKey deserialize(DataInputPlus in, IPartitioner partitioner) throws IOException { int len = partitioner.accordFixedLength(); if (len < 0) len = in.readUnsignedVInt32(); - TableId tableId = deserializePrefix(in, version); - return deserializeWithPrefix(tableId, len + 2, in, version, partitioner); + TableId tableId = deserializePrefix(in); + return deserializeWithPrefix(tableId, len + 2, in, partitioner); } @Override - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { - skip(in, version, getPartitioner()); + skip(in, getPartitioner()); } - public void skip(DataInputPlus in, int version, IPartitioner partitioner) throws IOException + public void skip(DataInputPlus in, IPartitioner partitioner) throws IOException { int len = partitioner.accordFixedLength(); if (len < 0) len = in.readUnsignedVInt32(); @@ -342,13 +353,13 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran } @Override - public void serializePrefix(Object prefix, DataOutputPlus out, int version) throws IOException + public void serializePrefix(Object prefix, DataOutputPlus out) throws IOException { ((TableId)prefix).serializeCompactComparable(out); } @Override - public void serializeWithoutPrefixOrLength(TokenKey key, DataOutputPlus out, int version) throws IOException + public void serializeWithoutPrefixOrLength(TokenKey key, DataOutputPlus out) throws IOException { out.write(key.prefixSentinel()); key.token.getPartitioner().accordSerialize(key.token, out); @@ -377,18 +388,18 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran } @Override - public TableId deserializePrefix(DataInputPlus in, int version) throws IOException + public TableId deserializePrefix(DataInputPlus in) throws IOException { return TableId.deserializeCompactComparable(in); } @Override - public TokenKey deserializeWithPrefix(Object tableId, int length, DataInputPlus in, int version) throws IOException + public TokenKey deserializeWithPrefix(Object tableId, int length, DataInputPlus in) throws IOException { - return deserializeWithPrefix(tableId, length, in, version, getPartitioner()); + return deserializeWithPrefix(tableId, length, in, getPartitioner()); } - public TokenKey deserializeWithPrefix(Object tableId, int length, DataInputPlus in, int version, IPartitioner partitioner) throws IOException + public TokenKey deserializeWithPrefix(Object tableId, int length, DataInputPlus in, IPartitioner partitioner) throws IOException { byte sentinel = in.readByte(); Token token = partitioner.accordDeserialize(in, length - 2); diff --git a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropApply.java b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropApply.java index fe3a1c74b3..7dd0a4f03b 100644 --- a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropApply.java +++ b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropApply.java @@ -44,9 +44,9 @@ import accord.topology.Topologies; import accord.utils.UnhandledEnum; import org.agrona.collections.Int2ObjectHashMap; import org.apache.cassandra.db.ConsistencyLevel; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.service.accord.AccordMessageSink.AccordMessageType; import org.apache.cassandra.service.accord.serializers.ApplySerializers.ApplySerializer; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.txn.AccordUpdate; import org.apache.cassandra.tcm.ClusterMetadata; diff --git a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropRead.java b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropRead.java index 0998c72634..c7e5d36af8 100644 --- a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropRead.java +++ b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropRead.java @@ -51,7 +51,6 @@ import org.apache.cassandra.db.ReadCommandVerbHandler; import org.apache.cassandra.db.ReadResponse; import org.apache.cassandra.db.SinglePartitionReadCommand; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -61,9 +60,11 @@ import org.apache.cassandra.service.accord.AccordMessageSink.AccordMessageType; import org.apache.cassandra.service.accord.TokenRange; import org.apache.cassandra.service.accord.api.TokenKey; import org.apache.cassandra.service.accord.serializers.CommandSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.ReadDataSerializers; import org.apache.cassandra.service.accord.serializers.ReadDataSerializers.ReadDataSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.accord.txn.TxnNamedRead; import org.apache.cassandra.service.accord.txn.TxnRead; import org.apache.cassandra.utils.Pair; @@ -79,31 +80,31 @@ public class AccordInteropRead extends ReadData public static final IVersionedSerializer requestSerializer = new ReadDataSerializer() { @Override - public void serialize(AccordInteropRead read, DataOutputPlus out, int version) throws IOException + public void serialize(AccordInteropRead read, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(read.txnId, out, version); - KeySerializers.participants.serialize(read.scope, out, version); + CommandSerializers.txnId.serialize(read.txnId, out); + KeySerializers.participants.serialize(read.scope, out); out.writeUnsignedVInt(read.executeAtEpoch); - ReadCommand.serializer.serialize(read.command, out, version); + ReadCommand.serializer.serialize(read.command, out, version.messageVersion()); } @Override - public AccordInteropRead deserialize(DataInputPlus in, int version) throws IOException + public AccordInteropRead deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long executeAtEpoch = in.readUnsignedVInt(); - ReadCommand command = ReadCommand.serializer.deserialize(in, version); + ReadCommand command = ReadCommand.serializer.deserialize(in, version.messageVersion()); return new AccordInteropRead(txnId, scope, executeAtEpoch, command); } @Override - public long serializedSize(AccordInteropRead read, int version) + public long serializedSize(AccordInteropRead read, Version version) { - return CommandSerializers.txnId.serializedSize(read.txnId, version) - + KeySerializers.participants.serializedSize(read.scope, version) + return CommandSerializers.txnId.serializedSize(read.txnId) + + KeySerializers.participants.serializedSize(read.scope) + TypeSizes.sizeofUnsignedVInt(read.executeAtEpoch) - + ReadCommand.serializer.serializedSize(read.command, version); + + ReadCommand.serializer.serializedSize(read.command, version.messageVersion()); } }; @@ -116,23 +117,23 @@ public class AccordInteropRead extends ReadData static final IVersionedSerializer serializer = new IVersionedSerializer<>() { @Override - public void serialize(LocalReadData data, DataOutputPlus out, int version) throws IOException + public void serialize(LocalReadData data, DataOutputPlus out, Version version) throws IOException { data.ensureRemoteResponse(); - ReadResponse.serializer.serialize(data.remoteResponse, out, version); + ReadResponse.serializer.serialize(data.remoteResponse, out, version.messageVersion()); } @Override - public LocalReadData deserialize(DataInputPlus in, int version) throws IOException + public LocalReadData deserialize(DataInputPlus in, Version version) throws IOException { - return new LocalReadData(ReadResponse.serializer.deserialize(in, version)); + return new LocalReadData(ReadResponse.serializer.deserialize(in, version.messageVersion())); } @Override - public long serializedSize(LocalReadData data, int version) + public long serializedSize(LocalReadData data, Version version) { data.ensureRemoteResponse(); - return ReadResponse.serializer.serializedSize(data.remoteResponse, version); + return ReadResponse.serializer.serializedSize(data.remoteResponse, version.messageVersion()); } }; diff --git a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropReadRepair.java b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropReadRepair.java index be71dc0953..f74b6625c2 100644 --- a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropReadRepair.java +++ b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropReadRepair.java @@ -38,7 +38,6 @@ import accord.utils.async.AsyncChains; import org.apache.cassandra.db.Mutation; import org.apache.cassandra.db.ReadRepairVerbHandler; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -48,9 +47,11 @@ import org.apache.cassandra.net.RequestCallback; import org.apache.cassandra.net.Verb; import org.apache.cassandra.service.accord.AccordMessageSink.AccordMessageType; import org.apache.cassandra.service.accord.serializers.CommandSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.ReadDataSerializers; import org.apache.cassandra.service.accord.serializers.ReadDataSerializers.ReadDataSerializer; +import org.apache.cassandra.service.accord.serializers.Version; /** * Applies a read repair mutation from inside the context of a CommandStore via AbstractExecute @@ -62,31 +63,31 @@ public class AccordInteropReadRepair extends ReadData public static final IVersionedSerializer requestSerializer = new ReadDataSerializer() { @Override - public void serialize(AccordInteropReadRepair repair, DataOutputPlus out, int version) throws IOException + public void serialize(AccordInteropReadRepair repair, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(repair.txnId, out, version); - KeySerializers.participants.serialize(repair.scope, out, version); + CommandSerializers.txnId.serialize(repair.txnId, out); + KeySerializers.participants.serialize(repair.scope, out); out.writeUnsignedVInt(repair.executeAtEpoch); - Mutation.serializer.serialize(repair.mutation, out, version); + Mutation.serializer.serialize(repair.mutation, out, version.messageVersion()); } @Override - public AccordInteropReadRepair deserialize(DataInputPlus in, int version) throws IOException + public AccordInteropReadRepair deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long executeAtEpoch = in.readUnsignedVInt(); - Mutation mutation = Mutation.serializer.deserialize(in, version); + Mutation mutation = Mutation.serializer.deserialize(in, version.messageVersion()); return new AccordInteropReadRepair(txnId, scope, executeAtEpoch, mutation); } @Override - public long serializedSize(AccordInteropReadRepair repair, int version) + public long serializedSize(AccordInteropReadRepair repair, Version version) { - return CommandSerializers.txnId.serializedSize(repair.txnId, version) - + KeySerializers.participants.serializedSize(repair.scope, version) + return CommandSerializers.txnId.serializedSize(repair.txnId) + + KeySerializers.participants.serializedSize(repair.scope) + TypeSizes.sizeofUnsignedVInt(repair.executeAtEpoch) - + Mutation.serializer.serializedSize(repair.mutation, version); + + Mutation.serializer.serializedSize(repair.mutation, version.messageVersion()); } }; @@ -111,11 +112,11 @@ public class AccordInteropReadRepair extends ReadData private static final IVersionedSerializer noop_data_serializer = new IVersionedSerializer<>() { @Override - public void serialize(Data t, DataOutputPlus out, int version) throws IOException {} + public void serialize(Data t, DataOutputPlus out, Version version) throws IOException {} @Override - public Data deserialize(DataInputPlus in, int version) throws IOException { return Data.NOOP_DATA; } + public Data deserialize(DataInputPlus in, Version version) throws IOException { return Data.NOOP_DATA; } - public long serializedSize(Data t, int version) { return 0; } + public long serializedSize(Data t, Version version) { return 0; } }; public static final IVersionedSerializer replySerializer = new ReadDataSerializers.ReplySerializer<>(noop_data_serializer); diff --git a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropStableThenRead.java b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropStableThenRead.java index 8916c220ee..4f282467b7 100644 --- a/src/java/org/apache/cassandra/service/accord/interop/AccordInteropStableThenRead.java +++ b/src/java/org/apache/cassandra/service/accord/interop/AccordInteropStableThenRead.java @@ -41,7 +41,6 @@ import accord.primitives.TxnId; import accord.topology.Topologies; import org.apache.cassandra.db.ReadCommand; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.AccordMessageSink.AccordMessageType; @@ -49,8 +48,10 @@ import org.apache.cassandra.service.accord.serializers.CommandSerializers; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; import org.apache.cassandra.service.accord.serializers.CommitSerializers; import org.apache.cassandra.service.accord.serializers.DepsSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.ReadDataSerializers.ReadDataSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import static accord.messages.Commit.WithDeps.HasDeps; import static accord.messages.Commit.WithDeps.NoDeps; @@ -65,49 +66,49 @@ public class AccordInteropStableThenRead extends AccordInteropRead public static final IVersionedSerializer requestSerializer = new ReadDataSerializer<>() { @Override - public void serialize(AccordInteropStableThenRead read, DataOutputPlus out, int version) throws IOException + public void serialize(AccordInteropStableThenRead read, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(read.txnId, out, version); - KeySerializers.participants.serialize(read.scope, out, version); - CommitSerializers.kind.serialize(read.kind, out, version); + CommandSerializers.txnId.serialize(read.txnId, out); + KeySerializers.participants.serialize(read.scope, out); + CommitSerializers.kind.serialize(read.kind, out); out.writeUnsignedVInt(read.minEpoch); ExecuteAtSerializer.serialize(read.txnId, read.executeAt, out); if (read.kind.withTxn != NoTxn) CommandSerializers.nullablePartialTxn.serialize(read.partialTxn, out, version); if (read.kind.withDeps == HasDeps) - DepsSerializers.partialDeps.serialize(read.partialDeps, out, version); + DepsSerializers.partialDeps.serialize(read.partialDeps, out); if (read.kind.withTxn == HasTxn) - KeySerializers.fullRoute.serialize(read.route, out, version); - ReadCommand.serializer.serialize(read.command, out, version); + KeySerializers.fullRoute.serialize(read.route, out); + ReadCommand.serializer.serialize(read.command, out, version.messageVersion()); } @Override - public AccordInteropStableThenRead deserialize(DataInputPlus in, int version) throws IOException + public AccordInteropStableThenRead deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); - Commit.Kind kind = CommitSerializers.kind.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); + Commit.Kind kind = CommitSerializers.kind.deserialize(in); long minEpoch = in.readUnsignedVInt(); Timestamp executeAt = ExecuteAtSerializer.deserialize(txnId, in); PartialTxn partialTxn = kind.withTxn == NoTxn ? null : CommandSerializers.nullablePartialTxn.deserialize(in, version); - PartialDeps partialDeps = kind.withDeps == NoDeps ? null : DepsSerializers.partialDeps.deserialize(in, version); - FullRoute < ?> route = kind.withTxn == HasTxn ? KeySerializers.fullRoute.deserialize(in, version) : null; - ReadCommand command = ReadCommand.serializer.deserialize(in, version); + PartialDeps partialDeps = kind.withDeps == NoDeps ? null : DepsSerializers.partialDeps.deserialize(in); + FullRoute < ?> route = kind.withTxn == HasTxn ? KeySerializers.fullRoute.deserialize(in) : null; + ReadCommand command = ReadCommand.serializer.deserialize(in, version.messageVersion()); return new AccordInteropStableThenRead(txnId, scope, kind, minEpoch, executeAt, partialTxn, partialDeps, route, command); } @Override - public long serializedSize(AccordInteropStableThenRead read, int version) + public long serializedSize(AccordInteropStableThenRead read, Version version) { - return CommandSerializers.txnId.serializedSize(read.txnId, version) - + KeySerializers.participants.serializedSize(read.scope, version) - + CommitSerializers.kind.serializedSize(read.kind, version) + return CommandSerializers.txnId.serializedSize(read.txnId) + + KeySerializers.participants.serializedSize(read.scope) + + CommitSerializers.kind.serializedSize(read.kind) + TypeSizes.sizeofUnsignedVInt(read.minEpoch) + ExecuteAtSerializer.serializedSize(read.txnId, read.executeAt) + (read.kind.withTxn == NoTxn ? 0 : CommandSerializers.nullablePartialTxn.serializedSize(read.partialTxn, version)) - + (read.kind.withDeps != HasDeps ? 0 : DepsSerializers.partialDeps.serializedSize(read.partialDeps, version)) - + (read.kind.withTxn != HasTxn ? 0 : KeySerializers.fullRoute.serializedSize(read.route, version)) - + ReadCommand.serializer.serializedSize(read.command, version); + + (read.kind.withDeps != HasDeps ? 0 : DepsSerializers.partialDeps.serializedSize(read.partialDeps)) + + (read.kind.withTxn != HasTxn ? 0 : KeySerializers.fullRoute.serializedSize(read.route)) + + ReadCommand.serializer.serializedSize(read.command, version.messageVersion()); } }; diff --git a/src/java/org/apache/cassandra/service/accord/journal/AccordTopologyUpdate.java b/src/java/org/apache/cassandra/service/accord/journal/AccordTopologyUpdate.java index e48882e15e..86eff7369e 100644 --- a/src/java/org/apache/cassandra/service/accord/journal/AccordTopologyUpdate.java +++ b/src/java/org/apache/cassandra/service/accord/journal/AccordTopologyUpdate.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.NavigableMap; +import java.util.Objects; import java.util.TreeMap; import java.util.function.Function; @@ -34,7 +35,7 @@ import accord.utils.Invariants; import accord.utils.UnhandledEnum; import org.agrona.collections.Int2ObjectHashMap; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.AccordConfigurationService; @@ -42,6 +43,7 @@ import org.apache.cassandra.service.accord.AccordJournalValueSerializers; import org.apache.cassandra.service.accord.JournalKey; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.TopologySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import static org.apache.cassandra.service.accord.JournalKey.Type.TOPOLOGY_UPDATE; @@ -55,29 +57,23 @@ public interface AccordTopologyUpdate { return new NewTopology(update); } - class RangesForEpochSerializer implements IVersionedSerializer + class RangesForEpochSerializer implements UnversionedSerializer { public static final RangesForEpochSerializer instance = new RangesForEpochSerializer(); @Override - public void serialize(CommandStores.RangesForEpoch from, DataOutputPlus out, int version) throws IOException + public void serialize(CommandStores.RangesForEpoch from, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(from.size()); - from.forEach((epoch, ranges) -> { - try - { - out.writeLong(epoch); - KeySerializers.ranges.serialize(ranges, out, version); - } - catch (Throwable t) - { - throw new IllegalStateException("Serialization error", t); - } - }); + for (int i = 0; i < from.size(); i++) + { + out.writeLong(from.epochAtIndex(i)); + KeySerializers.ranges.serialize(from.rangesAtIndex(i), out); + } } @Override - public CommandStores.RangesForEpoch deserialize(DataInputPlus in, int version) throws IOException + public CommandStores.RangesForEpoch deserialize(DataInputPlus in) throws IOException { int size = in.readUnsignedVInt32(); Ranges[] ranges = new Ranges[size]; @@ -85,120 +81,130 @@ public interface AccordTopologyUpdate for (int i = 0; i < ranges.length; i++) { epochs[i] = in.readLong(); - ranges[i] = KeySerializers.ranges.deserialize(in, version); + ranges[i] = KeySerializers.ranges.deserialize(in); } Invariants.require(ranges.length == epochs.length); return new CommandStores.RangesForEpoch(epochs, ranges); } @Override - public long serializedSize(CommandStores.RangesForEpoch t, int version) + public long serializedSize(CommandStores.RangesForEpoch from) { - return TypeSizes.sizeofUnsignedVInt(t.size()); + long size = TypeSizes.sizeofUnsignedVInt(from.size()); + for (int i = 0; i < from.size(); i++) + { + size += TypeSizes.sizeof(from.epochAtIndex(i)); + size += KeySerializers.ranges.serializedSize(from.rangesAtIndex(i)); + } + return size; } } - class TopologyUpdateSerializer implements IVersionedSerializer + class TopologyUpdateSerializer implements UnversionedSerializer { public static final TopologyUpdateSerializer instance = new TopologyUpdateSerializer(); @Override - public void serialize(Journal.TopologyUpdate from, DataOutputPlus out, int version) throws IOException + public void serialize(Journal.TopologyUpdate from, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(from.commandStores.size()); for (Map.Entry e : from.commandStores.entrySet()) { out.writeUnsignedVInt32(e.getKey()); - RangesForEpochSerializer.instance.serialize(e.getValue(), out, version); + RangesForEpochSerializer.instance.serialize(e.getValue(), out); } - TopologySerializers.topology.serialize(from.local, out, version); - TopologySerializers.topology.serialize(from.global, out, version); + //TODO (performance): local to what? Rather than serializing local we can serialize the node its relative too? that why when we deserialize we do globa.forNode(node) + // this also decreases the size as we don't have redundent shards + TopologySerializers.topology.serialize(from.local, out); + TopologySerializers.topology.serialize(from.global, out); } @Override - public Journal.TopologyUpdate deserialize(DataInputPlus in, int version) throws IOException + public Journal.TopologyUpdate deserialize(DataInputPlus in) throws IOException { int commandStoresSize = in.readUnsignedVInt32(); Int2ObjectHashMap commandStores = new Int2ObjectHashMap<>(); for (int j = 0; j < commandStoresSize; j++) { int commandStoreId = in.readUnsignedVInt32(); - CommandStores.RangesForEpoch rangesForEpoch = RangesForEpochSerializer.instance.deserialize(in, version); + CommandStores.RangesForEpoch rangesForEpoch = RangesForEpochSerializer.instance.deserialize(in); commandStores.put(commandStoreId, rangesForEpoch); } - Topology local = TopologySerializers.topology.deserialize(in, version); - Topology global = TopologySerializers.topology.deserialize(in, version); + Topology local = TopologySerializers.topology.deserialize(in); + Topology global = TopologySerializers.topology.deserialize(in); return new Journal.TopologyUpdate(commandStores, local, global); } @Override - public long serializedSize(Journal.TopologyUpdate from, int version) + public long serializedSize(Journal.TopologyUpdate from) { long size = TypeSizes.sizeofUnsignedVInt(from.commandStores.size()); for (Map.Entry e : from.commandStores.entrySet()) { size += TypeSizes.sizeofUnsignedVInt(e.getKey()); - size += RangesForEpochSerializer.instance.serializedSize(e.getValue(), version); + size += RangesForEpochSerializer.instance.serializedSize(e.getValue()); } - size += TopologySerializers.topology.serializedSize(from.local, version); - size += TopologySerializers.topology.serializedSize(from.global, version); + size += TopologySerializers.topology.serializedSize(from.local); + size += TopologySerializers.topology.serializedSize(from.global); return size; } } - class Serializer implements IVersionedSerializer + class Serializer implements UnversionedSerializer { public static Serializer instance = new Serializer(); - public void serialize(AccordTopologyUpdate t, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(AccordTopologyUpdate t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt(t.epoch()); out.writeUnsignedVInt32(t.kind().ordinal()); switch (t.kind()) { case NewTopology: - TopologyUpdateSerializer.instance.serialize(((NewTopology) t).update, out, version); + TopologyUpdateSerializer.instance.serialize(((NewTopology) t).update, out); break; case Topologies: TopologyImage image = (TopologyImage) t; out.writeBoolean(image.update != null); if (image.update != null) - TopologyUpdateSerializer.instance.serialize(image.update, out, version); + TopologyUpdateSerializer.instance.serialize(image.update, out); if (image.syncStatus == null) out.writeByte(Byte.MAX_VALUE); else out.writeByte(image.syncStatus.ordinal()); - KeySerializers.ranges.serialize(image.closed, out, version); - KeySerializers.ranges.serialize(image.retired, out, version); + KeySerializers.ranges.serialize(image.closed, out); + KeySerializers.ranges.serialize(image.retired, out); break; default: throw new UnhandledEnum(t.kind()); } } - public AccordTopologyUpdate deserialize(DataInputPlus in, int version) throws IOException + @Override + public AccordTopologyUpdate deserialize(DataInputPlus in) throws IOException { - int epoch = in.readUnsignedVInt32(); + long epoch = in.readUnsignedVInt(); Kind kind = Kind.values()[in.readUnsignedVInt32()]; switch (kind) { case NewTopology: - return new NewTopology(TopologyUpdateSerializer.instance.deserialize(in, version)); + return new NewTopology(TopologyUpdateSerializer.instance.deserialize(in)); case Topologies: { TopologyImage image = new TopologyImage(epoch); if (in.readBoolean()) - image.update = TopologyUpdateSerializer.instance.deserialize(in, version); + image.update = TopologyUpdateSerializer.instance.deserialize(in); byte syncStateByte = in.readByte(); if (syncStateByte != Byte.MAX_VALUE) image.syncStatus = AccordConfigurationService.SyncStatus.values()[syncStateByte]; - image.closed = KeySerializers.ranges.deserialize(in, version); - image.retired = KeySerializers.ranges.deserialize(in, version); + image.closed = KeySerializers.ranges.deserialize(in); + image.retired = KeySerializers.ranges.deserialize(in); return image; } default: @@ -206,7 +212,8 @@ public interface AccordTopologyUpdate } } - public long serializedSize(AccordTopologyUpdate t, int version) + @Override + public long serializedSize(AccordTopologyUpdate t) { long size = TypeSizes.sizeofUnsignedVInt(t.epoch()); size += TypeSizes.sizeofUnsignedVInt(t.kind().ordinal()); @@ -214,19 +221,19 @@ public interface AccordTopologyUpdate switch (t.kind()) { case NewTopology: - size += TopologyUpdateSerializer.instance.serializedSize(((NewTopology) t).update, version); + size += TopologyUpdateSerializer.instance.serializedSize(((NewTopology) t).update); break; case Topologies: TopologyImage image = (TopologyImage) t; size += TypeSizes.sizeof(image.update != null); if (image.update != null) - size += TopologyUpdateSerializer.instance.serializedSize(image.update, version); + size += TopologyUpdateSerializer.instance.serializedSize(image.update); size += Byte.BYTES; - size += KeySerializers.ranges.serializedSize(image.closed, version); - size += KeySerializers.ranges.serializedSize(image.retired, version); + size += KeySerializers.ranges.serializedSize(image.closed); + size += KeySerializers.ranges.serializedSize(image.retired); break; default: throw new UnhandledEnum(t.kind()); @@ -288,11 +295,26 @@ public interface AccordTopologyUpdate accumulator.closed = accumulator.closed.with(closed); accumulator.retired = accumulator.retired.with(retired); } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TopologyImage that = (TopologyImage) o; + return epoch == that.epoch && Objects.equals(update, that.update) && syncStatus == that.syncStatus && closed.equals(that.closed) && retired.equals(that.retired); + } + + @Override + public int hashCode() + { + return Objects.hash(update, syncStatus, closed, retired, epoch); + } } class NewTopology implements AccordTopologyUpdate { - private final Journal.TopologyUpdate update; + public final Journal.TopologyUpdate update; private final long epoch; public NewTopology(Journal.TopologyUpdate update) @@ -320,6 +342,21 @@ public interface AccordTopologyUpdate Invariants.require(accumulator.update == null); accumulator.update = update; } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NewTopology that = (NewTopology) o; + return epoch == that.epoch && update.equals(that.update); + } + + @Override + public int hashCode() + { + return Objects.hash(update, epoch); + } } class Accumulator @@ -384,28 +421,28 @@ public interface AccordTopologyUpdate } @Override - public void serialize(JournalKey key, AccordTopologyUpdate from, DataOutputPlus out, int version) throws IOException + public void serialize(JournalKey key, AccordTopologyUpdate from, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt32(1); - Serializer.instance.serialize(from, out, version); + Serializer.instance.serialize(from, out); } @Override - public void reserialize(JournalKey key, Accumulator from, DataOutputPlus out, int version) throws IOException + public void reserialize(JournalKey key, Accumulator from, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt32(from.get().size()); for (TopologyImage value : from.get().values()) - Serializer.instance.serialize(value, out, version); + Serializer.instance.serialize(value, out); } @Override - public void deserialize(JournalKey key, Accumulator into, DataInputPlus in, int version) throws IOException + public void deserialize(JournalKey key, Accumulator into, DataInputPlus in, Version version) throws IOException { long minEpoch = this.minEpoch.epoch(); int count = in.readUnsignedVInt32(); while (--count >= 0) { - AccordTopologyUpdate update = Serializer.instance.deserialize(in, version); + AccordTopologyUpdate update = Serializer.instance.deserialize(in); if (update.epoch() >= minEpoch) into.update(update); else diff --git a/src/java/org/apache/cassandra/service/accord/serializers/AcceptSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/AcceptSerializers.java index fb96385eea..d7603b6981 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/AcceptSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/AcceptSerializers.java @@ -31,7 +31,7 @@ import accord.primitives.Route; import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -49,69 +49,69 @@ public class AcceptSerializers private static final int IS_PARTIAL = 1; @Override - public void serializeBody(Accept accept, DataOutputPlus out, int version) throws IOException + public void serializeBody(Accept accept, DataOutputPlus out, Version version) throws IOException { out.writeByte((accept.kind.ordinal() << 1) | (accept.isPartialAccept ? IS_PARTIAL : 0)); - CommandSerializers.ballot.serialize(accept.ballot, out, version); + CommandSerializers.ballot.serialize(accept.ballot, out); ExecuteAtSerializer.serialize(accept.txnId, accept.executeAt, out); - DepsSerializers.partialDeps.serialize(accept.partialDeps, out, version); + DepsSerializers.partialDeps.serialize(accept.partialDeps, out); } @Override - public Accept deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public Accept deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { int flags = in.readByte(); Accept.Kind kind = kinds[(flags >>> 1) & 1]; return create(txnId, scope, waitForEpoch, minEpoch, kind, - CommandSerializers.ballot.deserialize(in, version), + CommandSerializers.ballot.deserialize(in), ExecuteAtSerializer.deserialize(txnId, in), - DepsSerializers.partialDeps.deserialize(in, version), + DepsSerializers.partialDeps.deserialize(in), (flags & IS_PARTIAL) != 0); } @Override - public long serializedBodySize(Accept accept, int version) + public long serializedBodySize(Accept accept, Version version) { return 1 - + CommandSerializers.ballot.serializedSize(accept.ballot, version) + + CommandSerializers.ballot.serializedSize(accept.ballot) + ExecuteAtSerializer.serializedSize(accept.txnId, accept.executeAt) - + DepsSerializers.partialDeps.serializedSize(accept.partialDeps, version); + + DepsSerializers.partialDeps.serializedSize(accept.partialDeps); } - }; + } - public static final IVersionedSerializer notAccept = new IVersionedSerializer<>() + public static final UnversionedSerializer notAccept = new UnversionedSerializer<>() { @Override - public void serialize(Accept.NotAccept invalidate, DataOutputPlus out, int version) throws IOException + public void serialize(Accept.NotAccept invalidate, DataOutputPlus out) throws IOException { - CommandSerializers.status.serialize(invalidate.status, out, version); - CommandSerializers.ballot.serialize(invalidate.ballot, out, version); - CommandSerializers.txnId.serialize(invalidate.txnId, out, version); - KeySerializers.participants.serialize(invalidate.participants, out, version); + CommandSerializers.status.serialize(invalidate.status, out); + CommandSerializers.ballot.serialize(invalidate.ballot, out); + CommandSerializers.txnId.serialize(invalidate.txnId, out); + KeySerializers.participants.serialize(invalidate.participants, out); } @Override - public Accept.NotAccept deserialize(DataInputPlus in, int version) throws IOException + public Accept.NotAccept deserialize(DataInputPlus in) throws IOException { - return new Accept.NotAccept(CommandSerializers.status.deserialize(in, version), - CommandSerializers.ballot.deserialize(in, version), - CommandSerializers.txnId.deserialize(in, version), - KeySerializers.participants.deserialize(in, version)); + return new Accept.NotAccept(CommandSerializers.status.deserialize(in), + CommandSerializers.ballot.deserialize(in), + CommandSerializers.txnId.deserialize(in), + KeySerializers.participants.deserialize(in)); } @Override - public long serializedSize(Accept.NotAccept invalidate, int version) + public long serializedSize(Accept.NotAccept invalidate) { - return CommandSerializers.status.serializedSize(invalidate.status, version) - + CommandSerializers.ballot.serializedSize(invalidate.ballot, version) - + CommandSerializers.txnId.serializedSize(invalidate.txnId, version) - + KeySerializers.participants.serializedSize(invalidate.participants, version); + return CommandSerializers.status.serializedSize(invalidate.status) + + CommandSerializers.ballot.serializedSize(invalidate.ballot) + + CommandSerializers.txnId.serializedSize(invalidate.txnId) + + KeySerializers.participants.serializedSize(invalidate.participants); } }; - public static final IVersionedSerializer reply = new ReplySerializer(); - public static class ReplySerializer implements IVersionedSerializer + public static final UnversionedSerializer reply = new ReplySerializer(); + public static class ReplySerializer implements UnversionedSerializer { // we have one spare bit at 0x04 for either another flag or more AcceptOutcome variants private static final int SUPERSEDED_BY = 0x08; @@ -120,7 +120,7 @@ public class AcceptSerializers private static final int DEPS = 0x40; private static final int FLAGS = 0x80; @Override - public void serialize(AcceptReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(AcceptReply reply, DataOutputPlus out) throws IOException { int flags = reply.outcome.ordinal() | (reply.supersededBy != null ? SUPERSEDED_BY : 0) @@ -131,46 +131,46 @@ public class AcceptSerializers out.writeByte(flags); if (reply.supersededBy != null) - CommandSerializers.ballot.serialize(reply.supersededBy, out, version); + CommandSerializers.ballot.serialize(reply.supersededBy, out); if (reply.committedExecuteAt != null) ExecuteAtSerializer.serialize(reply.committedExecuteAt, out); if (reply.successful != null) - KeySerializers.participants.serialize(reply.successful, out, version); + KeySerializers.participants.serialize(reply.successful, out); if (reply.deps != null) - DepsSerializers.deps.serialize(reply.deps, out, version); + DepsSerializers.deps.serialize(reply.deps, out); if (!reply.flags.isEmpty()) out.writeUnsignedVInt32(reply.flags.bits()); } private final AcceptOutcome[] outcomes = AcceptOutcome.values(); @Override - public AcceptReply deserialize(DataInputPlus in, int version) throws IOException + public AcceptReply deserialize(DataInputPlus in) throws IOException { int flags = in.readByte(); AcceptOutcome outcome = outcomes[flags & 3]; - Ballot supersededBy = (flags & SUPERSEDED_BY) == 0 ? null : CommandSerializers.ballot.deserialize(in, version); + Ballot supersededBy = (flags & SUPERSEDED_BY) == 0 ? null : CommandSerializers.ballot.deserialize(in); Timestamp committedExecuteAt = (flags & COMMITTED_EXECUTE_AT) == 0 ? null : ExecuteAtSerializer.deserialize(in); - Participants successful = (flags & SUCCESSFUL) == 0 ? null : KeySerializers.participants.deserialize(in, version); - Deps deps = (flags & DEPS) == 0 ? null : DepsSerializers.deps.deserialize(in, version); + Participants successful = (flags & SUCCESSFUL) == 0 ? null : KeySerializers.participants.deserialize(in); + Deps deps = (flags & DEPS) == 0 ? null : DepsSerializers.deps.deserialize(in); ExecuteFlags executeFlags = (flags & FLAGS) == 0 ? ExecuteFlags.none() : ExecuteFlags.get(in.readUnsignedVInt32()); return new AcceptReply(outcome, supersededBy, successful, deps, committedExecuteAt, executeFlags); } @Override - public long serializedSize(AcceptReply reply, int version) + public long serializedSize(AcceptReply reply) { long size = TypeSizes.BYTE_SIZE; if (reply.supersededBy != null) - size += CommandSerializers.ballot.serializedSize(reply.supersededBy, version); + size += CommandSerializers.ballot.serializedSize(reply.supersededBy); if (reply.committedExecuteAt != null) size += ExecuteAtSerializer.serializedSize(reply.committedExecuteAt); if (reply.successful != null) - size += KeySerializers.participants.serializedSize(reply.successful, version); + size += KeySerializers.participants.serializedSize(reply.successful); if (reply.deps != null) - size += DepsSerializers.deps.serializedSize(reply.deps, version); + size += DepsSerializers.deps.serializedSize(reply.deps); if (!reply.flags.isEmpty()) size += TypeSizes.sizeofUnsignedVInt(reply.flags.bits()); return size; } - }; + } } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/ApplySerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/ApplySerializers.java index 11574c9e08..d4fd7f3ce5 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/ApplySerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/ApplySerializers.java @@ -31,7 +31,7 @@ import accord.primitives.TxnId; import accord.primitives.Writes; import accord.utils.Invariants; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -41,20 +41,20 @@ import static accord.primitives.Txn.Kind.Write; public class ApplySerializers { - private static final IVersionedSerializer kind = new IVersionedSerializer<>() + private static final UnversionedSerializer kind = new UnversionedSerializer<>() { - public void serialize(Apply.Kind kind, DataOutputPlus out, int version) throws IOException + public void serialize(Apply.Kind kind, DataOutputPlus out) throws IOException { Invariants.requireArgument(kind == Apply.Kind.Maximal || kind == Apply.Kind.Minimal); out.writeBoolean(kind == Apply.Kind.Maximal); } - public Apply.Kind deserialize(DataInputPlus in, int version) throws IOException + public Apply.Kind deserialize(DataInputPlus in) throws IOException { return in.readBoolean() ? Apply.Kind.Maximal : Apply.Kind.Minimal; } - public long serializedSize(Apply.Kind t, int version) + public long serializedSize(Apply.Kind t) { return TypeSizes.BOOL_SIZE; } @@ -63,14 +63,14 @@ public class ApplySerializers public abstract static class ApplySerializer extends TxnRequestSerializer { @Override - public void serializeBody(A apply, DataOutputPlus out, int version) throws IOException + public void serializeBody(A apply, DataOutputPlus out, Version version) throws IOException { out.writeVInt(apply.minEpoch - apply.waitForEpoch); - kind.serialize(apply.kind, out, version); + kind.serialize(apply.kind, out); ExecuteAtSerializer.serialize(apply.txnId, apply.executeAt, out); - DepsSerializers.partialDeps.serialize(apply.deps, out, version); + DepsSerializers.partialDeps.serialize(apply.deps, out); CommandSerializers.nullablePartialTxn.serialize(apply.txn, out, version); - KeySerializers.nullableFullRoute.serialize(apply.fullRoute, out, version); + KeySerializers.nullableFullRoute.serialize(apply.fullRoute, out); if (apply.txnId.is(Write)) CommandSerializers.writes.serialize(apply.writes, out, version); } @@ -79,27 +79,27 @@ public class ApplySerializers Timestamp executeAt, PartialDeps deps, PartialTxn txn, FullRoute fullRoute, Writes writes, Result result); @Override - public A deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch) throws IOException + public A deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch) throws IOException { return deserializeApply(txnId, scope, waitForEpoch + in.readVInt(), waitForEpoch, - kind.deserialize(in, version), + kind.deserialize(in), ExecuteAtSerializer.deserialize(txnId, in), - DepsSerializers.partialDeps.deserialize(in, version), + DepsSerializers.partialDeps.deserialize(in), CommandSerializers.nullablePartialTxn.deserialize(in, version), - KeySerializers.nullableFullRoute.deserialize(in, version), + KeySerializers.nullableFullRoute.deserialize(in), (txnId.is(Write) ? CommandSerializers.writes.deserialize(in, version) : null), ResultSerializers.APPLIED); } @Override - public long serializedBodySize(A apply, int version) + public long serializedBodySize(A apply, Version version) { return TypeSizes.sizeofVInt(apply.minEpoch - apply.waitForEpoch) - + kind.serializedSize(apply.kind, version) + + kind.serializedSize(apply.kind) + ExecuteAtSerializer.serializedSize(apply.txnId, apply.executeAt) - + DepsSerializers.partialDeps.serializedSize(apply.deps, version) + + DepsSerializers.partialDeps.serializedSize(apply.deps) + CommandSerializers.nullablePartialTxn.serializedSize(apply.txn, version) - + KeySerializers.nullableFullRoute.serializedSize(apply.fullRoute, version) + + KeySerializers.nullableFullRoute.serializedSize(apply.fullRoute) + (apply.txnId.is(Write) ? CommandSerializers.writes.serializedSize(apply.writes, version) : 0); } } @@ -114,24 +114,24 @@ public class ApplySerializers } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { private final Apply.ApplyReply[] replies = Apply.ApplyReply.values(); @Override - public void serialize(Apply.ApplyReply t, DataOutputPlus out, int version) throws IOException + public void serialize(Apply.ApplyReply t, DataOutputPlus out) throws IOException { out.writeByte(t.ordinal()); } @Override - public Apply.ApplyReply deserialize(DataInputPlus in, int version) throws IOException + public Apply.ApplyReply deserialize(DataInputPlus in) throws IOException { return replies[in.readByte()]; } @Override - public long serializedSize(Apply.ApplyReply t, int version) + public long serializedSize(Apply.ApplyReply t) { return 1; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/AsymmetricVersionedSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/AsymmetricVersionedSerializer.java new file mode 100644 index 0000000000..987762bd03 --- /dev/null +++ b/src/java/org/apache/cassandra/service/accord/serializers/AsymmetricVersionedSerializer.java @@ -0,0 +1,23 @@ +/* + * 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.service.accord.serializers; + +public interface AsymmetricVersionedSerializer extends org.apache.cassandra.io.AsymmetricVersionedSerializer +{ +} diff --git a/src/java/org/apache/cassandra/service/accord/serializers/AwaitSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/AwaitSerializers.java index 3341c2e218..d08d1bb822 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/AwaitSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/AwaitSerializers.java @@ -32,54 +32,54 @@ import accord.primitives.SaveStatus; import accord.primitives.TxnId; import accord.utils.Invariants; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.vint.VIntCoding; public class AwaitSerializers { - public static final IVersionedSerializer request = new RequestSerializer<>() + public static final UnversionedSerializer request = new RequestSerializer<>() { @Override - public Await deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in, int version) + public Await deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in) { return Await.SerializerSupport.create(txnId, scope, blockedUntil, notifyProgressLog, minAwaitEpoch, maxAwaitEpoch, callbackId); } }; - public static final IVersionedSerializer recoverRequest = new RequestSerializer<>() + public static final UnversionedSerializer recoverRequest = new RequestSerializer<>() { @Override - public RecoverAwait deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in, int version) throws IOException + public RecoverAwait deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in) throws IOException { - TxnId recoverId = CommandSerializers.txnId.deserialize(in, version); + TxnId recoverId = CommandSerializers.txnId.deserialize(in); return RecoverAwait.SerializerSupport.create(txnId, scope, blockedUntil, notifyProgressLog, minAwaitEpoch, maxAwaitEpoch, callbackId, recoverId); } @Override - public void serialize(RecoverAwait await, DataOutputPlus out, int version) throws IOException + public void serialize(RecoverAwait await, DataOutputPlus out) throws IOException { - super.serialize(await, out, version); - CommandSerializers.txnId.serialize(await.recoverId, out, version); + super.serialize(await, out); + CommandSerializers.txnId.serialize(await.recoverId, out); } @Override - public long serializedSize(RecoverAwait await, int version) + public long serializedSize(RecoverAwait await) { - return super.serializedSize(await, version) + CommandSerializers.txnId.serializedSize(await.recoverId, version); + return super.serializedSize(await) + CommandSerializers.txnId.serializedSize(await.recoverId); } }; - static abstract class RequestSerializer implements IVersionedSerializer + static abstract class RequestSerializer implements UnversionedSerializer { - abstract A deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in, int version) throws IOException; + abstract A deserialize(TxnId txnId, Participants scope, BlockedUntil blockedUntil, boolean notifyProgressLog, long minAwaitEpoch, long maxAwaitEpoch, int callbackId, DataInputPlus in) throws IOException; @Override - public void serialize(A await, DataOutputPlus out, int version) throws IOException + public void serialize(A await, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(await.txnId, out, version); - KeySerializers.participants.serialize(await.scope, out, version); + CommandSerializers.txnId.serialize(await.txnId, out); + KeySerializers.participants.serialize(await.scope, out); out.writeByte((await.blockedUntil.ordinal() << 1) | (await.notifyProgressLog ? 1 : 0)); out.writeUnsignedVInt(await.maxAwaitEpoch - await.txnId.epoch()); out.writeUnsignedVInt(await.maxAwaitEpoch - await.minAwaitEpoch); @@ -88,10 +88,10 @@ public class AwaitSerializers } @Override - public A deserialize(DataInputPlus in, int version) throws IOException + public A deserialize(DataInputPlus in) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); int blockedAndNotify = in.readByte(); BlockedUntil blockedUntil = BlockedUntil.forOrdinal(blockedAndNotify >>> 1); boolean notifyProgressLog = (blockedAndNotify & 1) == 1; @@ -99,50 +99,50 @@ public class AwaitSerializers long minAwaitEpoch = maxAwaitEpoch - in.readUnsignedVInt(); int callbackId = in.readUnsignedVInt32() - 1; Invariants.require(callbackId >= -1); - return deserialize(txnId, scope, blockedUntil, notifyProgressLog, minAwaitEpoch, maxAwaitEpoch, callbackId, in, version); + return deserialize(txnId, scope, blockedUntil, notifyProgressLog, minAwaitEpoch, maxAwaitEpoch, callbackId, in); } @Override - public long serializedSize(A await, int version) + public long serializedSize(A await) { - return CommandSerializers.txnId.serializedSize(await.txnId, version) - + KeySerializers.participants.serializedSize(await.scope, version) + return CommandSerializers.txnId.serializedSize(await.txnId) + + KeySerializers.participants.serializedSize(await.scope) + TypeSizes.BYTE_SIZE + VIntCoding.computeUnsignedVIntSize(await.maxAwaitEpoch - await.txnId.epoch()) + VIntCoding.computeUnsignedVIntSize(await.maxAwaitEpoch - await.minAwaitEpoch) + VIntCoding.computeUnsignedVIntSize(await.callbackId + 1); } - }; + } - public static final IVersionedSerializer syncReply = EncodeAsVInt32.of(AwaitOk.class); - public static final IVersionedSerializer recoverReply = EncodeAsVInt32.of(RecoverAwaitOk.class); + public static final UnversionedSerializer syncReply = EncodeAsVInt32.of(AwaitOk.class); + public static final UnversionedSerializer recoverReply = EncodeAsVInt32.of(RecoverAwaitOk.class); - public static final IVersionedSerializer asyncReply = new IVersionedSerializer<>() + public static final UnversionedSerializer asyncReply = new UnversionedSerializer<>() { @Override - public void serialize(AsyncAwaitComplete ok, DataOutputPlus out, int version) throws IOException + public void serialize(AsyncAwaitComplete ok, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(ok.txnId, out, version); - KeySerializers.route.serialize(ok.route, out, version); + CommandSerializers.txnId.serialize(ok.txnId, out); + KeySerializers.route.serialize(ok.route, out); out.writeByte(ok.newStatus.ordinal()); out.writeUnsignedVInt32(ok.callbackId); } @Override - public AsyncAwaitComplete deserialize(DataInputPlus in, int version) throws IOException + public AsyncAwaitComplete deserialize(DataInputPlus in) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Route scope = KeySerializers.route.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Route scope = KeySerializers.route.deserialize(in); SaveStatus newStatus = SaveStatus.forOrdinal(in.readByte()); int callbackId = in.readUnsignedVInt32(); return new AsyncAwaitComplete(txnId, scope, newStatus, callbackId); } @Override - public long serializedSize(AsyncAwaitComplete ok, int version) + public long serializedSize(AsyncAwaitComplete ok) { - return CommandSerializers.txnId.serializedSize(ok.txnId, version) - + KeySerializers.route.serializedSize(ok.route, version) + return CommandSerializers.txnId.serializedSize(ok.txnId) + + KeySerializers.route.serializedSize(ok.route) + TypeSizes.BYTE_SIZE + VIntCoding.computeVIntSize(ok.callbackId); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/BeginInvalidationSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/BeginInvalidationSerializers.java index 8eeed391a7..6ec96618a1 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/BeginInvalidationSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/BeginInvalidationSerializers.java @@ -28,80 +28,80 @@ import accord.primitives.Participants; import accord.primitives.Route; import accord.primitives.SaveStatus; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; public class BeginInvalidationSerializers { - public static final IVersionedSerializer request = new IVersionedSerializer<>() + public static final UnversionedSerializer request = new UnversionedSerializer<>() { @Override - public void serialize(BeginInvalidation begin, DataOutputPlus out, int version) throws IOException + public void serialize(BeginInvalidation begin, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(begin.txnId, out, version); - KeySerializers.participants.serialize(begin.participants, out, version); - CommandSerializers.ballot.serialize(begin.ballot, out, version); + CommandSerializers.txnId.serialize(begin.txnId, out); + KeySerializers.participants.serialize(begin.participants, out); + CommandSerializers.ballot.serialize(begin.ballot, out); } @Override - public BeginInvalidation deserialize(DataInputPlus in, int version) throws IOException + public BeginInvalidation deserialize(DataInputPlus in) throws IOException { - return new BeginInvalidation(CommandSerializers.txnId.deserialize(in, version), - KeySerializers.participants.deserialize(in, version), - CommandSerializers.ballot.deserialize(in, version)); + return new BeginInvalidation(CommandSerializers.txnId.deserialize(in), + KeySerializers.participants.deserialize(in), + CommandSerializers.ballot.deserialize(in)); } @Override - public long serializedSize(BeginInvalidation begin, int version) + public long serializedSize(BeginInvalidation begin) { - return CommandSerializers.txnId.serializedSize(begin.txnId, version) - + KeySerializers.participants.serializedSize(begin.participants, version) - + CommandSerializers.ballot.serializedSize(begin.ballot, version); + return CommandSerializers.txnId.serializedSize(begin.txnId) + + KeySerializers.participants.serializedSize(begin.participants) + + CommandSerializers.ballot.serializedSize(begin.ballot); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { @Override - public void serialize(InvalidateReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(InvalidateReply reply, DataOutputPlus out) throws IOException { - CommandSerializers.ballot.serialize(reply.supersededBy, out, version); - CommandSerializers.ballot.serialize(reply.accepted, out, version); - CommandSerializers.saveStatus.serialize(reply.maxStatus, out, version); - CommandSerializers.saveStatus.serialize(reply.maxKnowledgeStatus, out, version); + CommandSerializers.ballot.serialize(reply.supersededBy, out); + CommandSerializers.ballot.serialize(reply.accepted, out); + CommandSerializers.saveStatus.serialize(reply.maxStatus, out); + CommandSerializers.saveStatus.serialize(reply.maxKnowledgeStatus, out); out.writeBoolean(reply.acceptedFastPath); - KeySerializers.nullableParticipants.serialize(reply.truncated, out, version); - KeySerializers.nullableRoute.serialize(reply.route, out, version); - KeySerializers.nullableRoutingKey.serialize(reply.homeKey, out, version); + KeySerializers.nullableParticipants.serialize(reply.truncated, out); + KeySerializers.nullableRoute.serialize(reply.route, out); + KeySerializers.nullableRoutingKey.serialize(reply.homeKey, out); } @Override - public InvalidateReply deserialize(DataInputPlus in, int version) throws IOException + public InvalidateReply deserialize(DataInputPlus in) throws IOException { // TODO (expected): use headers instead of nullable+bool serializers - Ballot supersededBy = CommandSerializers.ballot.deserialize(in, version); - Ballot accepted = CommandSerializers.ballot.deserialize(in, version); - SaveStatus maxStatus = CommandSerializers.saveStatus.deserialize(in, version); - SaveStatus maxKnowledgeStatus = CommandSerializers.saveStatus.deserialize(in, version); + Ballot supersededBy = CommandSerializers.ballot.deserialize(in); + Ballot accepted = CommandSerializers.ballot.deserialize(in); + SaveStatus maxStatus = CommandSerializers.saveStatus.deserialize(in); + SaveStatus maxKnowledgeStatus = CommandSerializers.saveStatus.deserialize(in); boolean acceptedFastPath = in.readBoolean(); - Participants truncated = KeySerializers.nullableParticipants.deserialize(in, version); - Route route = KeySerializers.nullableRoute.deserialize(in, version); - RoutingKey homeKey = KeySerializers.nullableRoutingKey.deserialize(in, version); + Participants truncated = KeySerializers.nullableParticipants.deserialize(in); + Route route = KeySerializers.nullableRoute.deserialize(in); + RoutingKey homeKey = KeySerializers.nullableRoutingKey.deserialize(in); return new InvalidateReply(supersededBy, accepted, maxStatus, maxKnowledgeStatus, acceptedFastPath, truncated, route, homeKey); } @Override - public long serializedSize(InvalidateReply reply, int version) + public long serializedSize(InvalidateReply reply) { - return CommandSerializers.ballot.serializedSize(reply.supersededBy, version) - + CommandSerializers.ballot.serializedSize(reply.accepted, version) - + CommandSerializers.saveStatus.serializedSize(reply.maxStatus, version) - + CommandSerializers.saveStatus.serializedSize(reply.maxKnowledgeStatus, version) + return CommandSerializers.ballot.serializedSize(reply.supersededBy) + + CommandSerializers.ballot.serializedSize(reply.accepted) + + CommandSerializers.saveStatus.serializedSize(reply.maxStatus) + + CommandSerializers.saveStatus.serializedSize(reply.maxKnowledgeStatus) + TypeSizes.BOOL_SIZE - + KeySerializers.nullableParticipants.serializedSize(reply.truncated, version) - + KeySerializers.nullableRoute.serializedSize(reply.route, version) - + KeySerializers.nullableRoutingKey.serializedSize(reply.homeKey, version); + + KeySerializers.nullableParticipants.serializedSize(reply.truncated) + + KeySerializers.nullableRoute.serializedSize(reply.route) + + KeySerializers.nullableRoutingKey.serializedSize(reply.homeKey); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/CheckStatusSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/CheckStatusSerializers.java index 2905ec6370..9933f53f9b 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/CheckStatusSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/CheckStatusSerializers.java @@ -42,7 +42,7 @@ import accord.primitives.Timestamp; import accord.primitives.TxnId; import accord.primitives.Writes; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -52,15 +52,15 @@ import static org.apache.cassandra.service.accord.serializers.CommandSerializers public class CheckStatusSerializers { - public static final IVersionedSerializer knownMap = new IVersionedSerializer<>() + public static final UnversionedSerializer knownMap = new UnversionedSerializer<>() { @Override - public void serialize(KnownMap knownMap, DataOutputPlus out, int version) throws IOException + public void serialize(KnownMap knownMap, DataOutputPlus out) throws IOException { int size = knownMap.size(); out.writeUnsignedVInt32(size); for (int i = 0 ; i <= size ; ++i) - KeySerializers.routingKey.serialize(knownMap.startAt(i), out, version); + KeySerializers.routingKey.serialize(knownMap.startAt(i), out); for (int i = 0 ; i < size ; ++i) { KnownMap.MinMax minMax = knownMap.valueAt(i); @@ -71,39 +71,39 @@ public class CheckStatusSerializers } boolean equal = minMax.min.equals(minMax); out.writeByte(equal ? 1 : 2); - known.serialize(minMax.min, out, version); + known.serialize(minMax.min, out); if (!equal) - known.serialize(minMax, out, version); + known.serialize(minMax, out); } } @Override - public KnownMap deserialize(DataInputPlus in, int version) throws IOException + public KnownMap deserialize(DataInputPlus in) throws IOException { int size = in.readUnsignedVInt32(); RoutingKey[] starts = new RoutingKey[size + 1]; for (int i = 0 ; i <= size ; ++i) - starts[i] = KeySerializers.routingKey.deserialize(in, version); + starts[i] = KeySerializers.routingKey.deserialize(in); MinMax[] values = new MinMax[size]; for (int i = 0 ; i < size ; ++i) { int kind = in.readByte(); if (kind == 0) continue; - Known min = known.deserialize(in, version); - Known max = kind == 1 ? min : known.deserialize(in, version); + Known min = known.deserialize(in); + Known max = kind == 1 ? min : known.deserialize(in); values[i] = new KnownMap.MinMax(min, max); } return KnownMap.SerializerSupport.create(true, starts, values); } @Override - public long serializedSize(KnownMap knownMap, int version) + public long serializedSize(KnownMap knownMap) { int size = knownMap.size(); long result = TypeSizes.sizeofUnsignedVInt(size); for (int i = 0 ; i <= size ; ++i) - result += KeySerializers.routingKey.serializedSize(knownMap.startAt(i), version); + result += KeySerializers.routingKey.serializedSize(knownMap.startAt(i)); for (int i = 0 ; i < size ; ++i) { KnownMap.MinMax minMax = knownMap.valueAt(i); @@ -111,42 +111,42 @@ public class CheckStatusSerializers if (minMax == null) continue; boolean equal = minMax.min.equals(minMax); - result += known.serializedSize(minMax.min, version); + result += known.serializedSize(minMax.min); if (!equal) - result += known.serializedSize(minMax, version); + result += known.serializedSize(minMax); } return result; } }; - public static final IVersionedSerializer request = new IVersionedSerializer<>() + public static final UnversionedSerializer request = new UnversionedSerializer<>() { final CheckStatus.IncludeInfo[] infos = CheckStatus.IncludeInfo.values(); @Override - public void serialize(CheckStatus check, DataOutputPlus out, int version) throws IOException + public void serialize(CheckStatus check, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(check.txnId, out, version); - KeySerializers.participants.serialize(check.query, out, version); + CommandSerializers.txnId.serialize(check.txnId, out); + KeySerializers.participants.serialize(check.query, out); out.writeUnsignedVInt(check.sourceEpoch); out.writeByte(check.includeInfo.ordinal()); } @Override - public CheckStatus deserialize(DataInputPlus in, int version) throws IOException + public CheckStatus deserialize(DataInputPlus in) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants query = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants query = KeySerializers.participants.deserialize(in); long sourceEpoch = in.readUnsignedVInt(); CheckStatus.IncludeInfo info = infos[in.readByte()]; return new CheckStatus(txnId, query, sourceEpoch, info); } @Override - public long serializedSize(CheckStatus check, int version) + public long serializedSize(CheckStatus check) { - return CommandSerializers.txnId.serializedSize(check.txnId, version) - + KeySerializers.participants.serializedSize(check.query, version) + return CommandSerializers.txnId.serializedSize(check.txnId) + + KeySerializers.participants.serializedSize(check.query) + TypeSizes.sizeofUnsignedVInt(check.sourceEpoch) + TypeSizes.BYTE_SIZE; } @@ -159,7 +159,7 @@ public class CheckStatusSerializers private static final byte NACK = 0x02; @Override - public void serialize(CheckStatusReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(CheckStatusReply reply, DataOutputPlus out, Version version) throws IOException { if (!reply.isOk()) { @@ -169,30 +169,30 @@ public class CheckStatusSerializers CheckStatusOk ok = (CheckStatusOk) reply; out.write(reply instanceof CheckStatusOkFull ? FULL : OK); - knownMap.serialize(ok.map, out, version); - CommandSerializers.saveStatus.serialize(ok.maxKnowledgeSaveStatus, out, version); - CommandSerializers.saveStatus.serialize(ok.maxSaveStatus, out, version); - CommandSerializers.ballot.serialize(ok.maxPromised, out, version); - CommandSerializers.ballot.serialize(ok.maxAcceptedOrCommitted, out, version); - CommandSerializers.ballot.serialize(ok.acceptedOrCommitted, out, version); + knownMap.serialize(ok.map, out); + CommandSerializers.saveStatus.serialize(ok.maxKnowledgeSaveStatus, out); + CommandSerializers.saveStatus.serialize(ok.maxSaveStatus, out); + CommandSerializers.ballot.serialize(ok.maxPromised, out); + CommandSerializers.ballot.serialize(ok.maxAcceptedOrCommitted, out); + CommandSerializers.ballot.serialize(ok.acceptedOrCommitted, out); ExecuteAtSerializer.serializeNullable(ok.executeAt, out); out.writeBoolean(ok.isCoordinating); - CommandSerializers.durability.serialize(ok.durability, out, version); - KeySerializers.nullableRoute.serialize(ok.route, out, version); - KeySerializers.nullableRoutingKey.serialize(ok.homeKey, out, version); - CommandSerializers.invalidIf.serialize(ok.invalidIf, out, version); + CommandSerializers.durability.serialize(ok.durability, out); + KeySerializers.nullableRoute.serialize(ok.route, out); + KeySerializers.nullableRoutingKey.serialize(ok.homeKey, out); + CommandSerializers.invalidIf.serialize(ok.invalidIf, out); if (!(reply instanceof CheckStatusOkFull)) return; CheckStatusOkFull okFull = (CheckStatusOkFull) ok; CommandSerializers.nullablePartialTxn.serialize(okFull.partialTxn, out, version); - DepsSerializers.nullablePartialDeps.serialize(okFull.stableDeps, out, version); + DepsSerializers.nullablePartialDeps.serialize(okFull.stableDeps, out); CommandSerializers.nullableWrites.serialize(okFull.writes, out, version); } @Override - public CheckStatusReply deserialize(DataInputPlus in, int version) throws IOException + public CheckStatusReply deserialize(DataInputPlus in, Version version) throws IOException { byte kind = in.readByte(); switch (kind) @@ -202,25 +202,25 @@ public class CheckStatusSerializers return CheckStatusNack.NotOwned; case OK: case FULL: - KnownMap map = knownMap.deserialize(in, version); - SaveStatus maxKnowledgeStatus = CommandSerializers.saveStatus.deserialize(in, version); - SaveStatus maxStatus = CommandSerializers.saveStatus.deserialize(in, version); - Ballot maxPromised = CommandSerializers.ballot.deserialize(in, version); - Ballot maxAcceptedOrCommitted = CommandSerializers.ballot.deserialize(in, version); - Ballot acceptedOrCommitted = CommandSerializers.ballot.deserialize(in, version); + KnownMap map = knownMap.deserialize(in); + SaveStatus maxKnowledgeStatus = CommandSerializers.saveStatus.deserialize(in); + SaveStatus maxStatus = CommandSerializers.saveStatus.deserialize(in); + Ballot maxPromised = CommandSerializers.ballot.deserialize(in); + Ballot maxAcceptedOrCommitted = CommandSerializers.ballot.deserialize(in); + Ballot acceptedOrCommitted = CommandSerializers.ballot.deserialize(in); Timestamp executeAt = ExecuteAtSerializer.deserializeNullable(in); boolean isCoordinating = in.readBoolean(); - Durability durability = CommandSerializers.durability.deserialize(in, version); - Route route = KeySerializers.nullableRoute.deserialize(in, version); - RoutingKey homeKey = KeySerializers.nullableRoutingKey.deserialize(in, version); - Infer.InvalidIf invalidIf = CommandSerializers.invalidIf.deserialize(in, version); + Durability durability = CommandSerializers.durability.deserialize(in); + Route route = KeySerializers.nullableRoute.deserialize(in); + RoutingKey homeKey = KeySerializers.nullableRoutingKey.deserialize(in); + Infer.InvalidIf invalidIf = CommandSerializers.invalidIf.deserialize(in); if (kind == OK) return createOk(map, maxKnowledgeStatus, maxStatus, maxPromised, maxAcceptedOrCommitted, acceptedOrCommitted, executeAt, isCoordinating, durability, route, homeKey, invalidIf); PartialTxn partialTxn = CommandSerializers.nullablePartialTxn.deserialize(in, version); - PartialDeps committedDeps = DepsSerializers.nullablePartialDeps.deserialize(in, version); + PartialDeps committedDeps = DepsSerializers.nullablePartialDeps.deserialize(in); Writes writes = CommandSerializers.nullableWrites.deserialize(in, version); Result result = null; @@ -234,32 +234,32 @@ public class CheckStatusSerializers } @Override - public long serializedSize(CheckStatusReply reply, int version) + public long serializedSize(CheckStatusReply reply, Version version) { long size = TypeSizes.BYTE_SIZE; if (!reply.isOk()) return size; CheckStatusOk ok = (CheckStatusOk) reply; - size += knownMap.serializedSize(ok.map, version); - size += CommandSerializers.saveStatus.serializedSize(ok.maxKnowledgeSaveStatus, version); - size += CommandSerializers.saveStatus.serializedSize(ok.maxSaveStatus, version); - size += CommandSerializers.ballot.serializedSize(ok.maxPromised, version); - size += CommandSerializers.ballot.serializedSize(ok.maxAcceptedOrCommitted, version); - size += CommandSerializers.ballot.serializedSize(ok.acceptedOrCommitted, version); + size += knownMap.serializedSize(ok.map); + size += CommandSerializers.saveStatus.serializedSize(ok.maxKnowledgeSaveStatus); + size += CommandSerializers.saveStatus.serializedSize(ok.maxSaveStatus); + size += CommandSerializers.ballot.serializedSize(ok.maxPromised); + size += CommandSerializers.ballot.serializedSize(ok.maxAcceptedOrCommitted); + size += CommandSerializers.ballot.serializedSize(ok.acceptedOrCommitted); size += ExecuteAtSerializer.serializedNullableSize(ok.executeAt); size += TypeSizes.BOOL_SIZE; - size += CommandSerializers.durability.serializedSize(ok.durability, version); - size += KeySerializers.nullableRoute.serializedSize(ok.route, version); - size += KeySerializers.nullableRoutingKey.serializedSize(ok.homeKey, version); - size += CommandSerializers.invalidIf.serializedSize(ok.invalidIf, version); + size += CommandSerializers.durability.serializedSize(ok.durability); + size += KeySerializers.nullableRoute.serializedSize(ok.route); + size += KeySerializers.nullableRoutingKey.serializedSize(ok.homeKey); + size += CommandSerializers.invalidIf.serializedSize(ok.invalidIf); if (!(reply instanceof CheckStatusOkFull)) return size; CheckStatusOkFull okFull = (CheckStatusOkFull) ok; size += CommandSerializers.nullablePartialTxn.serializedSize(okFull.partialTxn, version); - size += DepsSerializers.nullablePartialDeps.serializedSize(okFull.stableDeps, version); + size += DepsSerializers.nullablePartialDeps.serializedSize(okFull.stableDeps); size += CommandSerializers.nullableWrites.serializedSize(okFull.writes, version); return size; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/CommandSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/CommandSerializers.java index 463ac254a5..ec3fa6e109 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/CommandSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/CommandSerializers.java @@ -49,7 +49,8 @@ import accord.primitives.Writes; import accord.utils.Invariants; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.marshal.ValueAccessor; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.IVersionedWithKeysSerializer.AbstractWithKeysSerializer; @@ -68,9 +69,9 @@ public class CommandSerializers public static final TimestampSerializer txnId = new TimestampSerializer<>(TxnId::fromBits); public static final TimestampSerializer timestamp = new TimestampSerializer<>(Timestamp::fromBits); - public static final IVersionedSerializer nullableTimestamp = NullableSerializer.wrap(timestamp); + public static final UnversionedSerializer nullableTimestamp = NullableSerializer.wrap(timestamp); public static final BallotSerializer ballot = new BallotSerializer(); // permits null - public static final IVersionedSerializer kind = EncodeAsVInt32.of(Txn.Kind.class); + public static final UnversionedSerializer kind = EncodeAsVInt32.of(Txn.Kind.class); public static final StoreParticipantsSerializer participants = new StoreParticipantsSerializer(); public static class ExecuteAtSerializer @@ -325,7 +326,7 @@ public class CommandSerializers static final int WAITSON_IS_OWNS = 0x40; @Override - public void serialize(StoreParticipants t, DataOutputPlus out, int version) throws IOException + public void serialize(StoreParticipants t, DataOutputPlus out, Version version) throws IOException { boolean hasRoute = t.route() != null; boolean hasTouchedEqualsRoute = t.route() == t.hasTouched(); @@ -342,40 +343,40 @@ public class CommandSerializers | (executesIsOwns ? EXECUTES_IS_OWNS : 0) | (waitsOnIsOwns ? WAITSON_IS_OWNS : 0) ); - if (hasRoute) KeySerializers.route.serialize(t.route(), out, version); - if (!hasTouchedEqualsRoute) KeySerializers.participants.serialize(t.hasTouched(), out, version); - if (!touchesEqualsHasTouched) KeySerializers.participants.serialize(t.touches(), out, version); - if (!ownsEqualsTouches) KeySerializers.participants.serialize(t.owns(), out, version); - if (!executesIsNull && !executesIsOwns) KeySerializers.participants.serialize(t.executes(), out, version); - if (!executesIsNull && !waitsOnIsOwns) KeySerializers.participants.serialize(t.waitsOn(), out, version); + if (hasRoute) KeySerializers.route.serialize(t.route(), out); + if (!hasTouchedEqualsRoute) KeySerializers.participants.serialize(t.hasTouched(), out); + if (!touchesEqualsHasTouched) KeySerializers.participants.serialize(t.touches(), out); + if (!ownsEqualsTouches) KeySerializers.participants.serialize(t.owns(), out); + if (!executesIsNull && !executesIsOwns) KeySerializers.participants.serialize(t.executes(), out); + if (!executesIsNull && !waitsOnIsOwns) KeySerializers.participants.serialize(t.waitsOn(), out); } - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in, Version version) throws IOException { int flags = in.readByte(); - if (0 != (flags & HAS_ROUTE)) KeySerializers.route.skip(in, version); - if (0 == (flags & HAS_TOUCHED_EQUALS_ROUTE)) KeySerializers.participants.skip(in, version); - if (0 == (flags & TOUCHES_EQUALS_HAS_TOUCHED)) KeySerializers.participants.skip(in, version); - if (0 == (flags & OWNS_EQUALS_TOUCHES)) KeySerializers.participants.skip(in, version); - if (0 == (flags & (EXECUTES_IS_OWNS | EXECUTES_IS_NULL))) KeySerializers.participants.skip(in, version); - if (0 == (flags & (WAITSON_IS_OWNS | EXECUTES_IS_NULL))) KeySerializers.participants.skip(in, version); + if (0 != (flags & HAS_ROUTE)) KeySerializers.route.skip(in); + if (0 == (flags & HAS_TOUCHED_EQUALS_ROUTE)) KeySerializers.participants.skip(in); + if (0 == (flags & TOUCHES_EQUALS_HAS_TOUCHED)) KeySerializers.participants.skip(in); + if (0 == (flags & OWNS_EQUALS_TOUCHES)) KeySerializers.participants.skip(in); + if (0 == (flags & (EXECUTES_IS_OWNS | EXECUTES_IS_NULL))) KeySerializers.participants.skip(in); + if (0 == (flags & (WAITSON_IS_OWNS | EXECUTES_IS_NULL))) KeySerializers.participants.skip(in); } @Override - public StoreParticipants deserialize(DataInputPlus in, int version) throws IOException + public StoreParticipants deserialize(DataInputPlus in, Version version) throws IOException { int flags = in.readByte(); - Route route = 0 == (flags & HAS_ROUTE) ? null : KeySerializers.route.deserialize(in, version); - Participants hasTouched = 0 != (flags & HAS_TOUCHED_EQUALS_ROUTE) ? route : KeySerializers.participants.deserialize(in, version); - Participants touches = 0 != (flags & TOUCHES_EQUALS_HAS_TOUCHED) ? hasTouched : KeySerializers.participants.deserialize(in, version); - Participants owns = 0 != (flags & OWNS_EQUALS_TOUCHES) ? touches : KeySerializers.participants.deserialize(in, version); - Participants executes = 0 != (flags & EXECUTES_IS_NULL) ? null : 0 != (flags & EXECUTES_IS_OWNS) ? owns : KeySerializers.participants.deserialize(in, version); - Participants waitsOn = 0 != (flags & EXECUTES_IS_NULL) ? null : 0 != (flags & WAITSON_IS_OWNS) ? owns : KeySerializers.participants.deserialize(in, version); + Route route = 0 == (flags & HAS_ROUTE) ? null : KeySerializers.route.deserialize(in); + Participants hasTouched = 0 != (flags & HAS_TOUCHED_EQUALS_ROUTE) ? route : KeySerializers.participants.deserialize(in); + Participants touches = 0 != (flags & TOUCHES_EQUALS_HAS_TOUCHED) ? hasTouched : KeySerializers.participants.deserialize(in); + Participants owns = 0 != (flags & OWNS_EQUALS_TOUCHES) ? touches : KeySerializers.participants.deserialize(in); + Participants executes = 0 != (flags & EXECUTES_IS_NULL) ? null : 0 != (flags & EXECUTES_IS_OWNS) ? owns : KeySerializers.participants.deserialize(in); + Participants waitsOn = 0 != (flags & EXECUTES_IS_NULL) ? null : 0 != (flags & WAITSON_IS_OWNS) ? owns : KeySerializers.participants.deserialize(in); return StoreParticipants.create(route, owns, executes, waitsOn, touches, hasTouched); } @Override - public long serializedSize(StoreParticipants t, int version) + public long serializedSize(StoreParticipants t, Version version) { boolean hasRoute = t.route() != null; boolean hasTouchedEqualsRoute = t.route() == t.hasTouched(); @@ -383,16 +384,16 @@ public class CommandSerializers boolean ownsEqualsTouches = t.owns() == t.touches(); boolean executesIsNotNullAndNotOwns = t.executes() != null && t.owns() != t.executes(); long size = 1; - if (hasRoute) size += KeySerializers.route.serializedSize(t.route(), version); - if (!hasTouchedEqualsRoute) size += KeySerializers.participants.serializedSize(t.hasTouched(), version); - if (!touchesEqualsHasTouched) size += KeySerializers.participants.serializedSize(t.touches(), version); - if (!ownsEqualsTouches) size += KeySerializers.participants.serializedSize(t.owns(), version); - if (executesIsNotNullAndNotOwns) size += KeySerializers.participants.serializedSize(t.executes(), version); + if (hasRoute) size += KeySerializers.route.serializedSize(t.route()); + if (!hasTouchedEqualsRoute) size += KeySerializers.participants.serializedSize(t.hasTouched()); + if (!touchesEqualsHasTouched) size += KeySerializers.participants.serializedSize(t.touches()); + if (!ownsEqualsTouches) size += KeySerializers.participants.serializedSize(t.owns()); + if (executesIsNotNullAndNotOwns) size += KeySerializers.participants.serializedSize(t.executes()); return size; } } - public static class TimestampSerializer implements IVersionedSerializer + public static class TimestampSerializer implements UnversionedSerializer { interface Factory { @@ -407,18 +408,11 @@ public class CommandSerializers } @Override - public void serialize(T ts, DataOutputPlus out, int version) throws IOException - { - out.writeLong(ts.msb); - out.writeLong(ts.lsb); - TopologySerializers.nodeId.serialize(ts.node, out, version); - } - public void serialize(T ts, DataOutputPlus out) throws IOException { out.writeLong(ts.msb); out.writeLong(ts.lsb); - TopologySerializers.NodeIdSerializer.serialize(ts.node, out); + TopologySerializers.nodeId.serialize(ts.node, out); } public int serialize(T ts, V dst, ValueAccessor accessor, int offset) @@ -445,18 +439,11 @@ public class CommandSerializers } @Override - public T deserialize(DataInputPlus in, int version) throws IOException - { - return factory.create(in.readLong(), - in.readLong(), - TopologySerializers.nodeId.deserialize(in, version)); - } - public T deserialize(DataInputPlus in) throws IOException { return factory.create(in.readLong(), in.readLong(), - TopologySerializers.NodeIdSerializer.deserialize(in)); + TopologySerializers.nodeId.deserialize(in)); } public T deserialize(V src, ValueAccessor accessor, int offset) @@ -480,25 +467,25 @@ public class CommandSerializers } @Override - public long serializedSize(T ts, int version) + public long serializedSize(T ts) { return serializedSize(); } public int serializedSize() { - return TypeSizes.LONG_SIZE + // ts.msb - TypeSizes.LONG_SIZE + // ts.lsb - TopologySerializers.nodeId.serializedSize(); // ts.node + return Math.toIntExact(TypeSizes.LONG_SIZE + // ts.msb + TypeSizes.LONG_SIZE + // ts.lsb + TopologySerializers.nodeId.serializedSize(null)); // ts.node } } - public static class BallotSerializer implements IVersionedSerializer + public static class BallotSerializer implements UnversionedSerializer { final TimestampSerializer wrapped = new TimestampSerializer<>(Ballot::fromBits); @Override - public void serialize(Ballot t, DataOutputPlus out, int version) throws IOException + public void serialize(Ballot t, DataOutputPlus out) throws IOException { if (t == null || t.equals(Ballot.ZERO) || t.equals(Ballot.MAX)) { @@ -507,16 +494,11 @@ public class CommandSerializers else { out.writeByte(0); - wrapped.serialize(t, out, version); + wrapped.serialize(t, out); } } @Override - public Ballot deserialize(DataInputPlus in, int version) throws IOException - { - return deserialize(in); - } - public Ballot deserialize(DataInputPlus in) throws IOException { int flags = in.readByte(); @@ -538,11 +520,6 @@ public class CommandSerializers } @Override - public long serializedSize(Ballot t, int version) - { - return serializedSize(t); - } - public long serializedSize(Ballot t) { if (t == null || t.equals(Ballot.ZERO) || t.equals(Ballot.MAX)) @@ -554,11 +531,13 @@ public class CommandSerializers public static class PartialTxnSerializer extends AbstractWithKeysSerializer implements IVersionedSerializer { - private final IVersionedSerializer readSerializer; - private final IVersionedSerializer querySerializer; - private final IVersionedSerializer updateSerializer; + private final VersionedSerializer readSerializer; + private final UnversionedSerializer querySerializer; + private final VersionedSerializer updateSerializer; - public PartialTxnSerializer(IVersionedSerializer readSerializer, IVersionedSerializer querySerializer, IVersionedSerializer updateSerializer) + public PartialTxnSerializer(VersionedSerializer readSerializer, + UnversionedSerializer querySerializer, + VersionedSerializer updateSerializer) { this.readSerializer = readSerializer; this.querySerializer = querySerializer; @@ -566,51 +545,51 @@ public class CommandSerializers } @Override - public void serialize(PartialTxn txn, DataOutputPlus out, int version) throws IOException + public void serialize(PartialTxn txn, DataOutputPlus out, Version version) throws IOException { - KeySerializers.seekables.serialize(txn.keys(), out, version); + KeySerializers.seekables.serialize(txn.keys(), out); serializeWithoutKeys(txn, out, version); } @Override - public PartialTxn deserialize(DataInputPlus in, int version) throws IOException + public PartialTxn deserialize(DataInputPlus in, Version version) throws IOException { - Seekables keys = KeySerializers.seekables.deserialize(in, version); + Seekables keys = KeySerializers.seekables.deserialize(in); return deserializeWithoutKeys(keys, in, version); } @Override - public long serializedSize(PartialTxn txn, int version) + public long serializedSize(PartialTxn txn, Version version) { - long size = KeySerializers.seekables.serializedSize(txn.keys(), version); + long size = KeySerializers.seekables.serializedSize(txn.keys()); size += serializedSizeWithoutKeys(txn, version); return size; } - private void serializeWithoutKeys(PartialTxn txn, DataOutputPlus out, int version) throws IOException + private void serializeWithoutKeys(PartialTxn txn, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.kind.serialize(txn.kind(), out, version); + CommandSerializers.kind.serialize(txn.kind(), out); readSerializer.serialize(txn.read(), out, version); - querySerializer.serialize(txn.query(), out, version); + querySerializer.serialize(txn.query(), out); out.writeBoolean(txn.update() != null); if (txn.update() != null) updateSerializer.serialize(txn.update(), out, version); } - private PartialTxn deserializeWithoutKeys(Seekables keys, DataInputPlus in, int version) throws IOException + private PartialTxn deserializeWithoutKeys(Seekables keys, DataInputPlus in, Version version) throws IOException { - Txn.Kind kind = CommandSerializers.kind.deserialize(in, version); + Txn.Kind kind = CommandSerializers.kind.deserialize(in); Read read = readSerializer.deserialize(in, version); - Query query = querySerializer.deserialize(in, version); + Query query = querySerializer.deserialize(in); Update update = in.readBoolean() ? updateSerializer.deserialize(in, version) : null; return new PartialTxn.InMemory(kind, keys, read, query, update); } - private long serializedSizeWithoutKeys(PartialTxn txn, int version) + private long serializedSizeWithoutKeys(PartialTxn txn, Version version) { - long size = CommandSerializers.kind.serializedSize(txn.kind(), version); + long size = CommandSerializers.kind.serializedSize(txn.kind()); size += readSerializer.serializedSize(txn.read(), version); - size += querySerializer.serializedSize(txn.query(), version); + size += querySerializer.serializedSize(txn.query()); size += TypeSizes.sizeof(txn.update() != null); if (txn.update() != null) size += updateSerializer.serializedSize(txn.update(), version); @@ -618,13 +597,13 @@ public class CommandSerializers } } - public static final IVersionedSerializer read; - public static final IVersionedSerializer query; - public static final IVersionedSerializer update; - public static final IVersionedSerializer write; + public static final VersionedSerializer read; + public static final UnversionedSerializer query; + public static final VersionedSerializer update; + public static final VersionedSerializer write; - public static final IVersionedSerializer partialTxn; - public static final IVersionedSerializer nullablePartialTxn; + public static final VersionedSerializer partialTxn; + public static final VersionedSerializer nullablePartialTxn; static { @@ -642,26 +621,26 @@ public class CommandSerializers @VisibleForTesting public static class QuerySerializers { - public final IVersionedSerializer read; - public final IVersionedSerializer query; - public final IVersionedSerializer update; - public final IVersionedSerializer write; + public final VersionedSerializer read; + public final UnversionedSerializer query; + public final VersionedSerializer update; + public final VersionedSerializer write; - public final IVersionedSerializer partialTxn; - public final IVersionedSerializer nullablePartialTxn; + public final VersionedSerializer partialTxn; + public final VersionedSerializer nullablePartialTxn; private QuerySerializers() { - this(new CastingSerializer<>(TxnRead.class, TxnRead.serializer), - new CastingSerializer<>(TxnQuery.class, TxnQuery.serializer), - new CastingSerializer<>(AccordUpdate.class, AccordUpdate.serializer), - new CastingSerializer<>(TxnWrite.class, TxnWrite.serializer)); + this(CastingSerializer.create(TxnRead.class, TxnRead.serializer), + CastingSerializer.create(TxnQuery.class, TxnQuery.serializer), + CastingSerializer.create(AccordUpdate.class, AccordUpdate.serializer), + CastingSerializer.create(TxnWrite.class, TxnWrite.serializer)); } - public QuerySerializers(IVersionedSerializer read, - IVersionedSerializer query, - IVersionedSerializer update, - IVersionedSerializer write) + public QuerySerializers(VersionedSerializer read, + UnversionedSerializer query, + VersionedSerializer update, + VersionedSerializer write) { this.read = read; this.query = query; @@ -673,18 +652,18 @@ public class CommandSerializers } } - public static final IVersionedSerializer saveStatus = EncodeAsVInt32.of(SaveStatus.class); - public static final IVersionedSerializer status = EncodeAsVInt32.of(Status.class); - public static final IVersionedSerializer durability = EncodeAsVInt32.of(Durability.class); + public static final UnversionedSerializer saveStatus = EncodeAsVInt32.of(SaveStatus.class); + public static final UnversionedSerializer status = EncodeAsVInt32.of(Status.class); + public static final UnversionedSerializer durability = EncodeAsVInt32.of(Durability.class); public static final IVersionedSerializer writes = new IVersionedSerializer<>() { @Override - public void serialize(Writes writes, DataOutputPlus out, int version) throws IOException + public void serialize(Writes writes, DataOutputPlus out, Version version) throws IOException { - txnId.serialize(writes.txnId, out, version); + txnId.serialize(writes.txnId, out); ExecuteAtSerializer.serialize(writes.txnId, writes.executeAt, out); - KeySerializers.seekables.serialize(writes.keys, out, version); + KeySerializers.seekables.serialize(writes.keys, out); boolean hasWrites = writes.write != null; out.writeBoolean(hasWrites); @@ -693,20 +672,20 @@ public class CommandSerializers } @Override - public Writes deserialize(DataInputPlus in, int version) throws IOException + public Writes deserialize(DataInputPlus in, Version version) throws IOException { - TxnId id = txnId.deserialize(in, version); + TxnId id = txnId.deserialize(in); return new Writes(id, ExecuteAtSerializer.deserialize(id, in), - KeySerializers.seekables.deserialize(in, version), + KeySerializers.seekables.deserialize(in), in.readBoolean() ? CommandSerializers.write.deserialize(in, version) : null); } @Override - public long serializedSize(Writes writes, int version) + public long serializedSize(Writes writes, Version version) { - long size = txnId.serializedSize(writes.txnId, version); + long size = txnId.serializedSize(writes.txnId); size += ExecuteAtSerializer.serializedSize(writes.txnId, writes.executeAt); - size += KeySerializers.seekables.serializedSize(writes.keys, version); + size += KeySerializers.seekables.serializedSize(writes.keys); boolean hasWrites = writes.write != null; size += TypeSizes.sizeof(hasWrites); if (hasWrites) @@ -715,9 +694,10 @@ public class CommandSerializers } }; - public static final IVersionedSerializer nullableWrites = NullableSerializer.wrap(writes); - public static final IVersionedSerializer knownDeps = EncodeAsVInt32.of(KnownDeps.class); - public static final IVersionedSerializer invalidIf = EncodeAsVInt32.of(Infer.InvalidIf.class); + public static final VersionedSerializer nullableWrites = NullableSerializer.wrap(writes); + public static final UnversionedSerializer knownDeps = EncodeAsVInt32.of(KnownDeps.class); + public static final UnversionedSerializer invalidIf = EncodeAsVInt32.of(Infer.InvalidIf.class); + + public static final UnversionedSerializer known = EncodeAsVInt32.withNulls(known -> known.encoded, Known::new); - public static final IVersionedSerializer known = EncodeAsVInt32.withNulls(known -> known.encoded, Known::new); } \ No newline at end of file diff --git a/src/java/org/apache/cassandra/service/accord/serializers/CommandStoreSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/CommandStoreSerializers.java index e9b8d35028..cf28b5a4dc 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/CommandStoreSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/CommandStoreSerializers.java @@ -34,7 +34,7 @@ import accord.utils.Invariants; import accord.utils.ReducingRangeMap; import accord.utils.TriFunction; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.CollectionSerializers; @@ -48,20 +48,21 @@ public class CommandStoreSerializers { private CommandStoreSerializers() {} - public static class ReducingRangeMapSerializer> implements IVersionedSerializer + public static class ReducingRangeMapSerializer> implements UnversionedSerializer { - final IVersionedSerializer valueSerializer; + final UnversionedSerializer valueSerializer; final IntFunction newValueArray; final TriFunction constructor; - public ReducingRangeMapSerializer(IVersionedSerializer valueSerializer, IntFunction newValueArray, TriFunction constructor) + public ReducingRangeMapSerializer(UnversionedSerializer valueSerializer, IntFunction newValueArray, TriFunction constructor) { this.valueSerializer = valueSerializer; this.newValueArray = newValueArray; this.constructor = constructor; } - public void serialize(R map, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(R map, DataOutputPlus out) throws IOException { out.writeBoolean(map.inclusiveEnds()); int mapSize = map.size(); @@ -69,14 +70,15 @@ public class CommandStoreSerializers for (int i=0; i 0) - KeySerializers.routingKey.serialize(map.startAt(mapSize), out, version); + KeySerializers.routingKey.serialize(map.startAt(mapSize), out); } - public R deserialize(DataInputPlus in, int version) throws IOException + @Override + public R deserialize(DataInputPlus in) throws IOException { boolean inclusiveEnds = in.readBoolean(); int mapSize = in.readUnsignedVInt32(); @@ -84,62 +86,63 @@ public class CommandStoreSerializers T[] values = newValueArray.apply(mapSize); for (int i=0; i 0) - keys[mapSize] = KeySerializers.routingKey.deserialize(in, version); + keys[mapSize] = KeySerializers.routingKey.deserialize(in); return constructor.apply(inclusiveEnds, keys, values); } - public long serializedSize(R map, int version) + @Override + public long serializedSize(R map) { long size = TypeSizes.BOOL_SIZE; int mapSize = map.size(); size += TypeSizes.sizeofUnsignedVInt(mapSize); for (int i=0; i 0) - size += KeySerializers.routingKey.serializedSize(map.startAt(mapSize), version); + size += KeySerializers.routingKey.serializedSize(map.startAt(mapSize)); return size; } } - public static IVersionedSerializer durableBefore = new ReducingRangeMapSerializer<>(NullableSerializer.wrap(new IVersionedSerializer<>() + public static UnversionedSerializer durableBefore = new ReducingRangeMapSerializer<>(NullableSerializer.wrap(new UnversionedSerializer<>() { @Override - public void serialize(DurableBefore.Entry t, DataOutputPlus out, int version) throws IOException + public void serialize(DurableBefore.Entry t, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(t.majorityBefore, out, version); - CommandSerializers.txnId.serialize(t.universalBefore, out, version); + CommandSerializers.txnId.serialize(t.majorityBefore, out); + CommandSerializers.txnId.serialize(t.universalBefore, out); } @Override - public DurableBefore.Entry deserialize(DataInputPlus in, int version) throws IOException + public DurableBefore.Entry deserialize(DataInputPlus in) throws IOException { - TxnId majorityBefore = CommandSerializers.txnId.deserialize(in, version); - TxnId universalBefore = CommandSerializers.txnId.deserialize(in, version); + TxnId majorityBefore = CommandSerializers.txnId.deserialize(in); + TxnId universalBefore = CommandSerializers.txnId.deserialize(in); return new DurableBefore.Entry(majorityBefore, universalBefore); } @Override - public long serializedSize(DurableBefore.Entry t, int version) + public long serializedSize(DurableBefore.Entry t) { - return CommandSerializers.txnId.serializedSize(t.majorityBefore, version) - + CommandSerializers.txnId.serializedSize(t.universalBefore, version); + return CommandSerializers.txnId.serializedSize(t.majorityBefore) + + CommandSerializers.txnId.serializedSize(t.universalBefore); } }), DurableBefore.Entry[]::new, DurableBefore.SerializerSupport::create); - public static final IVersionedSerializer redundantBeforeEntry = new IVersionedSerializer<>() + public static final UnversionedSerializer redundantBeforeEntry = new UnversionedSerializer<>() { @Override - public void serialize(RedundantBefore.Bounds b, DataOutputPlus out, int version) throws IOException + public void serialize(RedundantBefore.Bounds b, DataOutputPlus out) throws IOException { - KeySerializers.range.serialize(b.range, out, version); + KeySerializers.range.serialize(b.range, out); Invariants.require(b.startEpoch <= b.endEpoch); out.writeUnsignedVInt(b.startEpoch); if (b.endEpoch == Long.MAX_VALUE) out.writeUnsignedVInt(0L); @@ -148,16 +151,16 @@ public class CommandStoreSerializers out.writeUnsignedVInt32(b.bounds.length); for (TxnId bound : b.bounds) { - CommandSerializers.txnId.serialize(bound, out, version); + CommandSerializers.txnId.serialize(bound, out); } for (int status : b.statuses) out.writeShort(status); } @Override - public RedundantBefore.Bounds deserialize(DataInputPlus in, int version) throws IOException + public RedundantBefore.Bounds deserialize(DataInputPlus in) throws IOException { - Range range = KeySerializers.range.deserialize(in, version); + Range range = KeySerializers.range.deserialize(in); long startEpoch = in.readUnsignedVInt(); long endEpoch = in.readUnsignedVInt(); if (endEpoch == 0) endEpoch = Long.MAX_VALUE; @@ -176,49 +179,52 @@ public class CommandStoreSerializers } @Override - public long serializedSize(RedundantBefore.Bounds b, int version) + public long serializedSize(RedundantBefore.Bounds b) { - long size = KeySerializers.range.serializedSize(b.range, version); + long size = KeySerializers.range.serializedSize(b.range); size += TypeSizes.sizeofUnsignedVInt(b.startEpoch); size += TypeSizes.sizeofUnsignedVInt(b.endEpoch == Long.MAX_VALUE ? 0 : 1 + b.endEpoch - b.startEpoch); size += serializedNullableSize(b.staleUntilAtLeast); size += TypeSizes.sizeofUnsignedVInt(b.bounds.length); for (TxnId bound : b.bounds) { - size += CommandSerializers.txnId.serializedSize(bound, version); + size += CommandSerializers.txnId.serializedSize(bound); } size += 2L * b.statuses.length; return size; } }; - public static IVersionedSerializer redundantBefore = new ReducingRangeMapSerializer<>(NullableSerializer.wrap(redundantBeforeEntry), RedundantBefore.Bounds[]::new, RedundantBefore.SerializerSupport::create); + public static UnversionedSerializer redundantBefore = new ReducingRangeMapSerializer<>(NullableSerializer.wrap(redundantBeforeEntry), RedundantBefore.Bounds[]::new, RedundantBefore.SerializerSupport::create); - private static class TimestampToRangesSerializer implements IVersionedSerializer> + private static class TimestampToRangesSerializer implements UnversionedSerializer> { - private final IVersionedSerializer timestampSerializer; + private final UnversionedSerializer timestampSerializer; - public TimestampToRangesSerializer(IVersionedSerializer timestampSerializer) + public TimestampToRangesSerializer(UnversionedSerializer timestampSerializer) { this.timestampSerializer = timestampSerializer; } - public void serialize(NavigableMap map, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(NavigableMap map, DataOutputPlus out) throws IOException { - CollectionSerializers.serializeMap(map, out, version, timestampSerializer, KeySerializers.ranges); + CollectionSerializers.serializeMap(map, out, timestampSerializer, KeySerializers.ranges); } - public NavigableMap deserialize(DataInputPlus in, int version) throws IOException + @Override + public NavigableMap deserialize(DataInputPlus in) throws IOException { - return CollectionSerializers.deserializeMap(in, version, timestampSerializer, KeySerializers.ranges, i -> new TreeMap<>()); + return CollectionSerializers.deserializeMap(in, timestampSerializer, KeySerializers.ranges, i -> new TreeMap<>()); } - public long serializedSize(NavigableMap map, int version) + @Override + public long serializedSize(NavigableMap map) { - return CollectionSerializers.serializedMapSize(map, version, timestampSerializer, KeySerializers.ranges); + return CollectionSerializers.serializedMapSize(map, timestampSerializer, KeySerializers.ranges); } } - public static final IVersionedSerializer> bootstrapBeganAt = new TimestampToRangesSerializer<>(CommandSerializers.txnId); - public static final IVersionedSerializer> safeToRead = new TimestampToRangesSerializer<>(CommandSerializers.timestamp); + public static final UnversionedSerializer> bootstrapBeganAt = new TimestampToRangesSerializer<>(CommandSerializers.txnId); + public static final UnversionedSerializer> safeToRead = new TimestampToRangesSerializer<>(CommandSerializers.timestamp); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/CommitSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/CommitSerializers.java index 1ba1b89ffc..31d879ce7c 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/CommitSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/CommitSerializers.java @@ -30,7 +30,7 @@ import accord.primitives.Route; import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -41,79 +41,79 @@ import static org.apache.cassandra.utils.NullableSerializer.serializedNullableSi public class CommitSerializers { - public static final IVersionedSerializer kind = EncodeAsVInt32.of(Commit.Kind.class); + public static final UnversionedSerializer kind = EncodeAsVInt32.of(Commit.Kind.class); public static final CommitSerializer request = new CommitSerializer(); public static class CommitSerializer extends TxnRequestSerializer.WithUnsyncedSerializer { @Override - public void serializeBody(Commit msg, DataOutputPlus out, int version) throws IOException + public void serializeBody(Commit msg, DataOutputPlus out, Version version) throws IOException { - kind.serialize(msg.kind, out, version); - CommandSerializers.ballot.serialize(msg.ballot, out, version); + kind.serialize(msg.kind, out); + CommandSerializers.ballot.serialize(msg.ballot, out); ExecuteAtSerializer.serialize(msg.txnId, msg.executeAt, out); CommandSerializers.nullablePartialTxn.serialize(msg.partialTxn, out, version); if (msg.kind.withDeps == Commit.WithDeps.HasDeps) - DepsSerializers.partialDeps.serialize(msg.partialDeps, out, version); - serializeNullable(msg.route, out, version, KeySerializers.fullRoute); + DepsSerializers.partialDeps.serialize(msg.partialDeps, out); + serializeNullable(msg.route, out, KeySerializers.fullRoute); } @Override - public Commit deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public Commit deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { - Commit.Kind kind = CommitSerializers.kind.deserialize(in, version); - Ballot ballot = CommandSerializers.ballot.deserialize(in, version); + Commit.Kind kind = CommitSerializers.kind.deserialize(in); + Ballot ballot = CommandSerializers.ballot.deserialize(in); Timestamp executeAt = ExecuteAtSerializer.deserialize(txnId, in); PartialTxn partialTxn = CommandSerializers.nullablePartialTxn.deserialize(in, version); PartialDeps partialDeps = null; if (kind.withDeps == Commit.WithDeps.HasDeps) - partialDeps = DepsSerializers.partialDeps.deserialize(in, version); - FullRoute route = deserializeNullable(in, version, KeySerializers.fullRoute); + partialDeps = DepsSerializers.partialDeps.deserialize(in); + FullRoute route = deserializeNullable(in, KeySerializers.fullRoute); return Commit.SerializerSupport.create(txnId, scope, waitForEpoch, minEpoch, kind, ballot, executeAt, partialTxn, partialDeps, route); } @Override - public long serializedBodySize(Commit msg, int version) + public long serializedBodySize(Commit msg, Version version) { - long size = kind.serializedSize(msg.kind, version) - + CommandSerializers.ballot.serializedSize(msg.ballot, version) + long size = kind.serializedSize(msg.kind) + + CommandSerializers.ballot.serializedSize(msg.ballot) + ExecuteAtSerializer.serializedSize(msg.txnId, msg.executeAt) + CommandSerializers.nullablePartialTxn.serializedSize(msg.partialTxn, version); if (msg.kind.withDeps == Commit.WithDeps.HasDeps) - size += DepsSerializers.partialDeps.serializedSize(msg.partialDeps, version); + size += DepsSerializers.partialDeps.serializedSize(msg.partialDeps); - size += serializedNullableSize(msg.route, version, KeySerializers.fullRoute); + size += serializedNullableSize(msg.route, KeySerializers.fullRoute); return size; } } - public static final IVersionedSerializer invalidate = new IVersionedSerializer<>() + public static final UnversionedSerializer invalidate = new UnversionedSerializer<>() { @Override - public void serialize(Commit.Invalidate invalidate, DataOutputPlus out, int version) throws IOException + public void serialize(Commit.Invalidate invalidate, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(invalidate.txnId, out, version); - KeySerializers.participants.serialize(invalidate.scope, out, version); + CommandSerializers.txnId.serialize(invalidate.txnId, out); + KeySerializers.participants.serialize(invalidate.scope, out); out.writeUnsignedVInt(invalidate.waitForEpoch); out.writeUnsignedVInt(invalidate.invalidateUntilEpoch - invalidate.waitForEpoch); } @Override - public Commit.Invalidate deserialize(DataInputPlus in, int version) throws IOException + public Commit.Invalidate deserialize(DataInputPlus in) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long waitForEpoch = in.readUnsignedVInt(); long invalidateUntilEpoch = in.readUnsignedVInt() + waitForEpoch; return Commit.Invalidate.SerializerSupport.create(txnId, scope, waitForEpoch, invalidateUntilEpoch); } @Override - public long serializedSize(Commit.Invalidate invalidate, int version) + public long serializedSize(Commit.Invalidate invalidate) { - return CommandSerializers.txnId.serializedSize(invalidate.txnId, version) - + KeySerializers.participants.serializedSize(invalidate.scope, version) + return CommandSerializers.txnId.serializedSize(invalidate.txnId) + + KeySerializers.participants.serializedSize(invalidate.scope) + TypeSizes.sizeofUnsignedVInt(invalidate.waitForEpoch) + TypeSizes.sizeofUnsignedVInt(invalidate.invalidateUntilEpoch - invalidate.waitForEpoch); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/DepsSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/DepsSerializers.java index f2c4c6ee47..daf6f923d2 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/DepsSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/DepsSerializers.java @@ -30,7 +30,7 @@ import accord.primitives.Range; import accord.primitives.RangeDeps; import accord.primitives.RoutingKeys; import accord.primitives.TxnId; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.TokenRange; @@ -44,16 +44,16 @@ import static org.apache.cassandra.db.TypeSizes.sizeofUnsignedVInt; public class DepsSerializers { - public static final IVersionedSerializer tokenRange; + public static final UnversionedSerializer tokenRange; public static final DepsSerializer deps; - public static final IVersionedSerializer nullableDeps; + public static final UnversionedSerializer nullableDeps; public static final DepsSerializer partialDeps; - public static final IVersionedSerializer nullablePartialDeps; + public static final UnversionedSerializer nullablePartialDeps; static { // We use a separate class for initialization to make it easier for BurnTest to plug its own serializers. - Impl serializers = new Impl((IVersionedSerializer) (IVersionedSerializer) TokenRange.serializer); + Impl serializers = new Impl((UnversionedSerializer) (UnversionedSerializer) TokenRange.serializer); tokenRange = serializers.tokenRange; deps = serializers.deps; nullableDeps = serializers.nullableDeps; @@ -61,26 +61,26 @@ public class DepsSerializers nullablePartialDeps = serializers.nullablePartialDeps; } - public static abstract class DepsSerializer implements IVersionedSerializer + public static abstract class DepsSerializer implements UnversionedSerializer { - protected IVersionedSerializer tokenRange; - public DepsSerializer(IVersionedSerializer tokenRange) + protected UnversionedSerializer tokenRange; + public DepsSerializer(UnversionedSerializer tokenRange) { this.tokenRange = tokenRange; } - abstract D deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in, int version) throws IOException; + abstract D deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in) throws IOException; @Override - public void serialize(D deps, DataOutputPlus out, int version) throws IOException + public void serialize(D deps, DataOutputPlus out) throws IOException { { KeyDeps keyDeps = deps.keyDeps; - KeySerializers.routingKeys.serialize(keyDeps.keys(), out, version); + KeySerializers.routingKeys.serialize(keyDeps.keys(), out); int txnIdCount = keyDeps.txnIdCount(); out.writeUnsignedVInt32(txnIdCount); for (int i = 0; i < txnIdCount; i++) - CommandSerializers.txnId.serialize(keyDeps.txnId(i), out, version); + CommandSerializers.txnId.serialize(keyDeps.txnId(i), out); int keysToTxnIdsCount = keysToTxnIdsCount(keyDeps); out.writeUnsignedVInt32(keysToTxnIdsCount); @@ -92,12 +92,12 @@ public class DepsSerializers int rangeCount = rangeDeps.rangeCount(); out.writeUnsignedVInt32(rangeCount); for (int i = 0; i < rangeCount; i++) - tokenRange.serialize(rangeDeps.range(i), out, version); + tokenRange.serialize(rangeDeps.range(i), out); int txnIdCount = rangeDeps.txnIdCount(); out.writeUnsignedVInt32(txnIdCount); for (int i = 0; i < txnIdCount; i++) - CommandSerializers.txnId.serialize(rangeDeps.txnId(i), out, version); + CommandSerializers.txnId.serialize(rangeDeps.txnId(i), out); int rangesToTxnIdsCount = rangesToTxnIdsCount(rangeDeps); out.writeUnsignedVInt32(rangesToTxnIdsCount); @@ -107,15 +107,15 @@ public class DepsSerializers } @Override - public D deserialize(DataInputPlus in, int version) throws IOException + public D deserialize(DataInputPlus in) throws IOException { KeyDeps keyDeps; { - RoutingKeys keys = KeySerializers.routingKeys.deserialize(in, version); + RoutingKeys keys = KeySerializers.routingKeys.deserialize(in); int txnIdCount = in.readUnsignedVInt32(); TxnId[] txnIds = new TxnId[txnIdCount]; for (int i = 0; i < txnIdCount; i++) - txnIds[i] = CommandSerializers.txnId.deserialize(in, version); + txnIds[i] = CommandSerializers.txnId.deserialize(in); int keysToTxnIdsCount = in.readUnsignedVInt32(); int[] keysToTxnIds = new int[keysToTxnIdsCount]; @@ -130,12 +130,12 @@ public class DepsSerializers int rangeCount = Ints.checkedCast(in.readUnsignedVInt32()); Range[] ranges = new Range[rangeCount]; for (int i = 0; i < rangeCount; i++) - ranges[i] = tokenRange.deserialize(in, version); + ranges[i] = tokenRange.deserialize(in); int txnIdCount = in.readUnsignedVInt32(); TxnId[] txnIds = new TxnId[txnIdCount]; for (int i = 0; i < txnIdCount; i++) - txnIds[i] = CommandSerializers.txnId.deserialize(in, version); + txnIds[i] = CommandSerializers.txnId.deserialize(in); int rangesToTxnIdsCount = in.readUnsignedVInt32(); int[] rangesToTxnIds = new int[rangesToTxnIdsCount]; @@ -144,20 +144,20 @@ public class DepsSerializers rangeDeps = RangeDeps.SerializerSupport.create(ranges, txnIds, rangesToTxnIds); } - return deserialize(keyDeps, rangeDeps, in, version); + return deserialize(keyDeps, rangeDeps, in); } @Override - public long serializedSize(D deps, int version) + public long serializedSize(D deps) { long size; { KeyDeps keyDeps = deps.keyDeps; - size = KeySerializers.routingKeys.serializedSize(deps.keyDeps.keys(), version); + size = KeySerializers.routingKeys.serializedSize(deps.keyDeps.keys()); int txnIdCount = keyDeps.txnIdCount(); size += sizeofUnsignedVInt(txnIdCount); for (int i = 0; i < txnIdCount; i++) - size += CommandSerializers.txnId.serializedSize(keyDeps.txnId(i), version); + size += CommandSerializers.txnId.serializedSize(keyDeps.txnId(i)); int keysToTxnIdsCount = keysToTxnIdsCount(keyDeps); size += sizeofUnsignedVInt(keysToTxnIdsCount); @@ -170,12 +170,12 @@ public class DepsSerializers int rangeCount = rangeDeps.rangeCount(); size += sizeofUnsignedVInt(rangeCount); for (int i = 0; i < rangeCount; ++i) - size += tokenRange.serializedSize(rangeDeps.range(i), version); + size += tokenRange.serializedSize(rangeDeps.range(i)); int txnIdCount = rangeDeps.txnIdCount(); size += sizeofUnsignedVInt(txnIdCount); for (int i = 0; i < txnIdCount; i++) - size += CommandSerializers.txnId.serializedSize(rangeDeps.txnId(i), version); + size += CommandSerializers.txnId.serializedSize(rangeDeps.txnId(i)); int rangesToTxnIdsCount = rangesToTxnIdsCount(rangeDeps); size += sizeofUnsignedVInt(rangesToTxnIdsCount); @@ -189,19 +189,19 @@ public class DepsSerializers @VisibleForTesting public static class Impl { - final IVersionedSerializer tokenRange; + final UnversionedSerializer tokenRange; final DepsSerializer deps; - final IVersionedSerializer nullableDeps; + final UnversionedSerializer nullableDeps; final DepsSerializer partialDeps; - final IVersionedSerializer nullablePartialDeps; + final UnversionedSerializer nullablePartialDeps; - public Impl(IVersionedSerializer tokenRange) + public Impl(UnversionedSerializer tokenRange) { this.tokenRange = tokenRange; this.deps = new DepsSerializer<>(tokenRange) { @Override - Deps deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in, int version) + Deps deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in) { return new Deps(keyDeps, rangeDeps); } @@ -210,24 +210,24 @@ public class DepsSerializers this.partialDeps = new DepsSerializer<>(tokenRange) { @Override - PartialDeps deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in, int version) throws IOException + PartialDeps deserialize(KeyDeps keyDeps, RangeDeps rangeDeps, DataInputPlus in) throws IOException { - Participants covering = KeySerializers.participants.deserialize(in, version); + Participants covering = KeySerializers.participants.deserialize(in); return new PartialDeps(covering, keyDeps, rangeDeps); } @Override - public void serialize(PartialDeps partialDeps, DataOutputPlus out, int version) throws IOException + public void serialize(PartialDeps partialDeps, DataOutputPlus out) throws IOException { - super.serialize(partialDeps, out, version); - KeySerializers.participants.serialize(partialDeps.covering, out, version); + super.serialize(partialDeps, out); + KeySerializers.participants.serialize(partialDeps.covering, out); } @Override - public long serializedSize(PartialDeps partialDeps, int version) + public long serializedSize(PartialDeps partialDeps) { - return super.serializedSize(partialDeps, version) - + KeySerializers.participants.serializedSize(partialDeps.covering, version); + return super.serializedSize(partialDeps) + + KeySerializers.participants.serializedSize(partialDeps.covering); } }; diff --git a/src/java/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32.java b/src/java/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32.java index c9ed942279..81cae8885f 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32.java @@ -26,13 +26,18 @@ import javax.annotation.Nullable; import com.google.common.primitives.Ints; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.vint.VIntCoding; -public abstract class EncodeAsVInt32 implements IVersionedSerializer +public abstract class EncodeAsVInt32 implements UnversionedSerializer { + /** + * Creates a serializer that uses vint to store the encoded value. + * + * Negative ints cause undefined behavior and are unsafe to use; this logic is only safe for 0 and posotive values + */ public static EncodeAsVInt32 withNulls(ToIntFunction encode, IntFunction decode) { return new WithNulls<>(encode, decode); @@ -102,20 +107,20 @@ public abstract class EncodeAsVInt32 implements IVersionedSerializer } @Override - public void serialize(T t, DataOutputPlus out, int version) throws IOException + public void serialize(T t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(encode(t)); } @Override - public T deserialize(DataInputPlus in, int version) throws IOException + public T deserialize(DataInputPlus in) throws IOException { // we read a long to ensure we are correct even if the underlying conversion may return -1 return decode(in.readUnsignedVInt()); } @Override - public long serializedSize(T t, int version) + public long serializedSize(T t) { return VIntCoding.computeUnsignedVIntSize(encode(t)); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/EnumSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/EnumSerializer.java index 9a81f96cab..b8c77d3ecf 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/EnumSerializer.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/EnumSerializer.java @@ -19,16 +19,14 @@ package org.apache.cassandra.service.accord.serializers; import java.io.IOException; -import java.nio.ByteBuffer; import accord.messages.SimpleReply; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; -import org.apache.cassandra.utils.vint.VIntCoding; -public class EnumSerializer> implements IVersionedSerializer +public class EnumSerializer> implements UnversionedSerializer { public static final EnumSerializer simpleReply = new EnumSerializer<>(SimpleReply.class); @@ -45,28 +43,19 @@ public class EnumSerializer> implements IVersionedSerializer request = new IVersionedSerializer<>() { @Override - public void serialize(FetchRequest request, DataOutputPlus out, int version) throws IOException + public void serialize(FetchRequest request, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt(request.executeAtEpoch); - CommandSerializers.txnId.serialize(request.txnId, out, version); - KeySerializers.ranges.serialize((Ranges) request.scope, out, version); - DepsSerializers.partialDeps.serialize(request.partialDeps, out, version); + CommandSerializers.txnId.serialize(request.txnId, out); + KeySerializers.ranges.serialize((Ranges) request.scope, out); + DepsSerializers.partialDeps.serialize(request.partialDeps, out); StreamingTxn.serializer.serialize(request.read, out, version); } @Override - public FetchRequest deserialize(DataInputPlus in, int version) throws IOException + public FetchRequest deserialize(DataInputPlus in, Version version) throws IOException { return new AccordFetchRequest(in.readUnsignedVInt(), - CommandSerializers.txnId.deserialize(in, version), - KeySerializers.ranges.deserialize(in, version), - DepsSerializers.partialDeps.deserialize(in, version), + CommandSerializers.txnId.deserialize(in), + KeySerializers.ranges.deserialize(in), + DepsSerializers.partialDeps.deserialize(in), StreamingTxn.serializer.deserialize(in, version)); } @Override - public long serializedSize(FetchRequest request, int version) + public long serializedSize(FetchRequest request, Version version) { return TypeSizes.sizeofUnsignedVInt(request.executeAtEpoch) - + CommandSerializers.txnId.serializedSize(request.txnId, version) - + KeySerializers.ranges.serializedSize((Ranges) request.scope, version) - + DepsSerializers.partialDeps.serializedSize(request.partialDeps, version) + + CommandSerializers.txnId.serializedSize(request.txnId) + + KeySerializers.ranges.serializedSize((Ranges) request.scope) + + DepsSerializers.partialDeps.serializedSize(request.partialDeps) + StreamingTxn.serializer.serializedSize(request.read, version); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { final CommitOrReadNack[] nacks = CommitOrReadNack.values(); - final IVersionedSerializer streamDataSerializer = new CastingSerializer<>(StreamData.class, StreamData.serializer); + final UnversionedSerializer streamDataSerializer = CastingSerializer.create(StreamData.class, StreamData.serializer); @Override - public void serialize(ReadReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(ReadReply reply, DataOutputPlus out) throws IOException { if (!reply.isOk()) { @@ -90,34 +90,34 @@ public class FetchSerializers out.writeByte(0); FetchResponse response = (FetchResponse) reply; - serializeNullable(response.unavailable, out, version, KeySerializers.ranges); - serializeNullable(response.data, out, version, streamDataSerializer); - CommandSerializers.nullableTimestamp.serialize(response.safeToReadAfter, out, version); + serializeNullable(response.unavailable, out, KeySerializers.ranges); + serializeNullable(response.data, out, streamDataSerializer); + CommandSerializers.nullableTimestamp.serialize(response.safeToReadAfter, out); } @Override - public ReadReply deserialize(DataInputPlus in, int version) throws IOException + public ReadReply deserialize(DataInputPlus in) throws IOException { int id = in.readByte(); if (id != 0) return nacks[id - 1]; - return new FetchResponse(deserializeNullable(in, version, KeySerializers.ranges), - deserializeNullable(in, version, streamDataSerializer), - CommandSerializers.nullableTimestamp.deserialize(in, version)); + return new FetchResponse(deserializeNullable(in, KeySerializers.ranges), + deserializeNullable(in, streamDataSerializer), + CommandSerializers.nullableTimestamp.deserialize(in)); } @Override - public long serializedSize(ReadReply reply, int version) + public long serializedSize(ReadReply reply) { if (!reply.isOk()) return TypeSizes.BYTE_SIZE; FetchResponse response = (FetchResponse) reply; return TypeSizes.BYTE_SIZE - + serializedNullableSize(response.unavailable, version, KeySerializers.ranges) - + serializedNullableSize(response.data, version, streamDataSerializer) - + CommandSerializers.nullableTimestamp.serializedSize(response.safeToReadAfter, version); + + serializedNullableSize(response.unavailable, KeySerializers.ranges) + + serializedNullableSize(response.data, streamDataSerializer) + + CommandSerializers.nullableTimestamp.serializedSize(response.safeToReadAfter); } }; diff --git a/src/java/org/apache/cassandra/service/accord/serializers/GetDurableBeforeSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/GetDurableBeforeSerializers.java index f79039ae81..c314e51a79 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/GetDurableBeforeSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/GetDurableBeforeSerializers.java @@ -21,50 +21,50 @@ import java.io.IOException; import accord.messages.GetDurableBefore; import accord.messages.GetDurableBefore.DurableBeforeReply; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; public class GetDurableBeforeSerializers { - public static final IVersionedSerializer request = new IVersionedSerializer() + public static final UnversionedSerializer request = new UnversionedSerializer() { @Override - public void serialize(GetDurableBefore msg, DataOutputPlus out, int version) throws IOException + public void serialize(GetDurableBefore msg, DataOutputPlus out) throws IOException { } @Override - public GetDurableBefore deserialize(DataInputPlus in, int version) throws IOException + public GetDurableBefore deserialize(DataInputPlus in) throws IOException { return new GetDurableBefore(); } @Override - public long serializedSize(GetDurableBefore msg, int version) + public long serializedSize(GetDurableBefore msg) { return 0; } }; - public static final IVersionedSerializer reply = new IVersionedSerializer() + public static final UnversionedSerializer reply = new UnversionedSerializer() { @Override - public void serialize(DurableBeforeReply msg, DataOutputPlus out, int version) throws IOException + public void serialize(DurableBeforeReply msg, DataOutputPlus out) throws IOException { - CommandStoreSerializers.durableBefore.serialize(msg.durableBeforeMap, out, version); + CommandStoreSerializers.durableBefore.serialize(msg.durableBeforeMap, out); } @Override - public DurableBeforeReply deserialize(DataInputPlus in, int version) throws IOException + public DurableBeforeReply deserialize(DataInputPlus in) throws IOException { - return new DurableBeforeReply(CommandStoreSerializers.durableBefore.deserialize(in, version)); + return new DurableBeforeReply(CommandStoreSerializers.durableBefore.deserialize(in)); } @Override - public long serializedSize(DurableBeforeReply msg, int version) + public long serializedSize(DurableBeforeReply msg) { - return CommandStoreSerializers.durableBefore.serializedSize(msg.durableBeforeMap, version); + return CommandStoreSerializers.durableBefore.serializedSize(msg.durableBeforeMap); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/GetEphmrlReadDepsSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/GetEphmrlReadDepsSerializers.java index 56f97b71ed..9f90274a94 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/GetEphmrlReadDepsSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/GetEphmrlReadDepsSerializers.java @@ -27,7 +27,7 @@ import accord.primitives.Deps; import accord.primitives.Route; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -36,48 +36,48 @@ public class GetEphmrlReadDepsSerializers public static final IVersionedSerializer request = new TxnRequestSerializer.WithUnsyncedSerializer() { @Override - public void serializeBody(GetEphemeralReadDeps msg, DataOutputPlus out, int version) throws IOException + public void serializeBody(GetEphemeralReadDeps msg, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt(msg.executionEpoch); } @Override - public GetEphemeralReadDeps deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public GetEphemeralReadDeps deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { long executionEpoch = in.readUnsignedVInt(); return GetEphemeralReadDeps.SerializationSupport.create(txnId, scope, waitForEpoch, minEpoch, executionEpoch); } @Override - public long serializedBodySize(GetEphemeralReadDeps msg, int version) + public long serializedBodySize(GetEphemeralReadDeps msg, Version version) { return TypeSizes.sizeofUnsignedVInt(msg.executionEpoch); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer() + public static final UnversionedSerializer reply = new UnversionedSerializer() { @Override - public void serialize(GetEphemeralReadDepsOk reply, DataOutputPlus out, int version) throws IOException + public void serialize(GetEphemeralReadDepsOk reply, DataOutputPlus out) throws IOException { - DepsSerializers.deps.serialize(reply.deps, out, version); + DepsSerializers.deps.serialize(reply.deps, out); out.writeUnsignedVInt(reply.latestEpoch); out.writeUnsignedVInt32(reply.flags.bits()); } @Override - public GetEphemeralReadDepsOk deserialize(DataInputPlus in, int version) throws IOException + public GetEphemeralReadDepsOk deserialize(DataInputPlus in) throws IOException { - Deps deps = DepsSerializers.deps.deserialize(in, version); + Deps deps = DepsSerializers.deps.deserialize(in); long latestEpoch = in.readUnsignedVInt(); ExecuteFlags flags = ExecuteFlags.get(in.readUnsignedVInt32()); return new GetEphemeralReadDepsOk(deps, latestEpoch, flags); } @Override - public long serializedSize(GetEphemeralReadDepsOk reply, int version) + public long serializedSize(GetEphemeralReadDepsOk reply) { - return DepsSerializers.deps.serializedSize(reply.deps, version) + return DepsSerializers.deps.serializedSize(reply.deps) + TypeSizes.sizeofUnsignedVInt(reply.latestEpoch) + TypeSizes.sizeofUnsignedVInt(reply.flags.bits()); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/GetMaxConflictSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/GetMaxConflictSerializers.java index 5be2af043a..eed742e247 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/GetMaxConflictSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/GetMaxConflictSerializers.java @@ -25,27 +25,27 @@ import accord.messages.GetMaxConflict.GetMaxConflictOk; import accord.primitives.Route; import accord.primitives.Timestamp; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; public class GetMaxConflictSerializers { - public static final IVersionedSerializer request = new IVersionedSerializer<>() + public static final UnversionedSerializer request = new UnversionedSerializer<>() { @Override - public void serialize(GetMaxConflict msg, DataOutputPlus out, int version) throws IOException + public void serialize(GetMaxConflict msg, DataOutputPlus out) throws IOException { - KeySerializers.route.serialize(msg.scope, out, version); + KeySerializers.route.serialize(msg.scope, out); out.writeUnsignedVInt(msg.waitForEpoch); out.writeUnsignedVInt(msg.minEpoch); out.writeUnsignedVInt(msg.executionEpoch); } @Override - public GetMaxConflict deserialize(DataInputPlus in, int version) throws IOException + public GetMaxConflict deserialize(DataInputPlus in) throws IOException { - Route scope = KeySerializers.route.deserialize(in, version); + Route scope = KeySerializers.route.deserialize(in); long waitForEpoch = in.readUnsignedVInt(); long minEpoch = in.readUnsignedVInt(); long executionEpoch = in.readUnsignedVInt(); @@ -53,36 +53,36 @@ public class GetMaxConflictSerializers } @Override - public long serializedSize(GetMaxConflict msg, int version) + public long serializedSize(GetMaxConflict msg) { - return KeySerializers.route.serializedSize(msg.scope(), version) + return KeySerializers.route.serializedSize(msg.scope()) + TypeSizes.sizeofUnsignedVInt(msg.waitForEpoch) + TypeSizes.sizeofUnsignedVInt(msg.minEpoch) + TypeSizes.sizeofUnsignedVInt(msg.executionEpoch); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { @Override - public void serialize(GetMaxConflictOk reply, DataOutputPlus out, int version) throws IOException + public void serialize(GetMaxConflictOk reply, DataOutputPlus out) throws IOException { - CommandSerializers.timestamp.serialize(reply.maxConflict, out, version); + CommandSerializers.timestamp.serialize(reply.maxConflict, out); out.writeUnsignedVInt(reply.latestEpoch); } @Override - public GetMaxConflictOk deserialize(DataInputPlus in, int version) throws IOException + public GetMaxConflictOk deserialize(DataInputPlus in) throws IOException { - Timestamp maxConflict = CommandSerializers.timestamp.deserialize(in, version); + Timestamp maxConflict = CommandSerializers.timestamp.deserialize(in); long latestEpoch = in.readUnsignedVInt(); return new GetMaxConflictOk(maxConflict, latestEpoch); } @Override - public long serializedSize(GetMaxConflictOk reply, int version) + public long serializedSize(GetMaxConflictOk reply) { - return CommandSerializers.timestamp.serializedSize(reply.maxConflict, version) + return CommandSerializers.timestamp.serializedSize(reply.maxConflict) + TypeSizes.sizeofUnsignedVInt(reply.latestEpoch); } }; diff --git a/src/java/org/apache/cassandra/service/accord/serializers/IVersionedSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/IVersionedSerializer.java new file mode 100644 index 0000000000..58f775e636 --- /dev/null +++ b/src/java/org/apache/cassandra/service/accord/serializers/IVersionedSerializer.java @@ -0,0 +1,77 @@ +/* + * 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.service.accord.serializers; + +import java.io.IOException; + +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputPlus; + +public interface IVersionedSerializer extends VersionedSerializer +{ + static IVersionedSerializer fromMessaging(org.apache.cassandra.io.IVersionedSerializer delegate) + { + return new IVersionedSerializer() + { + @Override + public void serialize(T t, DataOutputPlus out, Version version) throws IOException + { + delegate.serialize(t, out, version.messageVersion()); + } + + @Override + public T deserialize(DataInputPlus in, Version version) throws IOException + { + return delegate.deserialize(in, version.messageVersion()); + } + + @Override + public long serializedSize(T t, Version version) + { + return delegate.serializedSize(t, version.messageVersion()); + } + }; + } + + static IVersionedSerializer fromSerializer(UnversionedSerializer delegate) + { + return new IVersionedSerializer() + { + @Override + public void serialize(T t, DataOutputPlus out, Version version) throws IOException + { + delegate.serialize(t, out); + } + + @Override + public T deserialize(DataInputPlus in, Version version) throws IOException + { + return delegate.deserialize(in); + } + + @Override + public long serializedSize(T t, Version version) + { + return delegate.serializedSize(t); + } + }; + } +} diff --git a/src/java/org/apache/cassandra/service/accord/serializers/IVersionedWithKeysSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/IVersionedWithKeysSerializer.java index da0d0b0077..61f7a02dc9 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/IVersionedWithKeysSerializer.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/IVersionedWithKeysSerializer.java @@ -32,7 +32,6 @@ import accord.primitives.RoutingKeys; import accord.primitives.Unseekables; import net.nicoulaj.compilecommand.annotations.DontInline; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -51,7 +50,7 @@ public interface IVersionedWithKeysSerializer, T> extends * @param version protocol version * @throws IOException if serialization fails */ - void serialize(K keys, T t, DataOutputPlus out, int version) throws IOException; + void serialize(K keys, T t, DataOutputPlus out, Version version) throws IOException; /** * Deserialize into the specified DataInputStream instance. @@ -60,7 +59,7 @@ public interface IVersionedWithKeysSerializer, T> extends * @return the type that was deserialized * @throws IOException if deserialization fails */ - T deserialize(K keys, DataInputPlus in, int version) throws IOException; + T deserialize(K keys, DataInputPlus in, Version version) throws IOException; /** * Calculate serialized size of object without actually serializing. @@ -68,7 +67,7 @@ public interface IVersionedWithKeysSerializer, T> extends * @param version protocol version * @return serialized size of object t */ - long serializedSize(K keys, T t, int version); + long serializedSize(K keys, T t, Version version); final class NullableWithKeysSerializer, T> implements IVersionedWithKeysSerializer { @@ -79,41 +78,41 @@ public interface IVersionedWithKeysSerializer, T> extends } @Override - public void serialize(T t, DataOutputPlus out, int version) throws IOException + public void serialize(T t, DataOutputPlus out, Version version) throws IOException { out.writeByte(t == null ? 0 : 1); if (t != null) wrapped.serialize(t, out, version); } @Override - public T deserialize(DataInputPlus in, int version) throws IOException + public T deserialize(DataInputPlus in, Version version) throws IOException { if (in.readByte() == 0) return null; return wrapped.deserialize(in, version); } @Override - public long serializedSize(T t, int version) + public long serializedSize(T t, Version version) { return t == null ? 1 : 1 + wrapped.serializedSize(t, version); } @Override - public void serialize(K keys, T t, DataOutputPlus out, int version) throws IOException + public void serialize(K keys, T t, DataOutputPlus out, Version version) throws IOException { out.writeByte(t == null ? 0 : 1); if (t != null) wrapped.serialize(keys, t, out, version); } @Override - public T deserialize(K keys, DataInputPlus in, int version) throws IOException + public T deserialize(K keys, DataInputPlus in, Version version) throws IOException { if (in.readByte() == 0) return null; return wrapped.deserialize(keys, in, version); } @Override - public long serializedSize(K keys, T t, int version) + public long serializedSize(K keys, T t, Version version) { return t == null ? 1 : 1 + wrapped.serializedSize(keys, t, version); } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/InformDurableSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/InformDurableSerializers.java index 43b693c89a..c800974e88 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/InformDurableSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/InformDurableSerializers.java @@ -26,7 +26,6 @@ import accord.primitives.Status; import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -35,31 +34,31 @@ public class InformDurableSerializers public static final IVersionedSerializer request = new TxnRequestSerializer() { @Override - public void serializeBody(InformDurable msg, DataOutputPlus out, int version) throws IOException + public void serializeBody(InformDurable msg, DataOutputPlus out, Version version) throws IOException { out.writeVInt(msg.minEpoch - msg.waitForEpoch); out.writeVInt(msg.maxEpoch - msg.waitForEpoch); - CommandSerializers.nullableTimestamp.serialize(msg.executeAt, out, version); - CommandSerializers.durability.serialize(msg.durability, out, version); + CommandSerializers.nullableTimestamp.serialize(msg.executeAt, out); + CommandSerializers.durability.serialize(msg.durability, out); } @Override - public InformDurable deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch) throws IOException + public InformDurable deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch) throws IOException { long minEpoch = waitForEpoch + in.readVInt(); long maxEpoch = waitForEpoch + in.readVInt(); - Timestamp executeAt = CommandSerializers.nullableTimestamp.deserialize(in, version); - Status.Durability durability = CommandSerializers.durability.deserialize(in, version); + Timestamp executeAt = CommandSerializers.nullableTimestamp.deserialize(in); + Status.Durability durability = CommandSerializers.durability.deserialize(in); return InformDurable.SerializationSupport.create(txnId, scope, executeAt, minEpoch, waitForEpoch, maxEpoch, durability); } @Override - public long serializedBodySize(InformDurable msg, int version) + public long serializedBodySize(InformDurable msg, Version version) { return TypeSizes.sizeofVInt(msg.minEpoch - msg.waitForEpoch) + TypeSizes.sizeofVInt(msg.maxEpoch - msg.waitForEpoch) - + CommandSerializers.nullableTimestamp.serializedSize(msg.executeAt, version) - + CommandSerializers.durability.serializedSize(msg.durability, version); + + CommandSerializers.nullableTimestamp.serializedSize(msg.executeAt) + + CommandSerializers.durability.serializedSize(msg.durability); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/KeySerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/KeySerializers.java index 5fca029eba..b8c3ceefd2 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/KeySerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/KeySerializers.java @@ -54,7 +54,7 @@ import accord.primitives.Unseekables; import accord.primitives.Unseekables.UnseekablesKind; import accord.utils.Invariants; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.TokenRange; @@ -69,30 +69,30 @@ import static accord.utils.ArrayBuffers.cachedInts; public class KeySerializers { public static final AccordKeySerializer key; - public static final IVersionedSerializer routingKey; + public static final UnversionedSerializer routingKey; - public static final IVersionedSerializer nullableRoutingKey; + public static final UnversionedSerializer nullableRoutingKey; public static final AbstractSearchableKeysSerializer routingKeys; - public static final IVersionedSerializer keys; + public static final UnversionedSerializer keys; public static final AbstractSearchableKeysSerializer partialKeyRoute; public static final AbstractSearchableKeysSerializer fullKeyRoute; - public static final IVersionedSerializer range; + public static final UnversionedSerializer range; public static final AbstractRangesSerializer ranges; public static final AbstractRangesSerializer partialRangeRoute; public static final AbstractRangesSerializer fullRangeRoute; public static final AbstractRoutablesSerializer> route; - public static final IVersionedSerializer> nullableRoute; - public static final IVersionedSerializer> partialRoute; + public static final UnversionedSerializer> nullableRoute; + public static final UnversionedSerializer> partialRoute; public static final AbstractRoutablesSerializer> fullRoute; - public static final IVersionedSerializer> seekables; - public static final IVersionedSerializer> nullableFullRoute; + public static final UnversionedSerializer> seekables; + public static final UnversionedSerializer> nullableFullRoute; public static final AbstractRoutablesSerializer> unseekables; public static final AbstractRoutablesSerializer> participants; - public static final IVersionedSerializer> nullableParticipants; + public static final UnversionedSerializer> nullableParticipants; static { @@ -129,39 +129,39 @@ public class KeySerializers final AccordKeySerializer key; final AccordSearchableKeySerializer routingKey; - final IVersionedSerializer nullableRoutingKey; + final UnversionedSerializer nullableRoutingKey; final AbstractSearchableKeysSerializer routingKeys; - final IVersionedSerializer keys; + final UnversionedSerializer keys; final AbstractSearchableKeysSerializer partialKeyRoute; final AbstractSearchableKeysSerializer fullKeyRoute; - final IVersionedSerializer range; + final UnversionedSerializer range; final AbstractRangesSerializer ranges; final AbstractRangesSerializer partialRangeRoute; final AbstractRangesSerializer fullRangeRoute; final AbstractRoutablesSerializer> route; - final IVersionedSerializer> nullableRoute; - final IVersionedSerializer> partialRoute; + final UnversionedSerializer> nullableRoute; + final UnversionedSerializer> partialRoute; final AbstractRoutablesSerializer> fullRoute; final AbstractSeekablesSerializer seekables; - final IVersionedSerializer> nullableFullRoute; + final UnversionedSerializer> nullableFullRoute; final AbstractRoutablesSerializer> unseekables; final AbstractRoutablesSerializer> participants; - final IVersionedSerializer> nullableParticipants; + final UnversionedSerializer> nullableParticipants; private Impl() { this((AccordKeySerializer) (AccordKeySerializer) PartitionKey.serializer, (AccordSearchableKeySerializer) (AccordSearchableKeySerializer) TokenKey.serializer, - (IVersionedSerializer) (IVersionedSerializer) TokenRange.serializer); + (UnversionedSerializer) (UnversionedSerializer) TokenRange.serializer); } @VisibleForTesting public Impl(AccordKeySerializer key, AccordSearchableKeySerializer routingKey, - IVersionedSerializer range) + UnversionedSerializer range) { this.key = key; this.routingKey = routingKey; @@ -170,7 +170,7 @@ public class KeySerializers this.nullableRoutingKey = NullableSerializer.wrap(routingKey); this.routingKeys = new AbstractSearchableKeysSerializer<>(routingKey, RoutingKey[]::new) { - @Override RoutingKeys deserialize(DataInputPlus in, int version, RoutingKey[] keys) + @Override RoutingKeys deserialize(DataInputPlus in, RoutingKey[] keys) { return RoutingKeys.SerializationSupport.create(keys); } @@ -178,7 +178,7 @@ public class KeySerializers this.keys = new AbstractKeysSerializer<>(key, Key[]::new) { - @Override Keys deserialize(DataInputPlus in, int version, Key[] keys) + @Override Keys deserialize(DataInputPlus in, Key[] keys) { return Keys.SerializationSupport.create(keys); } @@ -186,54 +186,54 @@ public class KeySerializers this.partialKeyRoute = new AbstractSearchableKeysSerializer<>(routingKey, RoutingKey[]::new) { - @Override PartialKeyRoute deserialize(DataInputPlus in, int version, RoutingKey[] keys) throws IOException + @Override PartialKeyRoute deserialize(DataInputPlus in, RoutingKey[] keys) throws IOException { - RoutingKey homeKey = routingKey.deserialize(in, version); + RoutingKey homeKey = routingKey.deserialize(in); return PartialKeyRoute.SerializationSupport.create(homeKey, keys); } @Override - public void serialize(PartialKeyRoute route, DataOutputPlus out, int version) throws IOException + public void serialize(PartialKeyRoute route, DataOutputPlus out) throws IOException { - super.serialize(route, out, version); - routingKey.serialize(route.homeKey, out, version); + super.serialize(route, out); + routingKey.serialize(route.homeKey, out); } @Override - public long serializedSize(PartialKeyRoute routables, int version) + public long serializedSize(PartialKeyRoute routables) { - return super.serializedSize(routables, version) - + routingKey.serializedSize(routables.homeKey, version); + return super.serializedSize(routables) + + routingKey.serializedSize(routables.homeKey); } }; this.fullKeyRoute = new AbstractSearchableKeysSerializer<>(routingKey, RoutingKey[]::new) { - @Override FullKeyRoute deserialize(DataInputPlus in, int version, RoutingKey[] keys) throws IOException + @Override FullKeyRoute deserialize(DataInputPlus in, RoutingKey[] keys) throws IOException { - RoutingKey homeKey = routingKey.deserialize(in, version); + RoutingKey homeKey = routingKey.deserialize(in); return FullKeyRoute.SerializationSupport.create(homeKey, keys); } @Override - public void serialize(FullKeyRoute route, DataOutputPlus out, int version) throws IOException + public void serialize(FullKeyRoute route, DataOutputPlus out) throws IOException { - super.serialize(route, out, version); - routingKey.serialize(route.homeKey, out, version); + super.serialize(route, out); + routingKey.serialize(route.homeKey, out); } @Override - public long serializedSize(FullKeyRoute routables, int version) + public long serializedSize(FullKeyRoute routables) { - return super.serializedSize(routables, version) - + routingKey.serializedSize(routables.homeKey, version); + return super.serializedSize(routables) + + routingKey.serializedSize(routables.homeKey); } }; this.ranges = new AbstractRangesSerializer<>(routingKey) { @Override - public Ranges deserialize(DataInputPlus in, int version, Range[] ranges) + public Ranges deserialize(DataInputPlus in, Range[] ranges) { return Ranges.ofSortedAndDeoverlapped(ranges); } @@ -242,47 +242,47 @@ public class KeySerializers this.partialRangeRoute = new AbstractRangesSerializer<>(routingKey) { - @Override PartialRangeRoute deserialize(DataInputPlus in, int version, Range[] rs) throws IOException + @Override PartialRangeRoute deserialize(DataInputPlus in, Range[] rs) throws IOException { - RoutingKey homeKey = routingKey.deserialize(in, version); + RoutingKey homeKey = routingKey.deserialize(in); return PartialRangeRoute.SerializationSupport.create(homeKey, rs); } @Override - public void serialize(PartialRangeRoute route, DataOutputPlus out, int version) throws IOException + public void serialize(PartialRangeRoute route, DataOutputPlus out) throws IOException { - super.serialize(route, out, version); - routingKey.serialize(route.homeKey, out, version); + super.serialize(route, out); + routingKey.serialize(route.homeKey, out); } @Override - public long serializedSize(PartialRangeRoute rs, int version) + public long serializedSize(PartialRangeRoute rs) { - return super.serializedSize(rs, version) - + routingKey.serializedSize(rs.homeKey, version); + return super.serializedSize(rs) + + routingKey.serializedSize(rs.homeKey); } }; this.fullRangeRoute = new AbstractRangesSerializer<>(routingKey) { - @Override FullRangeRoute deserialize(DataInputPlus in, int version, Range[] Ranges) throws IOException + @Override FullRangeRoute deserialize(DataInputPlus in, Range[] Ranges) throws IOException { - RoutingKey homeKey = routingKey.deserialize(in, version); + RoutingKey homeKey = routingKey.deserialize(in); return FullRangeRoute.SerializationSupport.create(homeKey, Ranges); } @Override - public void serialize(FullRangeRoute route, DataOutputPlus out, int version) throws IOException + public void serialize(FullRangeRoute route, DataOutputPlus out) throws IOException { - super.serialize(route, out, version); - routingKey.serialize(route.homeKey, out, version); + super.serialize(route, out); + routingKey.serialize(route.homeKey, out); } @Override - public long serializedSize(FullRangeRoute ranges, int version) + public long serializedSize(FullRangeRoute ranges) { - return super.serializedSize(ranges, version) - + routingKey.serializedSize(ranges.homeKey(), version); + return super.serializedSize(ranges) + + routingKey.serializedSize(ranges.homeKey()); } }; @@ -303,7 +303,7 @@ public class KeySerializers } } - public static class AbstractRoutablesSerializer> implements IVersionedSerializer + public static class AbstractRoutablesSerializer> implements UnversionedSerializer { final EnumSet permitted; final AbstractSearchableKeysSerializer routingKeys; @@ -331,7 +331,7 @@ public class KeySerializers } @Override - public void serialize(RS t, DataOutputPlus out, int version) throws IOException + public void serialize(RS t, DataOutputPlus out) throws IOException { UnseekablesKind kind = t.kind(); if (!permitted.contains(kind)) @@ -342,33 +342,33 @@ public class KeySerializers default: throw new AssertionError(); case RoutingKeys: out.writeByte(1); - routingKeys.serialize((RoutingKeys)t, out, version); + routingKeys.serialize((RoutingKeys)t, out); break; case PartialKeyRoute: out.writeByte(2); - partialKeyRoute.serialize((PartialKeyRoute)t, out, version); + partialKeyRoute.serialize((PartialKeyRoute)t, out); break; case FullKeyRoute: out.writeByte(3); - fullKeyRoute.serialize((FullKeyRoute)t, out, version); + fullKeyRoute.serialize((FullKeyRoute)t, out); break; case RoutingRanges: out.writeByte(4); - ranges.serialize((Ranges)t, out, version); + ranges.serialize((Ranges)t, out); break; case PartialRangeRoute: out.writeByte(5); - partialRangeRoute.serialize((PartialRangeRoute)t, out, version); + partialRangeRoute.serialize((PartialRangeRoute)t, out); break; case FullRangeRoute: out.writeByte(6); - fullRangeRoute.serialize((FullRangeRoute)t, out, version); + fullRangeRoute.serialize((FullRangeRoute)t, out); break; } } @Override - public RS deserialize(DataInputPlus in, int version) throws IOException + public RS deserialize(DataInputPlus in) throws IOException { byte b = in.readByte(); UnseekablesKind kind; @@ -376,156 +376,156 @@ public class KeySerializers switch (b) { default: throw new IOException("Corrupted input: expected byte 1, 2, 3, 4 or 5; received " + b); - case 1: kind = UnseekablesKind.RoutingKeys; result = (RS)routingKeys.deserialize(in, version); break; - case 2: kind = UnseekablesKind.PartialKeyRoute; result = (RS)partialKeyRoute.deserialize(in, version); break; - case 3: kind = UnseekablesKind.FullKeyRoute; result = (RS)fullKeyRoute.deserialize(in, version); break; - case 4: kind = UnseekablesKind.RoutingRanges; result = (RS)ranges.deserialize(in, version); break; - case 5: kind = UnseekablesKind.PartialRangeRoute; result = (RS)partialRangeRoute.deserialize(in, version); break; - case 6: kind = UnseekablesKind.FullRangeRoute; result = (RS)fullRangeRoute.deserialize(in, version); break; + case 1: kind = UnseekablesKind.RoutingKeys; result = (RS)routingKeys.deserialize(in); break; + case 2: kind = UnseekablesKind.PartialKeyRoute; result = (RS)partialKeyRoute.deserialize(in); break; + case 3: kind = UnseekablesKind.FullKeyRoute; result = (RS)fullKeyRoute.deserialize(in); break; + case 4: kind = UnseekablesKind.RoutingRanges; result = (RS)ranges.deserialize(in); break; + case 5: kind = UnseekablesKind.PartialRangeRoute; result = (RS)partialRangeRoute.deserialize(in); break; + case 6: kind = UnseekablesKind.FullRangeRoute; result = (RS)fullRangeRoute.deserialize(in); break; } Invariants.require(permitted.contains(kind)); return result; } - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { byte b = in.readByte(); switch (b) { default: throw new IOException("Corrupted input: expected byte 1, 2, 3, 4 or 5; received " + b); - case 1: routingKeys.skip(in, version); break; - case 2: partialKeyRoute.skip(in, version); break; - case 3: fullKeyRoute.skip(in, version); break; - case 4: ranges.skip(in, version); break; - case 5: partialRangeRoute.skip(in, version); break; - case 6: fullRangeRoute.skip(in, version); break; + case 1: routingKeys.skip(in); break; + case 2: partialKeyRoute.skip(in); break; + case 3: fullKeyRoute.skip(in); break; + case 4: ranges.skip(in); break; + case 5: partialRangeRoute.skip(in); break; + case 6: fullRangeRoute.skip(in); break; } } @Override - public long serializedSize(RS t, int version) + public long serializedSize(RS t) { switch (t.kind()) { default: throw new AssertionError(); case RoutingKeys: - return 1 + routingKeys.serializedSize((RoutingKeys)t, version); + return 1 + routingKeys.serializedSize((RoutingKeys)t); case PartialKeyRoute: - return 1 + partialKeyRoute.serializedSize((PartialKeyRoute)t, version); + return 1 + partialKeyRoute.serializedSize((PartialKeyRoute)t); case FullKeyRoute: - return 1 + fullKeyRoute.serializedSize((FullKeyRoute)t, version); + return 1 + fullKeyRoute.serializedSize((FullKeyRoute)t); case RoutingRanges: - return 1 + ranges.serializedSize((Ranges)t, version); + return 1 + ranges.serializedSize((Ranges)t); case PartialRangeRoute: - return 1 + partialRangeRoute.serializedSize((PartialRangeRoute)t, version); + return 1 + partialRangeRoute.serializedSize((PartialRangeRoute)t); case FullRangeRoute: - return 1 + fullRangeRoute.serializedSize((FullRangeRoute)t, version); + return 1 + fullRangeRoute.serializedSize((FullRangeRoute)t); } } } - public static final IVersionedSerializer seekable = new IVersionedSerializer<>() + public static final UnversionedSerializer seekable = new UnversionedSerializer<>() { @Override - public void serialize(Seekable seekable, DataOutputPlus out, int version) throws IOException + public void serialize(Seekable seekable, DataOutputPlus out) throws IOException { switch (seekable.domain()) { default: throw new AssertionError(); case Key: out.writeByte(0); - PartitionKey.serializer.serialize((PartitionKey) seekable, out, version); + PartitionKey.serializer.serialize((PartitionKey) seekable, out); break; case Range: out.writeByte(1); - TokenRange.serializer.serialize((TokenRange) seekable, out, version); + TokenRange.serializer.serialize((TokenRange) seekable, out); break; } } @Override - public Seekable deserialize(DataInputPlus in, int version) throws IOException + public Seekable deserialize(DataInputPlus in) throws IOException { byte b = in.readByte(); switch (b) { default: throw new IOException("Corrupted input: expected byte 1 or 2, received " + b); - case 0: return PartitionKey.serializer.deserialize(in, version); - case 1: return TokenRange.serializer.deserialize(in, version); + case 0: return PartitionKey.serializer.deserialize(in); + case 1: return TokenRange.serializer.deserialize(in); } } @Override - public long serializedSize(Seekable seekable, int version) + public long serializedSize(Seekable seekable) { switch (seekable.domain()) { default: throw new AssertionError(); case Key: - return 1 + PartitionKey.serializer.serializedSize((PartitionKey) seekable, version); + return 1 + PartitionKey.serializer.serializedSize((PartitionKey) seekable); case Range: - return 1 + TokenRange.serializer.serializedSize((TokenRange) seekable, version); + return 1 + TokenRange.serializer.serializedSize((TokenRange) seekable); } } }; - public static class AbstractSeekablesSerializer implements IVersionedSerializer> + public static class AbstractSeekablesSerializer implements UnversionedSerializer> { - final IVersionedSerializer keys; + final UnversionedSerializer keys; final AbstractRangesSerializer ranges; - public AbstractSeekablesSerializer(IVersionedSerializer keys, AbstractRangesSerializer ranges) + public AbstractSeekablesSerializer(UnversionedSerializer keys, AbstractRangesSerializer ranges) { this.keys = keys; this.ranges = ranges; } @Override - public void serialize(Seekables t, DataOutputPlus out, int version) throws IOException + public void serialize(Seekables t, DataOutputPlus out) throws IOException { switch (t.domain()) { default: throw new AssertionError(); case Key: out.writeByte(1); - keys.serialize((Keys)t, out, version); + keys.serialize((Keys)t, out); break; case Range: out.writeByte(2); - ranges.serialize((Ranges)t, out, version); + ranges.serialize((Ranges)t, out); break; } } @Override - public Seekables deserialize(DataInputPlus in, int version) throws IOException + public Seekables deserialize(DataInputPlus in) throws IOException { byte b = in.readByte(); switch (b) { default: throw new IOException("Corrupted input: expected byte 1 or 2, received " + b); - case 1: return keys.deserialize(in, version); - case 2: return ranges.deserialize(in, version); + case 1: return keys.deserialize(in); + case 2: return ranges.deserialize(in); } } @Override - public long serializedSize(Seekables t, int version) + public long serializedSize(Seekables t) { switch (t.domain()) { default: throw new AssertionError(); case Key: - return 1 + keys.serializedSize((Keys)t, version); + return 1 + keys.serializedSize((Keys)t); case Range: - return 1 + ranges.serializedSize((Ranges)t, version); + return 1 + ranges.serializedSize((Ranges)t); } } } // this serializer is designed to permits using the collection in its serialized form with minimal in-memory state. // it also saves some memory by avoiding duplicating prefixes (which happens to also assist faster lookups) - public abstract static class AbstractKeysSerializer> implements IVersionedSerializer + public abstract static class AbstractKeysSerializer> implements UnversionedSerializer { final AccordKeySerializer keySerializer; final IntFunction allocate; @@ -537,44 +537,44 @@ public class KeySerializers } @Override - public void serialize(KS keys, DataOutputPlus out, int version) throws IOException + public void serialize(KS keys, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(keys.size()); for (int i=0, mi=keys.size(); i> implements IVersionedSerializer + public abstract static class AbstractSearchableSerializer> implements UnversionedSerializer { final AccordSearchableKeySerializer keySerializer; final IntFunction allocate; @@ -590,30 +590,30 @@ public class KeySerializers return keySerializer.serializedSizeOfPrefix(prefix); } - private void serializePrefix(Object prefix, DataOutputPlus out, int version) throws IOException + private void serializePrefix(Object prefix, DataOutputPlus out) throws IOException { - keySerializer.serializePrefix(prefix, out, version); + keySerializer.serializePrefix(prefix, out); } - private Object deserializePrefix(DataInputPlus in, int version) throws IOException + private Object deserializePrefix(DataInputPlus in) throws IOException { - return keySerializer.deserializePrefix(in, version); + return keySerializer.deserializePrefix(in); } // if we store Ranges, we have twice as many indexes abstract int recordCountToLengthCount(int recordCount); abstract int fixedKeyLengthForPrefix(Object prefix); abstract int serializedSizeWithoutPrefix(R routable); - abstract void serializeWithoutPrefixOrLength(R routable, DataOutputPlus out, int version) throws IOException; + abstract void serializeWithoutPrefixOrLength(R routable, DataOutputPlus out) throws IOException; abstract void serializeOffsets(RS unseekables, int start, int end, DataOutputPlus out) throws IOException; - abstract R deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException; - abstract R deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in, int version) throws IOException; + abstract R deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException; + abstract R deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in) throws IOException; - abstract RS deserialize(DataInputPlus in, int version, R[] keys) throws IOException; + abstract RS deserialize(DataInputPlus in, R[] keys) throws IOException; @Override - public long serializedSize(RS routables, int version) + public long serializedSize(RS routables) { int count = routables.size(); long size = TypeSizes.sizeofUnsignedVInt(count); @@ -652,7 +652,7 @@ public class KeySerializers } @Override - public void serialize(RS keys, DataOutputPlus out, int version) throws IOException + public void serialize(RS keys, DataOutputPlus out) throws IOException { int size = keys.size(); out.writeUnsignedVInt32(size); @@ -672,11 +672,11 @@ public class KeySerializers } out.writeUnsignedVInt32(size - i); - serializePrefix(prefix, out, version); + serializePrefix(prefix, out); int fixedLength = fixedKeyLengthForPrefix(prefix); if (fixedLength < 0) serializeOffsets(keys, prefixStart, i, out); - serializeKeysWithoutPrefix(keys, prefixStart, i, out, version); + serializeKeysWithoutPrefix(keys, prefixStart, i, out); prefixStart = i; prefix = nextPrefix; } @@ -690,13 +690,13 @@ public class KeySerializers return size; } - private void serializeKeysWithoutPrefix(RS keys, int start, int end, DataOutputPlus out, int version) throws IOException + private void serializeKeysWithoutPrefix(RS keys, int start, int end, DataOutputPlus out) throws IOException { for (int i = start; i < end; ++i) - serializeWithoutPrefixOrLength(keys.get(i), out, version); + serializeWithoutPrefixOrLength(keys.get(i), out); } - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { int remaining = in.readUnsignedVInt32(); if (remaining == 0) @@ -706,7 +706,7 @@ public class KeySerializers { int count = remaining - in.readUnsignedVInt32(); remaining -= count; - Object prefix = deserializePrefix(in, version); + Object prefix = deserializePrefix(in); int fixedLength = fixedKeyLengthForPrefix(prefix); if (fixedLength >= 0) { @@ -722,7 +722,7 @@ public class KeySerializers } @Override - public RS deserialize(DataInputPlus in, int version) throws IOException + public RS deserialize(DataInputPlus in) throws IOException { int remaining = in.readUnsignedVInt32(); R[] out = allocate.apply(remaining); @@ -731,12 +731,12 @@ public class KeySerializers { int count = remaining - in.readUnsignedVInt32(); remaining -= count; - Object prefix = deserializePrefix(in, version); + Object prefix = deserializePrefix(in); int fixedLength = fixedKeyLengthForPrefix(prefix); if (fixedLength >= 0) { for (int i = 0 ; i < count ; ++i) - out[outCount++] = deserializeWithPrefix(prefix, fixedLength, in, version); + out[outCount++] = deserializeWithPrefix(prefix, fixedLength, in); } else { @@ -744,7 +744,7 @@ public class KeySerializers if (lengthCount == 1) { int end = in.readInt(); - out[outCount++] = deserializeWithPrefix(prefix, end, in, version); + out[outCount++] = deserializeWithPrefix(prefix, end, in); } else { @@ -757,19 +757,19 @@ public class KeySerializers prev = end; } for (int i = 0 ; i < count ; ++i) - out[outCount++] = deserializeWithPrefix(prefix, i, lengths, in, version); + out[outCount++] = deserializeWithPrefix(prefix, i, lengths, in); cachedInts().forceDiscard(lengths); } } } - return deserialize(in, version, out); + return deserialize(in, out); } } // this serializer is designed to permits using the collection in its serialized form with minimal in-memory state. // it also saves some memory by avoiding duplicating prefixes (which happens to also assist faster lookups) - public abstract static class AbstractSearchableKeysSerializer> extends AbstractSearchableSerializer implements IVersionedSerializer + public abstract static class AbstractSearchableKeysSerializer> extends AbstractSearchableSerializer implements UnversionedSerializer { public AbstractSearchableKeysSerializer(AccordSearchableKeySerializer keySerializer, IntFunction allocate) { @@ -795,9 +795,9 @@ public class KeySerializers } @Override - final void serializeWithoutPrefixOrLength(K routable, DataOutputPlus out, int version) throws IOException + final void serializeWithoutPrefixOrLength(K routable, DataOutputPlus out) throws IOException { - keySerializer.serializeWithoutPrefixOrLength(routable, out, version); + keySerializer.serializeWithoutPrefixOrLength(routable, out); } @Override @@ -812,19 +812,19 @@ public class KeySerializers } @Override - final K deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException + final K deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException { - return keySerializer.deserializeWithPrefix(prefix, length, in, version); + return keySerializer.deserializeWithPrefix(prefix, length, in); } @Override - final K deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in, int version) throws IOException + final K deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in) throws IOException { - return keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex], in, version); + return keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex], in); } } - public abstract static class AbstractRangesSerializer extends AbstractSearchableSerializer implements IVersionedSerializer + public abstract static class AbstractRangesSerializer extends AbstractSearchableSerializer implements UnversionedSerializer { public AbstractRangesSerializer(AccordSearchableKeySerializer keySerializer) { @@ -851,10 +851,10 @@ public class KeySerializers } @Override - final void serializeWithoutPrefixOrLength(Range key, DataOutputPlus out, int version) throws IOException + final void serializeWithoutPrefixOrLength(Range key, DataOutputPlus out) throws IOException { - keySerializer.serializeWithoutPrefixOrLength(key.start(), out, version); - keySerializer.serializeWithoutPrefixOrLength(key.end(), out, version); + keySerializer.serializeWithoutPrefixOrLength(key.start(), out); + keySerializer.serializeWithoutPrefixOrLength(key.end(), out); } @Override @@ -872,18 +872,18 @@ public class KeySerializers } @Override - final Range deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException + final Range deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException { - RoutingKey start = keySerializer.deserializeWithPrefix(prefix, length/2, in, version); - RoutingKey end = keySerializer.deserializeWithPrefix(prefix, length/2, in, version); + RoutingKey start = keySerializer.deserializeWithPrefix(prefix, length/2, in); + RoutingKey end = keySerializer.deserializeWithPrefix(prefix, length/2, in); return start.rangeFactory().newRange(start, end); } @Override - final Range deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in, int version) throws IOException + final Range deserializeWithPrefix(Object prefix, int lengthIndex, int[] lengths, DataInputPlus in) throws IOException { - RoutingKey start = keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex * 2], in, version); - RoutingKey end = keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex * 2 + 1], in, version); + RoutingKey start = keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex * 2], in); + RoutingKey end = keySerializer.deserializeWithPrefix(prefix, lengths[lengthIndex * 2 + 1], in); return start.rangeFactory().newRange(start, end); } } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/LatestDepsSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/LatestDepsSerializers.java index c9b5379939..0dda159259 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/LatestDepsSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/LatestDepsSerializers.java @@ -31,17 +31,17 @@ import accord.primitives.Route; import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; public class LatestDepsSerializers { - public static final IVersionedSerializer latestDeps = new IVersionedSerializer<>() + public static final UnversionedSerializer latestDeps = new UnversionedSerializer<>() { @Override - public void serialize(LatestDeps t, DataOutputPlus out, int version) throws IOException + public void serialize(LatestDeps t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(t.size()); if (t.size() == 0) @@ -50,25 +50,25 @@ public class LatestDepsSerializers for (int i = 0 ; i < t.size() ; ++i) { RoutingKey start = t.startAt(i); - KeySerializers.routingKey.serialize(start, out, version); + KeySerializers.routingKey.serialize(start, out); LatestDeps.LatestEntry e = t.valueAt(i); if (e == null) { - CommandSerializers.knownDeps.serialize(null, out, version); + CommandSerializers.knownDeps.serialize(null, out); } else { - CommandSerializers.knownDeps.serialize(e.known, out, version); - CommandSerializers.ballot.serialize(e.ballot, out, version); - DepsSerializers.nullableDeps.serialize(e.coordinatedDeps, out, version); - DepsSerializers.nullableDeps.serialize(e.localDeps, out, version); + CommandSerializers.knownDeps.serialize(e.known, out); + CommandSerializers.ballot.serialize(e.ballot, out); + DepsSerializers.nullableDeps.serialize(e.coordinatedDeps, out); + DepsSerializers.nullableDeps.serialize(e.localDeps, out); } } - KeySerializers.routingKey.serialize(t.startAt(t.size()), out, version); + KeySerializers.routingKey.serialize(t.startAt(t.size()), out); } @Override - public LatestDeps deserialize(DataInputPlus in, int version) throws IOException + public LatestDeps deserialize(DataInputPlus in) throws IOException { int size = in.readUnsignedVInt32(); if (size == 0) @@ -78,23 +78,23 @@ public class LatestDepsSerializers LatestDeps.LatestEntry[] values = new LatestDeps.LatestEntry[size]; for (int i = 0 ; i < size ; ++i) { - starts[i] = KeySerializers.routingKey.deserialize(in, version); - Known.KnownDeps knownDeps = CommandSerializers.knownDeps.deserialize(in, version); + starts[i] = KeySerializers.routingKey.deserialize(in); + Known.KnownDeps knownDeps = CommandSerializers.knownDeps.deserialize(in); if (knownDeps == null) continue; - Ballot ballot = CommandSerializers.ballot.deserialize(in, version); - Deps coordinatedDeps = DepsSerializers.nullableDeps.deserialize(in, version); - Deps localDeps = DepsSerializers.nullableDeps.deserialize(in, version); + Ballot ballot = CommandSerializers.ballot.deserialize(in); + Deps coordinatedDeps = DepsSerializers.nullableDeps.deserialize(in); + Deps localDeps = DepsSerializers.nullableDeps.deserialize(in); values[i] = new LatestDeps.LatestEntry(knownDeps, ballot, coordinatedDeps, localDeps); } - starts[size] = KeySerializers.routingKey.deserialize(in, version); + starts[size] = KeySerializers.routingKey.deserialize(in); return LatestDeps.SerializerSupport.create(true, starts, values); } @Override - public long serializedSize(LatestDeps t, int version) + public long serializedSize(LatestDeps t) { long size = 0; size += TypeSizes.sizeofUnsignedVInt(t.size()); @@ -103,21 +103,21 @@ public class LatestDepsSerializers for (int i = 0 ; i < t.size() ; ++i) { RoutingKey start = t.startAt(i); - size += KeySerializers.routingKey.serializedSize(start, version); + size += KeySerializers.routingKey.serializedSize(start); LatestDeps.LatestEntry e = t.valueAt(i); if (e == null) { - size += CommandSerializers.knownDeps.serializedSize(null, version); + size += CommandSerializers.knownDeps.serializedSize(null); } else { - size += CommandSerializers.knownDeps.serializedSize(e.known, version); - size += CommandSerializers.ballot.serializedSize(e.ballot, version); - size += DepsSerializers.nullableDeps.serializedSize(e.coordinatedDeps, version); - size += DepsSerializers.nullableDeps.serializedSize(e.localDeps, version); + size += CommandSerializers.knownDeps.serializedSize(e.known); + size += CommandSerializers.ballot.serializedSize(e.ballot); + size += DepsSerializers.nullableDeps.serializedSize(e.coordinatedDeps); + size += DepsSerializers.nullableDeps.serializedSize(e.localDeps); } } - size += KeySerializers.routingKey.serializedSize(t.startAt(t.size()), version); + size += KeySerializers.routingKey.serializedSize(t.startAt(t.size())); return size; } }; @@ -125,13 +125,13 @@ public class LatestDepsSerializers public static final IVersionedSerializer request = new TxnRequestSerializer.WithUnsyncedSerializer<>() { @Override - public void serializeBody(GetLatestDeps msg, DataOutputPlus out, int version) throws IOException + public void serializeBody(GetLatestDeps msg, DataOutputPlus out, Version version) throws IOException { ExecuteAtSerializer.serialize(msg.executeAt, out); } @Override - public GetLatestDeps deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public GetLatestDeps deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { Ballot ballot = CommandSerializers.ballot.deserialize(in); Timestamp executeAt = ExecuteAtSerializer.deserialize(in); @@ -139,30 +139,30 @@ public class LatestDepsSerializers } @Override - public long serializedBodySize(GetLatestDeps msg, int version) + public long serializedBodySize(GetLatestDeps msg, Version version) { return ExecuteAtSerializer.serializedSize(msg.executeAt); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { @Override - public void serialize(GetLatestDepsOk reply, DataOutputPlus out, int version) throws IOException + public void serialize(GetLatestDepsOk reply, DataOutputPlus out) throws IOException { - latestDeps.serialize(reply.deps, out, version); + latestDeps.serialize(reply.deps, out); } @Override - public GetLatestDepsOk deserialize(DataInputPlus in, int version) throws IOException + public GetLatestDepsOk deserialize(DataInputPlus in) throws IOException { - return new GetLatestDepsOk(latestDeps.deserialize(in, version)); + return new GetLatestDepsOk(latestDeps.deserialize(in)); } @Override - public long serializedSize(GetLatestDepsOk reply, int version) + public long serializedSize(GetLatestDepsOk reply) { - return latestDeps.serializedSize(reply.deps, version); + return latestDeps.serializedSize(reply.deps); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/PreacceptSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/PreacceptSerializers.java index 3f02f2d903..ae07f347c4 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/PreacceptSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/PreacceptSerializers.java @@ -31,7 +31,7 @@ import accord.primitives.PartialTxn; import accord.primitives.Route; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -45,7 +45,7 @@ public class PreacceptSerializers public static final IVersionedSerializer request = new WithUnsyncedSerializer<>() { @Override - public void serializeBody(PreAccept msg, DataOutputPlus out, int version) throws IOException + public void serializeBody(PreAccept msg, DataOutputPlus out, Version version) throws IOException { int flags = (msg.partialDeps == null ? 0 : 1) | (msg.route == null ? 0 : 2) @@ -54,76 +54,76 @@ public class PreacceptSerializers out.writeByte(flags); CommandSerializers.partialTxn.serialize(msg.partialTxn, out, version); if (msg.partialDeps != null) - DepsSerializers.partialDeps.serialize(msg.partialDeps, out, version); + DepsSerializers.partialDeps.serialize(msg.partialDeps, out); if (msg.route != null) - KeySerializers.fullRoute.serialize(msg.route, out, version); + KeySerializers.fullRoute.serialize(msg.route, out); if (msg.acceptEpoch != msg.minEpoch) out.writeUnsignedVInt(msg.acceptEpoch - msg.minEpoch); } @Override - public PreAccept deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public PreAccept deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { byte flags = in.readByte(); PartialTxn partialTxn = CommandSerializers.partialTxn.deserialize(in, version); - @Nullable PartialDeps partialDeps = (flags & 1) == 0 ? null : DepsSerializers.partialDeps.deserialize(in, version); - @Nullable FullRoute fullRoute = (flags & 2) == 0 ? null : KeySerializers.fullRoute.deserialize(in, version); + @Nullable PartialDeps partialDeps = (flags & 1) == 0 ? null : DepsSerializers.partialDeps.deserialize(in); + @Nullable FullRoute fullRoute = (flags & 2) == 0 ? null : KeySerializers.fullRoute.deserialize(in); boolean hasCoordinatorVote = (flags & 4) != 0; long acceptEpoch = (flags & 8) == 0 ? minEpoch : in.readUnsignedVInt() + minEpoch; return PreAccept.SerializerSupport.create(txnId, scope, waitForEpoch, minEpoch, acceptEpoch, partialTxn, partialDeps, hasCoordinatorVote, fullRoute); } @Override - public long serializedBodySize(PreAccept msg, int version) + public long serializedBodySize(PreAccept msg, Version version) { return TypeSizes.BYTE_SIZE + CommandSerializers.partialTxn.serializedSize(msg.partialTxn, version) - + (msg.partialDeps == null ? 0 : DepsSerializers.partialDeps.serializedSize(msg.partialDeps, version)) - + (msg.route == null ? 0 : KeySerializers.fullRoute.serializedSize(msg.route, version)) + + (msg.partialDeps == null ? 0 : DepsSerializers.partialDeps.serializedSize(msg.partialDeps)) + + (msg.route == null ? 0 : KeySerializers.fullRoute.serializedSize(msg.route)) + (msg.acceptEpoch == msg.minEpoch ? 0 : TypeSizes.sizeofUnsignedVInt(msg.acceptEpoch - msg.minEpoch)); } }; - public static final IVersionedSerializer reply = new IVersionedSerializer<>() + public static final UnversionedSerializer reply = new UnversionedSerializer<>() { @Override - public void serialize(PreAcceptReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(PreAcceptReply reply, DataOutputPlus out) throws IOException { out.writeBoolean(reply.isOk()); if (!reply.isOk()) return; PreAcceptOk preAcceptOk = (PreAcceptOk) reply; - CommandSerializers.txnId.serialize(preAcceptOk.txnId, out, version); + CommandSerializers.txnId.serialize(preAcceptOk.txnId, out); ExecuteAtSerializer.serialize(preAcceptOk.txnId, preAcceptOk.witnessedAt, out); - DepsSerializers.deps.serialize(preAcceptOk.deps, out, version); + DepsSerializers.deps.serialize(preAcceptOk.deps, out); out.writeUnsignedVInt32(preAcceptOk.flags.bits()); } @Override - public PreAcceptReply deserialize(DataInputPlus in, int version) throws IOException + public PreAcceptReply deserialize(DataInputPlus in) throws IOException { if (!in.readBoolean()) return PreAccept.PreAcceptNack.INSTANCE; - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); return new PreAcceptOk(txnId, ExecuteAtSerializer.deserialize(txnId, in), - DepsSerializers.deps.deserialize(in, version), + DepsSerializers.deps.deserialize(in), ExecuteFlags.get(in.readUnsignedVInt32())); } @Override - public long serializedSize(PreAcceptReply reply, int version) + public long serializedSize(PreAcceptReply reply) { long size = TypeSizes.sizeof(reply.isOk()); if (!reply.isOk()) return size; PreAcceptOk preAcceptOk = (PreAcceptOk) reply; - size += CommandSerializers.txnId.serializedSize(preAcceptOk.txnId, version); + size += CommandSerializers.txnId.serializedSize(preAcceptOk.txnId); size += ExecuteAtSerializer.serializedSize(preAcceptOk.txnId, preAcceptOk.witnessedAt); - size += DepsSerializers.deps.serializedSize(preAcceptOk.deps, version); + size += DepsSerializers.deps.serializedSize(preAcceptOk.deps); size += TypeSizes.sizeofUnsignedVInt(preAcceptOk.flags.bits()); return size; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/ReadDataSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/ReadDataSerializers.java index e7afd47471..3aedf090ea 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/ReadDataSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/ReadDataSerializers.java @@ -41,7 +41,7 @@ import accord.primitives.Ranges; import accord.primitives.Timestamp; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -61,20 +61,20 @@ public class ReadDataSerializers public static final IVersionedSerializer readData = new IVersionedSerializer() { @Override - public void serialize(ReadData t, DataOutputPlus out, int version) throws IOException + public void serialize(ReadData t, DataOutputPlus out, Version version) throws IOException { out.writeByte(t.kind().val); serializerFor(t).serialize(t, out, version); } @Override - public ReadData deserialize(DataInputPlus in, int version) throws IOException + public ReadData deserialize(DataInputPlus in, Version version) throws IOException { return serializerFor(ReadType.valueOf(in.readByte())).deserialize(in, version); } @Override - public long serializedSize(ReadData t, int version) + public long serializedSize(ReadData t, Version version) { return sizeof(t.kind().val) + serializerFor(t).serializedSize(t, version); } @@ -85,44 +85,44 @@ public class ReadDataSerializers public static class ApplyThenWaitUntilAppliedSerializer implements ReadDataSerializer { @Override - public void serialize(ApplyThenWaitUntilApplied msg, DataOutputPlus out, int version) throws IOException + public void serialize(ApplyThenWaitUntilApplied msg, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(msg.txnId, out, version); - KeySerializers.participants.serialize(msg.scope, out, version); + CommandSerializers.txnId.serialize(msg.txnId, out); + KeySerializers.participants.serialize(msg.scope, out); out.writeUnsignedVInt(msg.minEpoch()); ExecuteAtSerializer.serialize(msg.txnId, msg.executeAt, out); - KeySerializers.fullRoute.serialize(msg.route, out, version); + KeySerializers.fullRoute.serialize(msg.route, out); CommandSerializers.partialTxn.serialize(msg.txn, out, version); - DepsSerializers.partialDeps.serialize(msg.deps, out, version); + DepsSerializers.partialDeps.serialize(msg.deps, out); CommandSerializers.nullableWrites.serialize(msg.writes, out, version); } @Override - public ApplyThenWaitUntilApplied deserialize(DataInputPlus in, int version) throws IOException + public ApplyThenWaitUntilApplied deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); return ApplyThenWaitUntilApplied.SerializerSupport.create( txnId, - KeySerializers.participants.deserialize(in, version), + KeySerializers.participants.deserialize(in), in.readUnsignedVInt(), ExecuteAtSerializer.deserialize(txnId, in), - KeySerializers.fullRoute.deserialize(in, version), + KeySerializers.fullRoute.deserialize(in), CommandSerializers.partialTxn.deserialize(in, version), - DepsSerializers.partialDeps.deserialize(in, version), + DepsSerializers.partialDeps.deserialize(in), CommandSerializers.nullableWrites.deserialize(in, version), ResultSerializers.APPLIED); } @Override - public long serializedSize(ApplyThenWaitUntilApplied msg, int version) + public long serializedSize(ApplyThenWaitUntilApplied msg, Version version) { - return CommandSerializers.txnId.serializedSize(msg.txnId, version) - + KeySerializers.participants.serializedSize(msg.scope, version) + return CommandSerializers.txnId.serializedSize(msg.txnId) + + KeySerializers.participants.serializedSize(msg.scope) + TypeSizes.sizeofUnsignedVInt(msg.minEpoch()) + ExecuteAtSerializer.serializedSize(msg.txnId, msg.executeAt) - + KeySerializers.fullRoute.serializedSize(msg.route, version) + + KeySerializers.fullRoute.serializedSize(msg.route) + CommandSerializers.partialTxn.serializedSize(msg.txn, version) - + DepsSerializers.partialDeps.serializedSize(msg.deps, version) + + DepsSerializers.partialDeps.serializedSize(msg.deps) + CommandSerializers.nullableWrites.serializedSize(msg.writes, version); } } @@ -130,27 +130,27 @@ public class ReadDataSerializers private static final ReadDataSerializer readTxnData = new ReadDataSerializer() { @Override - public void serialize(ReadTxnData read, DataOutputPlus out, int version) throws IOException + public void serialize(ReadTxnData read, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(read.txnId, out, version); - KeySerializers.participants.serialize(read.scope, out, version); + CommandSerializers.txnId.serialize(read.txnId, out); + KeySerializers.participants.serialize(read.scope, out); out.writeUnsignedVInt(read.executeAtEpoch); } @Override - public ReadTxnData deserialize(DataInputPlus in, int version) throws IOException + public ReadTxnData deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long executeAtEpoch = in.readUnsignedVInt(); return ReadTxnData.SerializerSupport.create(txnId, scope, executeAtEpoch); } @Override - public long serializedSize(ReadTxnData read, int version) + public long serializedSize(ReadTxnData read, Version version) { - return CommandSerializers.txnId.serializedSize(read.txnId, version) - + KeySerializers.participants.serializedSize(read.scope, version) + return CommandSerializers.txnId.serializedSize(read.txnId) + + KeySerializers.participants.serializedSize(read.scope) + TypeSizes.sizeofUnsignedVInt(read.executeAtEpoch); } }; @@ -158,45 +158,45 @@ public class ReadDataSerializers public static final ReadDataSerializer readEphemeralTxnData = new ReadDataSerializer<>() { @Override - public void serialize(ReadEphemeralTxnData read, DataOutputPlus out, int version) throws IOException + public void serialize(ReadEphemeralTxnData read, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(read.txnId, out, version); - KeySerializers.participants.serialize(read.scope, out, version); + CommandSerializers.txnId.serialize(read.txnId, out); + KeySerializers.participants.serialize(read.scope, out); out.writeUnsignedVInt(read.executeAtEpoch); CommandSerializers.partialTxn.serialize(read.partialTxn(), out, version); - DepsSerializers.partialDeps.serialize(read.partialDeps(), out, version); - KeySerializers.fullRoute.serialize(read.route(), out, version); + DepsSerializers.partialDeps.serialize(read.partialDeps(), out); + KeySerializers.fullRoute.serialize(read.route(), out); } @Override - public ReadEphemeralTxnData deserialize(DataInputPlus in, int version) throws IOException + public ReadEphemeralTxnData deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long executeAtEpoch = in.readUnsignedVInt(); PartialTxn partialTxn = CommandSerializers.partialTxn.deserialize(in, version); - PartialDeps partialDeps = DepsSerializers.partialDeps.deserialize(in, version); - FullRoute route = KeySerializers.fullRoute.deserialize(in, version); + PartialDeps partialDeps = DepsSerializers.partialDeps.deserialize(in); + FullRoute route = KeySerializers.fullRoute.deserialize(in); return ReadEphemeralTxnData.SerializerSupport.create(txnId, scope, executeAtEpoch, partialTxn, partialDeps, route); } @Override - public long serializedSize(ReadEphemeralTxnData read, int version) + public long serializedSize(ReadEphemeralTxnData read, Version version) { - return CommandSerializers.txnId.serializedSize(read.txnId, version) - + KeySerializers.participants.serializedSize(read.scope, version) + return CommandSerializers.txnId.serializedSize(read.txnId) + + KeySerializers.participants.serializedSize(read.scope) + TypeSizes.sizeofUnsignedVInt(read.executeAtEpoch) + CommandSerializers.partialTxn.serializedSize(read.partialTxn(), version) - + DepsSerializers.partialDeps.serializedSize(read.partialDeps(), version) - + KeySerializers.fullRoute.serializedSize(read.route(), version); + + DepsSerializers.partialDeps.serializedSize(read.partialDeps()) + + KeySerializers.fullRoute.serializedSize(read.route()); } }; public interface ReadDataSerializer extends IVersionedSerializer { - void serialize(T bound, DataOutputPlus out, int version) throws IOException; - T deserialize(DataInputPlus in, int version) throws IOException; - long serializedSize(T condition, int version); + void serialize(T bound, DataOutputPlus out, Version version) throws IOException; + T deserialize(DataInputPlus in, Version version) throws IOException; + long serializedSize(T condition, Version version); } private static ReadDataSerializer serializerFor(ReadData toSerialize) @@ -225,15 +225,15 @@ public class ReadDataSerializers { // TODO (expected): use something other than ordinal final CommitOrReadNack[] nacks = CommitOrReadNack.values(); - private final IVersionedSerializer dataSerializer; + private final VersionedSerializer dataSerializer; - public ReplySerializer(IVersionedSerializer dataSerializer) + public ReplySerializer(VersionedSerializer dataSerializer) { this.dataSerializer = dataSerializer; } @Override - public void serialize(ReadReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(ReadReply reply, DataOutputPlus out, Version version) throws IOException { if (!reply.isOk()) { @@ -244,7 +244,7 @@ public class ReadDataSerializers ReadOk readOk = (ReadOk) reply; int flags = readOk.getClass() == ReadOkWithFutureEpoch.class ? 2 : readOk.uniqueHlc != 0 ? 1 : 0; out.writeByte(flags); - serializeNullable(readOk.unavailable, out, version, KeySerializers.ranges); + serializeNullable(readOk.unavailable, out, KeySerializers.ranges); dataSerializer.serialize((D) readOk.data, out, version); switch (flags) { @@ -254,13 +254,13 @@ public class ReadDataSerializers } @Override - public ReadReply deserialize(DataInputPlus in, int version) throws IOException + public ReadReply deserialize(DataInputPlus in, Version version) throws IOException { int flags = in.readByte(); if (flags > 2) return nacks[flags - 3]; - Ranges unavailable = deserializeNullable(in, version, KeySerializers.ranges); + Ranges unavailable = deserializeNullable(in, KeySerializers.ranges); D data = dataSerializer.deserialize(in, version); long extraLong = flags == 0 ? 0 : in.readUnsignedVInt(); @@ -270,14 +270,14 @@ public class ReadDataSerializers } @Override - public long serializedSize(ReadReply reply, int version) + public long serializedSize(ReadReply reply, Version version) { if (!reply.isOk()) return TypeSizes.BYTE_SIZE; ReadOk readOk = (ReadOk) reply; long size = TypeSizes.BYTE_SIZE - + serializedNullableSize(readOk.unavailable, version, KeySerializers.ranges) + + serializedNullableSize(readOk.unavailable, KeySerializers.ranges) + dataSerializer.serializedSize((D) readOk.data, version); if (readOk.uniqueHlc != 0) size += TypeSizes.sizeofUnsignedVInt(readOk.uniqueHlc); @@ -293,29 +293,29 @@ public class ReadDataSerializers public static final ReadDataSerializer waitUntilApplied = new ReadDataSerializer() { @Override - public void serialize(WaitUntilApplied waitUntilApplied, DataOutputPlus out, int version) throws IOException + public void serialize(WaitUntilApplied waitUntilApplied, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(waitUntilApplied.txnId, out, version); - KeySerializers.participants.serialize(waitUntilApplied.scope, out, version); + CommandSerializers.txnId.serialize(waitUntilApplied.txnId, out); + KeySerializers.participants.serialize(waitUntilApplied.scope, out); out.writeUnsignedVInt(waitUntilApplied.minEpoch()); out.writeUnsignedVInt(waitUntilApplied.executeAtEpoch - waitUntilApplied.minEpoch()); } @Override - public WaitUntilApplied deserialize(DataInputPlus in, int version) throws IOException + public WaitUntilApplied deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); long minEpoch = in.readUnsignedVInt(); long executeAtEpoch = minEpoch + in.readUnsignedVInt(); return WaitUntilApplied.SerializerSupport.create(txnId, scope, minEpoch, executeAtEpoch); } @Override - public long serializedSize(WaitUntilApplied waitUntilApplied, int version) + public long serializedSize(WaitUntilApplied waitUntilApplied, Version version) { - return CommandSerializers.txnId.serializedSize(waitUntilApplied.txnId, version) - + KeySerializers.participants.serializedSize(waitUntilApplied.scope, version) + return CommandSerializers.txnId.serializedSize(waitUntilApplied.txnId) + + KeySerializers.participants.serializedSize(waitUntilApplied.scope) + TypeSizes.sizeofUnsignedVInt(waitUntilApplied.minEpoch()) + TypeSizes.sizeofUnsignedVInt(waitUntilApplied.executeAtEpoch - waitUntilApplied.minEpoch()); } @@ -325,46 +325,46 @@ public class ReadDataSerializers public static final ReadDataSerializer stableThenRead = new ReadDataSerializer<>() { @Override - public void serialize(StableThenRead read, DataOutputPlus out, int version) throws IOException + public void serialize(StableThenRead read, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(read.txnId, out, version); - KeySerializers.participants.serialize(read.scope, out, version); - CommitSerializers.kind.serialize(read.kind, out, version); + CommandSerializers.txnId.serialize(read.txnId, out); + KeySerializers.participants.serialize(read.scope, out); + CommitSerializers.kind.serialize(read.kind, out); out.writeUnsignedVInt(read.minEpoch); ExecuteAtSerializer.serialize(read.txnId, read.executeAt, out); if (read.kind.withTxn != NoTxn) CommandSerializers.nullablePartialTxn.serialize(read.partialTxn, out, version); if (read.kind.withDeps == HasDeps) - DepsSerializers.partialDeps.serialize(read.partialDeps, out, version); + DepsSerializers.partialDeps.serialize(read.partialDeps, out); if (read.kind.withTxn == HasTxn) - KeySerializers.fullRoute.serialize(read.route, out, version); + KeySerializers.fullRoute.serialize(read.route, out); } @Override - public StableThenRead deserialize(DataInputPlus in, int version) throws IOException + public StableThenRead deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Participants scope = KeySerializers.participants.deserialize(in, version); - Commit.Kind kind = CommitSerializers.kind.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Participants scope = KeySerializers.participants.deserialize(in); + Commit.Kind kind = CommitSerializers.kind.deserialize(in); long minEpoch = in.readUnsignedVInt(); Timestamp executeAt = ExecuteAtSerializer.deserialize(txnId, in); PartialTxn partialTxn = kind.withTxn == NoTxn ? null : CommandSerializers.nullablePartialTxn.deserialize(in, version); - PartialDeps partialDeps = kind.withDeps == NoDeps ? null : DepsSerializers.partialDeps.deserialize(in, version); - FullRoute < ?> route = kind.withTxn == HasTxn ? KeySerializers.fullRoute.deserialize(in, version) : null; + PartialDeps partialDeps = kind.withDeps == NoDeps ? null : DepsSerializers.partialDeps.deserialize(in); + FullRoute < ?> route = kind.withTxn == HasTxn ? KeySerializers.fullRoute.deserialize(in) : null; return StableThenRead.SerializerSupport.create(txnId, scope, kind, minEpoch, executeAt, partialTxn, partialDeps, route); } @Override - public long serializedSize(StableThenRead read, int version) + public long serializedSize(StableThenRead read, Version version) { - return CommandSerializers.txnId.serializedSize(read.txnId, version) - + KeySerializers.participants.serializedSize(read.scope, version) - + CommitSerializers.kind.serializedSize(read.kind, version) + return CommandSerializers.txnId.serializedSize(read.txnId) + + KeySerializers.participants.serializedSize(read.scope) + + CommitSerializers.kind.serializedSize(read.kind) + TypeSizes.sizeofUnsignedVInt(read.minEpoch) + ExecuteAtSerializer.serializedSize(read.txnId, read.executeAt) + (read.kind.withTxn == NoTxn ? 0 : CommandSerializers.nullablePartialTxn.serializedSize(read.partialTxn, version)) - + (read.kind.withDeps != HasDeps ? 0 : DepsSerializers.partialDeps.serializedSize(read.partialDeps, version)) - + (read.kind.withTxn != HasTxn ? 0 : KeySerializers.fullRoute.serializedSize(read.route, version)); + + (read.kind.withDeps != HasDeps ? 0 : DepsSerializers.partialDeps.serializedSize(read.partialDeps)) + + (read.kind.withTxn != HasTxn ? 0 : KeySerializers.fullRoute.serializedSize(read.route)); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/RecoverySerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/RecoverySerializers.java index 7961c1aaa5..fcb680326d 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/RecoverySerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/RecoverySerializers.java @@ -41,7 +41,7 @@ import accord.primitives.Timestamp; import accord.primitives.TxnId; import accord.primitives.Writes; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; @@ -57,30 +57,30 @@ public class RecoverySerializers public static final IVersionedSerializer request = new WithUnsyncedSerializer() { @Override - public void serializeBody(BeginRecovery recover, DataOutputPlus out, int version) throws IOException + public void serializeBody(BeginRecovery recover, DataOutputPlus out, Version version) throws IOException { CommandSerializers.partialTxn.serialize(recover.partialTxn, out, version); - CommandSerializers.ballot.serialize(recover.ballot, out, version); - serializeNullable(recover.route, out, version, KeySerializers.fullRoute); + CommandSerializers.ballot.serialize(recover.ballot, out); + serializeNullable(recover.route, out, KeySerializers.fullRoute); out.writeUnsignedVInt(recover.executeAtOrTxnIdEpoch - recover.txnId.epoch()); } @Override - public BeginRecovery deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException + public BeginRecovery deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException { PartialTxn partialTxn = CommandSerializers.partialTxn.deserialize(in, version); - Ballot ballot = CommandSerializers.ballot.deserialize(in, version); - @Nullable FullRoute route = deserializeNullable(in, version, KeySerializers.fullRoute); + Ballot ballot = CommandSerializers.ballot.deserialize(in); + @Nullable FullRoute route = deserializeNullable(in, KeySerializers.fullRoute); long executeAtOrTxnIdEpoch = in.readUnsignedVInt32() + txnId.epoch(); return BeginRecovery.SerializationSupport.create(txnId, scope, waitForEpoch, minEpoch, partialTxn, ballot, route, executeAtOrTxnIdEpoch); } @Override - public long serializedBodySize(BeginRecovery recover, int version) + public long serializedBodySize(BeginRecovery recover, Version version) { return CommandSerializers.partialTxn.serializedSize(recover.partialTxn, version) - + CommandSerializers.ballot.serializedSize(recover.ballot, version) - + serializedNullableSize(recover.route, version, KeySerializers.fullRoute) + + CommandSerializers.ballot.serializedSize(recover.ballot) + + serializedNullableSize(recover.route, KeySerializers.fullRoute) + TypeSizes.sizeofUnsignedVInt(recover.executeAtOrTxnIdEpoch - recover.txnId.epoch()); } }; @@ -88,54 +88,54 @@ public class RecoverySerializers public static final IVersionedSerializer reply = new IVersionedSerializer() { final RecoverReply.Kind[] kinds = RecoverReply.Kind.values(); - void serializeNack(RecoverNack recoverNack, DataOutputPlus out, int version) throws IOException + void serializeNack(RecoverNack recoverNack, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.ballot.serialize(recoverNack.supersededBy, out, version); + CommandSerializers.ballot.serialize(recoverNack.supersededBy, out); } - void serializeOk(RecoverOk recoverOk, DataOutputPlus out, int version) throws IOException + void serializeOk(RecoverOk recoverOk, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(recoverOk.txnId, out, version); - CommandSerializers.status.serialize(recoverOk.status, out, version); - CommandSerializers.ballot.serialize(recoverOk.accepted, out, version); + CommandSerializers.txnId.serialize(recoverOk.txnId, out); + CommandSerializers.status.serialize(recoverOk.status, out); + CommandSerializers.ballot.serialize(recoverOk.accepted, out); ExecuteAtSerializer.serializeNullable(recoverOk.executeAt, out); - latestDeps.serialize(recoverOk.deps, out, version); - DepsSerializers.deps.serialize(recoverOk.earlierWait, out, version); - DepsSerializers.deps.serialize(recoverOk.earlierNoWait, out, version); - DepsSerializers.deps.serialize(recoverOk.laterCoordRejects, out, version); + latestDeps.serialize(recoverOk.deps, out); + DepsSerializers.deps.serialize(recoverOk.earlierWait, out); + DepsSerializers.deps.serialize(recoverOk.earlierNoWait, out); + DepsSerializers.deps.serialize(recoverOk.laterCoordRejects, out); out.writeBoolean(recoverOk.selfAcceptsFastPath); - KeySerializers.nullableParticipants.serialize(recoverOk.coordinatorAcceptsFastPath, out, version); + KeySerializers.nullableParticipants.serialize(recoverOk.coordinatorAcceptsFastPath, out); out.writeBoolean(recoverOk.supersedingRejects); CommandSerializers.nullableWrites.serialize(recoverOk.writes, out, version); } @Override - public void serialize(RecoverReply reply, DataOutputPlus out, int version) throws IOException + public void serialize(RecoverReply reply, DataOutputPlus out, Version version) throws IOException { out.writeByte(reply.kind().ordinal()); if (reply.kind() == Ok) serializeOk((RecoverOk) reply, out, version); else serializeNack((RecoverNack) reply, out, version); } - RecoverNack deserializeNack(RecoverReply.Kind kind, Ballot supersededBy, DataInputPlus in, int version) + RecoverNack deserializeNack(RecoverReply.Kind kind, Ballot supersededBy, DataInputPlus in, Version version) { return new RecoverNack(kind, supersededBy); } - RecoverOk deserializeOk(TxnId txnId, Status status, Ballot accepted, Timestamp executeAt, @Nonnull LatestDeps deps, Deps earlierWait, Deps earlierNoWait, Deps laterCoordRejects, boolean acceptsFastPath, @Nullable Participants coordinatorAcceptsFastPath, boolean rejectsFastPath, Writes writes, Result result, DataInputPlus in, int version) + RecoverOk deserializeOk(TxnId txnId, Status status, Ballot accepted, Timestamp executeAt, @Nonnull LatestDeps deps, Deps earlierWait, Deps earlierNoWait, Deps laterCoordRejects, boolean acceptsFastPath, @Nullable Participants coordinatorAcceptsFastPath, boolean rejectsFastPath, Writes writes, Result result, DataInputPlus in, Version version) { return new RecoverOk(txnId, status, accepted, executeAt, deps, earlierWait, earlierNoWait, laterCoordRejects, acceptsFastPath, coordinatorAcceptsFastPath, rejectsFastPath, writes, result); } @Override - public RecoverReply deserialize(DataInputPlus in, int version) throws IOException + public RecoverReply deserialize(DataInputPlus in, Version version) throws IOException { RecoverReply.Kind kind = kinds[in.readByte()]; if (kind != Ok) - return deserializeNack(kind, CommandSerializers.ballot.deserialize(in, version), in, version); + return deserializeNack(kind, CommandSerializers.ballot.deserialize(in), in, version); - TxnId id = CommandSerializers.txnId.deserialize(in, version); - Status status = CommandSerializers.status.deserialize(in, version); + TxnId id = CommandSerializers.txnId.deserialize(in); + Status status = CommandSerializers.status.deserialize(in); Result result = null; if (status == Status.PreApplied || status == Status.Applied || status == Status.Truncated) @@ -143,14 +143,14 @@ public class RecoverySerializers return deserializeOk(id, status, - CommandSerializers.ballot.deserialize(in, version), + CommandSerializers.ballot.deserialize(in), ExecuteAtSerializer.deserializeNullable(in), - latestDeps.deserialize(in, version), - DepsSerializers.deps.deserialize(in, version), - DepsSerializers.deps.deserialize(in, version), - DepsSerializers.deps.deserialize(in, version), + latestDeps.deserialize(in), + DepsSerializers.deps.deserialize(in), + DepsSerializers.deps.deserialize(in), + DepsSerializers.deps.deserialize(in), in.readBoolean(), - KeySerializers.nullableParticipants.deserialize(in, version), + KeySerializers.nullableParticipants.deserialize(in), in.readBoolean(), CommandSerializers.nullableWrites.deserialize(in, version), result, @@ -158,108 +158,108 @@ public class RecoverySerializers version); } - long serializedNackSize(RecoverNack recoverNack, int version) + long serializedNackSize(RecoverNack recoverNack, Version version) { - return CommandSerializers.ballot.serializedSize(recoverNack.supersededBy, version); + return CommandSerializers.ballot.serializedSize(recoverNack.supersededBy); } - long serializedOkSize(RecoverOk recoverOk, int version) + long serializedOkSize(RecoverOk recoverOk, Version version) { - long size = CommandSerializers.txnId.serializedSize(recoverOk.txnId, version); - size += CommandSerializers.status.serializedSize(recoverOk.status, version); - size += CommandSerializers.ballot.serializedSize(recoverOk.accepted, version); + long size = CommandSerializers.txnId.serializedSize(recoverOk.txnId); + size += CommandSerializers.status.serializedSize(recoverOk.status); + size += CommandSerializers.ballot.serializedSize(recoverOk.accepted); size += ExecuteAtSerializer.serializedNullableSize(recoverOk.executeAt); - size += latestDeps.serializedSize(recoverOk.deps, version); - size += DepsSerializers.deps.serializedSize(recoverOk.earlierWait, version); - size += DepsSerializers.deps.serializedSize(recoverOk.earlierNoWait, version); - size += DepsSerializers.deps.serializedSize(recoverOk.laterCoordRejects, version); + size += latestDeps.serializedSize(recoverOk.deps); + size += DepsSerializers.deps.serializedSize(recoverOk.earlierWait); + size += DepsSerializers.deps.serializedSize(recoverOk.earlierNoWait); + size += DepsSerializers.deps.serializedSize(recoverOk.laterCoordRejects); size += TypeSizes.sizeof(recoverOk.selfAcceptsFastPath); - size += KeySerializers.nullableParticipants.serializedSize(recoverOk.coordinatorAcceptsFastPath, version); + size += KeySerializers.nullableParticipants.serializedSize(recoverOk.coordinatorAcceptsFastPath); size += TypeSizes.sizeof(recoverOk.supersedingRejects); size += CommandSerializers.nullableWrites.serializedSize(recoverOk.writes, version); return size; } @Override - public long serializedSize(RecoverReply reply, int version) + public long serializedSize(RecoverReply reply, Version version) { return TypeSizes.BYTE_SIZE + (reply.kind() == Ok ? serializedOkSize((RecoverOk) reply, version) : serializedNackSize((RecoverNack) reply, version)); } }; - public static final IVersionedSerializer latestDeps = new IVersionedSerializer<>() + public static final UnversionedSerializer latestDeps = new UnversionedSerializer<>() { @Override - public void serialize(LatestDeps t, DataOutputPlus out, int version) throws IOException + public void serialize(LatestDeps t, DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(t.size()); for (int i = 0 ; i < t.size() ; ++i) { RoutingKey start = t.startAt(i); - KeySerializers.routingKey.serialize(start, out, version); + KeySerializers.routingKey.serialize(start, out); LatestDeps.LatestEntry e = t.valueAt(i); if (e == null) { - CommandSerializers.knownDeps.serialize(null, out, version); + CommandSerializers.knownDeps.serialize(null, out); } else { - CommandSerializers.knownDeps.serialize(e.known, out, version); - CommandSerializers.ballot.serialize(e.ballot, out, version); - DepsSerializers.nullableDeps.serialize(e.coordinatedDeps, out, version); - DepsSerializers.nullableDeps.serialize(e.localDeps, out, version); + CommandSerializers.knownDeps.serialize(e.known, out); + CommandSerializers.ballot.serialize(e.ballot, out); + DepsSerializers.nullableDeps.serialize(e.coordinatedDeps, out); + DepsSerializers.nullableDeps.serialize(e.localDeps, out); } } - KeySerializers.routingKey.serialize(t.startAt(t.size()), out, version); + KeySerializers.routingKey.serialize(t.startAt(t.size()), out); } @Override - public LatestDeps deserialize(DataInputPlus in, int version) throws IOException + public LatestDeps deserialize(DataInputPlus in) throws IOException { int size = in.readUnsignedVInt32(); RoutingKey[] starts = new RoutingKey[size + 1]; LatestDeps.LatestEntry[] values = new LatestDeps.LatestEntry[size]; for (int i = 0 ; i < size ; ++i) { - starts[i] = KeySerializers.routingKey.deserialize(in, version); - KnownDeps knownDeps = CommandSerializers.knownDeps.deserialize(in, version); + starts[i] = KeySerializers.routingKey.deserialize(in); + KnownDeps knownDeps = CommandSerializers.knownDeps.deserialize(in); if (knownDeps == null) continue; - Ballot ballot = CommandSerializers.ballot.deserialize(in, version); - Deps coordinatedDeps = DepsSerializers.nullableDeps.deserialize(in, version); - Deps localDeps = DepsSerializers.nullableDeps.deserialize(in, version); + Ballot ballot = CommandSerializers.ballot.deserialize(in); + Deps coordinatedDeps = DepsSerializers.nullableDeps.deserialize(in); + Deps localDeps = DepsSerializers.nullableDeps.deserialize(in); values[i] = new LatestDeps.LatestEntry(knownDeps, ballot, coordinatedDeps, localDeps); } - starts[size] = KeySerializers.routingKey.deserialize(in, version); + starts[size] = KeySerializers.routingKey.deserialize(in); return LatestDeps.SerializerSupport.create(true, starts, values); } @Override - public long serializedSize(LatestDeps t, int version) + public long serializedSize(LatestDeps t) { long size = 0; size += TypeSizes.sizeofUnsignedVInt(t.size()); for (int i = 0 ; i < t.size() ; ++i) { RoutingKey start = t.startAt(i); - size += KeySerializers.routingKey.serializedSize(start, version); + size += KeySerializers.routingKey.serializedSize(start); LatestDeps.LatestEntry e = t.valueAt(i); if (e == null) { - size += CommandSerializers.knownDeps.serializedSize(null, version); + size += CommandSerializers.knownDeps.serializedSize(null); } else { - size += CommandSerializers.knownDeps.serializedSize(e.known, version); - size += CommandSerializers.ballot.serializedSize(e.ballot, version); - size += DepsSerializers.nullableDeps.serializedSize(e.coordinatedDeps, version); - size += DepsSerializers.nullableDeps.serializedSize(e.localDeps, version); + size += CommandSerializers.knownDeps.serializedSize(e.known); + size += CommandSerializers.ballot.serializedSize(e.ballot); + size += DepsSerializers.nullableDeps.serializedSize(e.coordinatedDeps); + size += DepsSerializers.nullableDeps.serializedSize(e.localDeps); } } - size += KeySerializers.routingKey.serializedSize(t.startAt(t.size()), version); + size += KeySerializers.routingKey.serializedSize(t.startAt(t.size())); return size; } }; diff --git a/src/java/org/apache/cassandra/service/accord/serializers/ResultSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/ResultSerializers.java index 53b8d93e3f..0101efa04a 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/ResultSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/ResultSerializers.java @@ -20,7 +20,7 @@ package org.apache.cassandra.service.accord.serializers; import accord.api.Result; import accord.primitives.ProgressToken; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -36,15 +36,15 @@ public class ResultSerializers } }; - public static final IVersionedSerializer result = new IVersionedSerializer<>() + public static final UnversionedSerializer result = new UnversionedSerializer<>() { - public void serialize(Result t, DataOutputPlus out, int version) { } - public Result deserialize(DataInputPlus in, int version) + public void serialize(Result t, DataOutputPlus out) { } + public Result deserialize(DataInputPlus in) { return APPLIED; } - public long serializedSize(Result t, int version) + public long serializedSize(Result t) { return 0; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/SetDurableSerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/SetDurableSerializers.java index 76c192f4b5..60dbbc3c88 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/SetDurableSerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/SetDurableSerializers.java @@ -26,86 +26,86 @@ import accord.primitives.FullRoute; import accord.primitives.SyncPoint; import accord.primitives.Timestamp; import accord.primitives.TxnId; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.serializers.CommandSerializers.ExecuteAtSerializer; public class SetDurableSerializers { - public static final IVersionedSerializer shardDurable = new IVersionedSerializer<>() + public static final UnversionedSerializer shardDurable = new UnversionedSerializer<>() { @Override - public void serialize(SetShardDurable msg, DataOutputPlus out, int version) throws IOException + public void serialize(SetShardDurable msg, DataOutputPlus out) throws IOException { - syncPoint.serialize(msg.exclusiveSyncPoint, out, version); - CommandSerializers.durability.serialize(msg.durability, out, version); + syncPoint.serialize(msg.exclusiveSyncPoint, out); + CommandSerializers.durability.serialize(msg.durability, out); } @Override - public SetShardDurable deserialize(DataInputPlus in, int version) throws IOException + public SetShardDurable deserialize(DataInputPlus in) throws IOException { - return new SetShardDurable(syncPoint.deserialize(in, version), - CommandSerializers.durability.deserialize(in, version)); + return new SetShardDurable(syncPoint.deserialize(in), + CommandSerializers.durability.deserialize(in)); } @Override - public long serializedSize(SetShardDurable msg, int version) + public long serializedSize(SetShardDurable msg) { - return syncPoint.serializedSize(msg.exclusiveSyncPoint, version) - + CommandSerializers.durability.serializedSize(msg.durability, version); + return syncPoint.serializedSize(msg.exclusiveSyncPoint) + + CommandSerializers.durability.serializedSize(msg.durability); } }; - public static final IVersionedSerializer globallyDurable = new IVersionedSerializer<>() + public static final UnversionedSerializer globallyDurable = new UnversionedSerializer<>() { @Override - public void serialize(SetGloballyDurable msg, DataOutputPlus out, int version) throws IOException + public void serialize(SetGloballyDurable msg, DataOutputPlus out) throws IOException { - CommandStoreSerializers.durableBefore.serialize(msg.durableBefore, out, version); + CommandStoreSerializers.durableBefore.serialize(msg.durableBefore, out); } @Override - public SetGloballyDurable deserialize(DataInputPlus in, int version) throws IOException + public SetGloballyDurable deserialize(DataInputPlus in) throws IOException { - return new SetGloballyDurable(CommandStoreSerializers.durableBefore.deserialize(in, version)); + return new SetGloballyDurable(CommandStoreSerializers.durableBefore.deserialize(in)); } @Override - public long serializedSize(SetGloballyDurable msg, int version) + public long serializedSize(SetGloballyDurable msg) { - return CommandStoreSerializers.durableBefore.serializedSize(msg.durableBefore, version); + return CommandStoreSerializers.durableBefore.serializedSize(msg.durableBefore); } }; - public static final IVersionedSerializer syncPoint = new IVersionedSerializer<>() + public static final UnversionedSerializer syncPoint = new UnversionedSerializer<>() { @Override - public void serialize(SyncPoint sp, DataOutputPlus out, int version) throws IOException + public void serialize(SyncPoint sp, DataOutputPlus out) throws IOException { - CommandSerializers.txnId.serialize(sp.syncId, out, version); + CommandSerializers.txnId.serialize(sp.syncId, out); ExecuteAtSerializer.serialize(sp.syncId, sp.executeAt, out); - DepsSerializers.deps.serialize(sp.waitFor, out, version); - KeySerializers.fullRoute.serialize(sp.route, out, version); + DepsSerializers.deps.serialize(sp.waitFor, out); + KeySerializers.fullRoute.serialize(sp.route, out); } @Override - public SyncPoint deserialize(DataInputPlus in, int version) throws IOException + public SyncPoint deserialize(DataInputPlus in) throws IOException { - TxnId syncId = CommandSerializers.txnId.deserialize(in, version); + TxnId syncId = CommandSerializers.txnId.deserialize(in); Timestamp executeAt = ExecuteAtSerializer.deserialize(syncId, in); - Deps waitFor = DepsSerializers.deps.deserialize(in, version); - FullRoute route = KeySerializers.fullRoute.deserialize(in, version); + Deps waitFor = DepsSerializers.deps.deserialize(in); + FullRoute route = KeySerializers.fullRoute.deserialize(in); return SyncPoint.SerializationSupport.construct(syncId, executeAt, waitFor, route); } @Override - public long serializedSize(SyncPoint sp, int version) + public long serializedSize(SyncPoint sp) { - return CommandSerializers.txnId.serializedSize(sp.syncId, version) + return CommandSerializers.txnId.serializedSize(sp.syncId) + ExecuteAtSerializer.serializedSize(sp.syncId, sp.executeAt) - + DepsSerializers.deps.serializedSize(sp.waitFor, version) - + KeySerializers.fullRoute.serializedSize(sp.route, version); + + DepsSerializers.deps.serializedSize(sp.waitFor) + + KeySerializers.fullRoute.serializedSize(sp.route); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/serializers/TopologySerializers.java b/src/java/org/apache/cassandra/service/accord/serializers/TopologySerializers.java index 91d5bf1bdf..0fe912335c 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/TopologySerializers.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/TopologySerializers.java @@ -29,12 +29,10 @@ import accord.utils.SortedArrays.SortedArrayList; import accord.utils.TinyEnumSet; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.marshal.ValueAccessor; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.TokenRange; -import org.apache.cassandra.tcm.serialization.MetadataSerializer; -import org.apache.cassandra.tcm.serialization.Version; import org.apache.cassandra.utils.ArraySerializers; import org.apache.cassandra.utils.CollectionSerializers; @@ -43,27 +41,16 @@ public class TopologySerializers private TopologySerializers() {} public static final NodeIdSerializer nodeId = new NodeIdSerializer(); - public static class NodeIdSerializer implements IVersionedSerializer, MetadataSerializer + public static class NodeIdSerializer implements UnversionedSerializer { private NodeIdSerializer() {} - public static void serialize(Node.Id id, DataOutputPlus out) throws IOException + @Override + public void serialize(Node.Id id, DataOutputPlus out) throws IOException { out.writeInt(id.id); } - @Override - public void serialize(Node.Id id, DataOutputPlus out, int version) throws IOException - { - serialize(id, out); - } - - @Override - public void serialize(Node.Id id, DataOutputPlus out, Version version) throws IOException - { - serialize(id, out); - } - public int serialize(Node.Id id, V dst, ValueAccessor accessor, int offset) { return accessor.putInt(dst, offset, id.id); @@ -74,23 +61,12 @@ public class TopologySerializers out.putInt(id.id); } - public static Node.Id deserialize(DataInputPlus in) throws IOException + @Override + public Node.Id deserialize(DataInputPlus in) throws IOException { return new Node.Id(in.readInt()); } - @Override - public Node.Id deserialize(DataInputPlus in, int version) throws IOException - { - return deserialize(in); - } - - @Override - public Node.Id deserialize(DataInputPlus in, Version version) throws IOException - { - return deserialize(in); - } - public Node.Id deserialize(V src, ValueAccessor accessor, int offset) { return new Node.Id(accessor.getInt(src, offset)); @@ -101,96 +77,85 @@ public class TopologySerializers return new Node.Id(src.getInt(position)); } - public int serializedSize() + @Override + public long serializedSize(Node.Id id) { return TypeSizes.INT_SIZE; // id.id } + } - @Override - public long serializedSize(Node.Id id, int version) - { - return serializedSize(); - } + public static final UnversionedSerializer shard = new ShardSerializer((UnversionedSerializer) + (UnversionedSerializer) + TokenRange.serializer); - @Override - public long serializedSize(Node.Id t, Version version) - { - return serializedSize(); - } - }; - - public static final IVersionedSerializer shard = new ShardSerializer((IVersionedSerializer) - (IVersionedSerializer) - TokenRange.serializer); - - public static class ShardSerializer implements IVersionedSerializer + public static class ShardSerializer implements UnversionedSerializer { - protected IVersionedSerializer range; + protected UnversionedSerializer range; - public ShardSerializer(IVersionedSerializer range) + public ShardSerializer(UnversionedSerializer range) { this.range = range; } @Override - public void serialize(Shard shard, DataOutputPlus out, int version) throws IOException + public void serialize(Shard shard, DataOutputPlus out) throws IOException { - range.serialize(shard.range, out, version); - CollectionSerializers.serializeList(shard.nodes, out, version, nodeId); - CollectionSerializers.serializeList(shard.notInFastPath, out, version, nodeId); - CollectionSerializers.serializeList(shard.joining, out, version, nodeId); + range.serialize(shard.range, out); + CollectionSerializers.serializeList(shard.nodes, out, nodeId); + CollectionSerializers.serializeList(shard.notInFastPath, out, nodeId); + CollectionSerializers.serializeList(shard.joining, out, nodeId); out.writeUnsignedVInt32(shard.flags().bitset()); } @Override - public Shard deserialize(DataInputPlus in, int version) throws IOException + public Shard deserialize(DataInputPlus in) throws IOException { - Range range = ShardSerializer.this.range.deserialize(in, version); - SortedArrayList nodes = CollectionSerializers.deserializeSortedArrayList(in, version, nodeId, Node.Id[]::new); - SortedArrayList notInFastPath = CollectionSerializers.deserializeSortedArrayList(in, version, nodeId, Node.Id[]::new); - SortedArrayList joining = CollectionSerializers.deserializeSortedArrayList(in, version, nodeId, Node.Id[]::new); + Range range = ShardSerializer.this.range.deserialize(in); + SortedArrayList nodes = CollectionSerializers.deserializeSortedArrayList(in, nodeId, Node.Id[]::new); + SortedArrayList notInFastPath = CollectionSerializers.deserializeSortedArrayList(in, nodeId, Node.Id[]::new); + SortedArrayList joining = CollectionSerializers.deserializeSortedArrayList(in, nodeId, Node.Id[]::new); int flags = in.readUnsignedVInt32(); return Shard.SerializerSupport.create(range, nodes, notInFastPath, joining, new TinyEnumSet<>(flags)); } @Override - public long serializedSize(Shard shard, int version) + public long serializedSize(Shard shard) { - long size = range.serializedSize(shard.range, version); - size += CollectionSerializers.serializedListSize(shard.nodes, version, nodeId); - size += CollectionSerializers.serializedListSize(shard.notInFastPath, version, nodeId); - size += CollectionSerializers.serializedListSize(shard.joining, version, nodeId); + long size = range.serializedSize(shard.range); + size += CollectionSerializers.serializedListSize(shard.nodes, nodeId); + size += CollectionSerializers.serializedListSize(shard.notInFastPath, nodeId); + size += CollectionSerializers.serializedListSize(shard.joining, nodeId); size += TypeSizes.sizeofUnsignedVInt(shard.flags().bitset()); return size; } - }; + } - public static final IVersionedSerializer topology = new IVersionedSerializer<>() + public static final UnversionedSerializer topology = new UnversionedSerializer<>() { @Override - public void serialize(Topology topology, DataOutputPlus out, int version) throws IOException + public void serialize(Topology topology, DataOutputPlus out) throws IOException { out.writeLong(topology.epoch()); - ArraySerializers.serializeArray(topology.unsafeGetShards(), out, version, shard); - CollectionSerializers.serializeCollection(topology.staleIds(), out, version, TopologySerializers.nodeId); + CollectionSerializers.serializeList(topology.shards(), out, shard); + CollectionSerializers.serializeCollection(topology.staleIds(), out, TopologySerializers.nodeId); } @Override - public Topology deserialize(DataInputPlus in, int version) throws IOException + public Topology deserialize(DataInputPlus in) throws IOException { long epoch = in.readLong(); - Shard[] shards = ArraySerializers.deserializeArray(in, version, shard, Shard[]::new); - SortedArrayList staleIds = CollectionSerializers.deserializeSortedArrayList(in, version, TopologySerializers.nodeId, Node.Id[]::new); + Shard[] shards = ArraySerializers.deserializeArray(in, shard, Shard[]::new); + SortedArrayList staleIds = CollectionSerializers.deserializeSortedArrayList(in, TopologySerializers.nodeId, Node.Id[]::new); return new Topology(epoch, staleIds, shards); } @Override - public long serializedSize(Topology topology, int version) + public long serializedSize(Topology topology) { long size = 0; size += TypeSizes.LONG_SIZE; // epoch - size += ArraySerializers.serializedArraySize(topology.unsafeGetShards(), version, shard); - size += CollectionSerializers.serializedCollectionSize(topology.staleIds(), version, TopologySerializers.nodeId); + size += CollectionSerializers.serializedListSize(topology.shards(), shard); + size += CollectionSerializers.serializedCollectionSize(topology.staleIds(), TopologySerializers.nodeId); return size; } }; diff --git a/src/java/org/apache/cassandra/service/accord/serializers/TxnRequestSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/TxnRequestSerializer.java index 6dc5f9e564..800a491b6d 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/TxnRequestSerializer.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/TxnRequestSerializer.java @@ -24,51 +24,50 @@ import accord.messages.TxnRequest; import accord.primitives.Route; import accord.primitives.TxnId; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; public abstract class TxnRequestSerializer> implements IVersionedSerializer { - void serializeHeader(T msg, DataOutputPlus out, int version) throws IOException + void serializeHeader(T msg, DataOutputPlus out, Version version) throws IOException { - CommandSerializers.txnId.serialize(msg.txnId, out, version); - KeySerializers.route.serialize(msg.scope, out, version); + CommandSerializers.txnId.serialize(msg.txnId, out); + KeySerializers.route.serialize(msg.scope, out); out.writeUnsignedVInt(msg.waitForEpoch); } - public abstract void serializeBody(T msg, DataOutputPlus out, int version) throws IOException; + public abstract void serializeBody(T msg, DataOutputPlus out, Version version) throws IOException; @Override - public final void serialize(T msg, DataOutputPlus out, int version) throws IOException + public final void serialize(T msg, DataOutputPlus out, Version version) throws IOException { serializeHeader(msg, out, version); serializeBody(msg, out, version); } - public abstract T deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch) throws IOException; + public abstract T deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch) throws IOException; @Override - public final T deserialize(DataInputPlus in, int version) throws IOException + public final T deserialize(DataInputPlus in, Version version) throws IOException { - TxnId txnId = CommandSerializers.txnId.deserialize(in, version); - Route scope = KeySerializers.route.deserialize(in, version); + TxnId txnId = CommandSerializers.txnId.deserialize(in); + Route scope = KeySerializers.route.deserialize(in); // TODO: there should be a base epoch long waitForEpoch = in.readUnsignedVInt(); return deserializeBody(in, version, txnId, scope, waitForEpoch); } - long serializedHeaderSize(T msg, int version) + long serializedHeaderSize(T msg, Version version) { - return CommandSerializers.txnId.serializedSize(msg.txnId, version) - + KeySerializers.route.serializedSize(msg.scope(), version) + + return CommandSerializers.txnId.serializedSize(msg.txnId) + + KeySerializers.route.serializedSize(msg.scope()) + TypeSizes.sizeofUnsignedVInt(msg.waitForEpoch); } - public abstract long serializedBodySize(T msg, int version); + public abstract long serializedBodySize(T msg, Version version); @Override - public final long serializedSize(T msg, int version) + public final long serializedSize(T msg, Version version) { return serializedHeaderSize(msg, version) + serializedBodySize(msg, version); } @@ -76,23 +75,23 @@ public abstract class TxnRequestSerializer> implements I public static abstract class WithUnsyncedSerializer> extends TxnRequestSerializer { @Override - void serializeHeader(T msg, DataOutputPlus out, int version) throws IOException + void serializeHeader(T msg, DataOutputPlus out, Version version) throws IOException { super.serializeHeader(msg, out, version); out.writeUnsignedVInt(msg.minEpoch); } - public abstract T deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException; + public abstract T deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch, long minEpoch) throws IOException; @Override - public final T deserializeBody(DataInputPlus in, int version, TxnId txnId, Route scope, long waitForEpoch) throws IOException + public final T deserializeBody(DataInputPlus in, Version version, TxnId txnId, Route scope, long waitForEpoch) throws IOException { long minEpoch = in.readUnsignedVInt(); return deserializeBody(in, version, txnId, scope, waitForEpoch, minEpoch); } @Override - long serializedHeaderSize(T msg, int version) + long serializedHeaderSize(T msg, Version version) { long size = super.serializedHeaderSize(msg, version); size += TypeSizes.sizeofUnsignedVInt(msg.minEpoch); diff --git a/src/java/org/apache/cassandra/service/accord/serializers/Version.java b/src/java/org/apache/cassandra/service/accord/serializers/Version.java new file mode 100644 index 0000000000..45dfa09412 --- /dev/null +++ b/src/java/org/apache/cassandra/service/accord/serializers/Version.java @@ -0,0 +1,134 @@ +/* + * 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.service.accord.serializers; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.cassandra.db.TypeSizes; +import org.apache.cassandra.io.MessageVersionProvider; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.net.MessagingService; + +public enum Version implements MessageVersionProvider +{ + // If MessagingService version bumps, this mapping does not need to be updated; only updates needed are those that + // include accord serializer changes. + V1(1, MessagingService.Version.VERSION_51); + + public static final Version LATEST = Version.V1; + /** + * Version that should be used for disk serialization where downgrade may be possible. + * + * As of this writing only 1 version exists, so this is the same as LATEST... Once v2 comes into the picture we need this version to be the oldest version needed for downgrade... If you upgrade from 5.1 to 5.2 (assuming this adds a v2) you need a version that works with 5.1 here. + */ + public static final Version DOWNGRADE_SAFE_VERSION = Version.V1; + + /** + * Version that should be used for messaging serialization where mixed versions may be possible. + * + * As of this writing only 1 version exists, so this is the same as LATEST... Once v2 comes into the picture we need this version to be the oldest version needed for downgrade... If you upgrade from 5.1 to 5.2 (assuming this adds a v2) you need a version that works with 5.1 here. + */ + public static final Version CLUSTER_SAFE_VERSION = Version.V1; + + /** + * Version number used in the serialization protocol. This is not the same as the messaging version, and is localized to this class. + */ + public final int version; + /** + * For the accord versioned serializers they sometimes need to access existing messaging serializers, in these cases an agreed messaging version is required and can not be plumbed directly from the messaging layer. + * + * @see #messageVersion() + */ + private final MessagingService.Version messagingVersion; + + Version(int version, MessagingService.Version messagingVersion) + { + this.version = version; + this.messagingVersion = messagingVersion; + } + + public static Version fromVersion(int version) + { + switch (version) + { + case 1: return V1; + default: + throw new IllegalArgumentException("Unknown version: " + version); + } + } + + public static Version findBestMatchForMessagingVersion(int messagingVersion) + { + Version[] versions = values(); + for (int i = versions.length - 1; i >= 0; i--) + { + Version v = versions[i]; + // If network version bumped (12 to 13), the accord serializers may not have been changed; use the largest + // version smaller than or equal to this version + if (v.messageVersion() <= messagingVersion) + return v; + } + throw new IllegalArgumentException("Attempted to use message version " + messagingVersion + " which is smaller than " + versions[0] + " can handle (" + versions[0].messageVersion() + ")"); + } + + @Override + public int messageVersion() + { + return messagingVersion.value; + } + + public List greaterThanOrEqual() + { + Version[] all = Version.values(); + if (ordinal() == all.length - 1) + return Collections.singletonList(this); + List values = new ArrayList<>(all.length - ordinal()); + for (int i = ordinal(); i < all.length; i++) + values.add(all[i]); + return values; + } + + public enum Serializer implements UnversionedSerializer + { + instance; + + @Override + public void serialize(Version t, DataOutputPlus out) throws IOException + { + out.writeUnsignedVInt32(t.version); + } + + @Override + public Version deserialize(DataInputPlus in) throws IOException + { + return Version.fromVersion(in.readUnsignedVInt32()); + } + + @Override + public long serializedSize(Version t) + { + return TypeSizes.sizeofUnsignedVInt(t.version); + } + } +} diff --git a/src/java/org/apache/cassandra/service/accord/serializers/WaitingOnSerializer.java b/src/java/org/apache/cassandra/service/accord/serializers/WaitingOnSerializer.java index 2af8fd3b39..af7e5d66bb 100644 --- a/src/java/org/apache/cassandra/service/accord/serializers/WaitingOnSerializer.java +++ b/src/java/org/apache/cassandra/service/accord/serializers/WaitingOnSerializer.java @@ -86,7 +86,7 @@ public class WaitingOnSerializer return result; } - public void reserialize(DataOutputPlus out, int version) throws IOException + public void reserialize(DataOutputPlus out) throws IOException { out.writeUnsignedVInt32(waitingOnLength); serialize(waitingOnLength, waitingOn, out); diff --git a/src/java/org/apache/cassandra/service/accord/txn/AbstractSerialized.java b/src/java/org/apache/cassandra/service/accord/txn/AbstractSerialized.java index 85e90132ac..3f8a49cf34 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/AbstractSerialized.java +++ b/src/java/org/apache/cassandra/service/accord/txn/AbstractSerialized.java @@ -20,11 +20,15 @@ package org.apache.cassandra.service.accord.txn; import java.nio.ByteBuffer; import java.util.Objects; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.service.accord.AccordSerializers; +import accord.utils.Invariants; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; +import org.apache.cassandra.utils.ByteBufferUtil; +import org.apache.cassandra.utils.ObjectSizes; /** * Item that is serialized by default @@ -32,25 +36,40 @@ import org.apache.cassandra.service.accord.AccordSerializers; @NotThreadSafe public abstract class AbstractSerialized { + private static final long EMPTY = ObjectSizes.measure(new AbstractSerialized(null, null) { + @Override + protected IVersionedSerializer serializer() + { + throw new AssertionError(); + } + }); + public final Version version; private @Nullable final ByteBuffer bytes; - private @Nullable T memoized = null; + private transient @Nullable T memoized = null; - public AbstractSerialized(@Nullable ByteBuffer bytes) + public AbstractSerialized(@Nullable ByteBuffer bytes, Version version) { + this.version = version; this.bytes = bytes; } - public AbstractSerialized(@Nullable T value) + public AbstractSerialized(T value) { - this.bytes = value != null ? AccordSerializers.serialize(value, serializer()) : null; + this.version = Version.LATEST; + this.bytes = serializer().serializeUnchecked(Invariants.nonNull(value), version); this.memoized = value; } + public long estimatedSizeOnHeap() + { + return EMPTY + ByteBufferUtil.estimatedSizeOnHeap(bytes); + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (o == null || !(o instanceof AbstractSerialized)) return false; AbstractSerialized that = (AbstractSerialized) o; @@ -66,16 +85,22 @@ public abstract class AbstractSerialized @Override public String toString() { - return get().toString(); + return Objects.toString(get()); } protected abstract IVersionedSerializer serializer(); + protected boolean isNull() + { + return bytes == null; + } + + @Nullable protected T get() { T result = memoized; if (result == null && bytes != null) - memoized = result = AccordSerializers.deserialize(bytes, serializer()); + memoized = result = serializer().deserializeUnchecked(bytes, version); return result; } @@ -84,8 +109,42 @@ public abstract class AbstractSerialized memoized = null; } - protected ByteBuffer bytes() + @Nullable + protected ByteBuffer unsafeBytes() { return bytes; } + + @Nonnull + protected ByteBuffer bytes(Version target) + { + Invariants.nonNull(bytes); + if (version == target) + return bytes; + return serializer().serializeUnchecked(get(), target); + } + + public static AbstractSerialized of(IVersionedSerializer serializer, T value) + { + return new AbstractSerialized(value) + { + @Override + protected IVersionedSerializer serializer() + { + return serializer; + } + }; + } + + public static AbstractSerialized fromBytes(IVersionedSerializer serializer, ByteBuffer bytes, Version version) + { + return new AbstractSerialized(bytes, version) + { + @Override + protected IVersionedSerializer serializer() + { + return serializer; + } + }; + } } diff --git a/src/java/org/apache/cassandra/service/accord/txn/AccordUpdate.java b/src/java/org/apache/cassandra/service/accord/txn/AccordUpdate.java index ae63f9d26e..6a04485ab0 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/AccordUpdate.java +++ b/src/java/org/apache/cassandra/service/accord/txn/AccordUpdate.java @@ -24,9 +24,10 @@ import javax.annotation.Nullable; import accord.api.Data; import accord.api.Update; import org.apache.cassandra.db.ConsistencyLevel; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; public abstract class AccordUpdate implements Update { @@ -78,9 +79,12 @@ public abstract class AccordUpdate implements Update public interface AccordUpdateSerializer extends IVersionedSerializer { - void serialize(T update, DataOutputPlus out, int version) throws IOException; - T deserialize(DataInputPlus in, int version) throws IOException; - long serializedSize(T update, int version); + @Override + void serialize(T update, DataOutputPlus out, Version version) throws IOException; + @Override + T deserialize(DataInputPlus in, Version version) throws IOException; + @Override + long serializedSize(T update, Version version); } private static AccordUpdateSerializer serializerFor(AccordUpdate toSerialize) @@ -104,21 +108,21 @@ public abstract class AccordUpdate implements Update public static final AccordUpdateSerializer serializer = new AccordUpdateSerializer() { @Override - public void serialize(AccordUpdate update, DataOutputPlus out, int version) throws IOException + public void serialize(AccordUpdate update, DataOutputPlus out, Version version) throws IOException { out.writeByte(update.kind().val); serializerFor(update).serialize(update, out, version); } @Override - public AccordUpdate deserialize(DataInputPlus in, int version) throws IOException + public AccordUpdate deserialize(DataInputPlus in, Version version) throws IOException { Kind kind = Kind.valueOf(in.readByte()); return serializerFor(kind).deserialize(in, version); } @Override - public long serializedSize(AccordUpdate update, int version) + public long serializedSize(AccordUpdate update, Version version) { return 1 + serializerFor(update).serializedSize(update, version); } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnCondition.java b/src/java/org/apache/cassandra/service/accord/txn/TxnCondition.java index c3780502be..93431abac1 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnCondition.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnCondition.java @@ -43,10 +43,11 @@ import org.apache.cassandra.db.rows.Cell; import org.apache.cassandra.db.rows.ColumnData; import org.apache.cassandra.db.rows.ComplexColumnData; import org.apache.cassandra.db.rows.Row; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.ColumnMetadata; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.transport.ProtocolVersion; import org.apache.cassandra.utils.ByteBufferUtil; @@ -64,9 +65,9 @@ public abstract class TxnCondition { private interface ConditionSerializer { - void serialize(T condition, DataOutputPlus out, int version) throws IOException; - T deserialize(DataInputPlus in, int version, Kind kind) throws IOException; - long serializedSize(T condition, int version); + void serialize(T condition, DataOutputPlus out, Version version) throws IOException; + T deserialize(DataInputPlus in, Version version, Kind kind) throws IOException; + long serializedSize(T condition, Version version); } public enum Kind @@ -176,11 +177,11 @@ public abstract class TxnCondition private static final ConditionSerializer serializer = new ConditionSerializer() { @Override - public void serialize(None condition, DataOutputPlus out, int version) {} + public void serialize(None condition, DataOutputPlus out, Version version) {} @Override - public None deserialize(DataInputPlus in, int version, Kind kind) { return instance; } + public None deserialize(DataInputPlus in, Version version, Kind kind) { return instance; } @Override - public long serializedSize(None condition, int version) { return 0; } + public long serializedSize(None condition, Version version) { return 0; } }; } @@ -294,26 +295,27 @@ public abstract class TxnCondition private static final ConditionSerializer serializer = new ConditionSerializer() { @Override - public void serialize(Exists condition, DataOutputPlus out, int version) throws IOException + public void serialize(Exists condition, DataOutputPlus out, Version version) throws IOException { TxnReference.serializer.serialize(condition.reference, out, version); } @Override - public Exists deserialize(DataInputPlus in, int version, Kind kind) throws IOException + public Exists deserialize(DataInputPlus in, Version version, Kind kind) throws IOException { return new Exists(TxnReference.serializer.deserialize(in, version), kind); } @Override - public long serializedSize(Exists condition, int version) + public long serializedSize(Exists condition, Version version) { return TxnReference.serializer.serializedSize(condition.reference, version); } }; } - public static class ColumnConditionsAdapter extends TxnCondition { + public static class ColumnConditionsAdapter extends TxnCondition + { @Nonnull public final Collection bounds; @@ -346,25 +348,25 @@ public abstract class TxnCondition private static final ConditionSerializer serializer = new ConditionSerializer() { @Override - public void serialize(ColumnConditionsAdapter condition, DataOutputPlus out, int version) throws IOException + public void serialize(ColumnConditionsAdapter condition, DataOutputPlus out, Version version) throws IOException { - clusteringSerializer.serialize(condition.clustering, out, version); - serializeCollection(condition.bounds, out, version, Bound.serializer); + clusteringSerializer.serialize(condition.clustering, out); + serializeCollection(condition.bounds, out, Bound.serializer); } @Override - public ColumnConditionsAdapter deserialize(DataInputPlus in, int version, Kind ignored) throws IOException + public ColumnConditionsAdapter deserialize(DataInputPlus in, Version version, Kind ignored) throws IOException { - Clustering clustering = clusteringSerializer.deserialize(in, version); - List bounds = deserializeList(in, version, Bound.serializer); + Clustering clustering = clusteringSerializer.deserialize(in); + List bounds = deserializeList(in, Bound.serializer); return new ColumnConditionsAdapter(clustering, bounds); } @Override - public long serializedSize(ColumnConditionsAdapter condition, int version) + public long serializedSize(ColumnConditionsAdapter condition, Version version) { - return clusteringSerializer.serializedSize(condition.clustering, version) - + serializedCollectionSize(condition.bounds, version, Bound.serializer); + return clusteringSerializer.serializedSize(condition.clustering) + + serializedCollectionSize(condition.bounds, Bound.serializer); } }; } @@ -458,7 +460,7 @@ public abstract class TxnCondition private static final ConditionSerializer serializer = new ConditionSerializer<>() { @Override - public void serialize(Value condition, DataOutputPlus out, int version) throws IOException + public void serialize(Value condition, DataOutputPlus out, Version version) throws IOException { TxnReference.serializer.serialize(condition.reference, out, version); ByteBufferUtil.writeWithVIntLength(condition.value, out); @@ -466,7 +468,7 @@ public abstract class TxnCondition } @Override - public Value deserialize(DataInputPlus in, int version, Kind kind) throws IOException + public Value deserialize(DataInputPlus in, Version version, Kind kind) throws IOException { TxnReference reference = TxnReference.serializer.deserialize(in, version); ByteBuffer value = ByteBufferUtil.readWithVIntLength(in); @@ -475,7 +477,7 @@ public abstract class TxnCondition } @Override - public long serializedSize(Value condition, int version) + public long serializedSize(Value condition, Version version) { long size = 0; size += TxnReference.serializer.serializedSize(condition.reference, version); @@ -538,19 +540,19 @@ public abstract class TxnCondition private static final ConditionSerializer serializer = new ConditionSerializer() { @Override - public void serialize(BooleanGroup condition, DataOutputPlus out, int version) throws IOException + public void serialize(BooleanGroup condition, DataOutputPlus out, Version version) throws IOException { serializeList(condition.conditions, out, version, TxnCondition.serializer); } @Override - public BooleanGroup deserialize(DataInputPlus in, int version, Kind kind) throws IOException + public BooleanGroup deserialize(DataInputPlus in, Version version, Kind kind) throws IOException { return new BooleanGroup(kind, deserializeList(in, version, TxnCondition.serializer)); } @Override - public long serializedSize(BooleanGroup condition, int version) + public long serializedSize(BooleanGroup condition, Version version) { return serializedListSize(condition.conditions, version, TxnCondition.serializer); } @@ -561,14 +563,14 @@ public abstract class TxnCondition { @SuppressWarnings("unchecked") @Override - public void serialize(TxnCondition condition, DataOutputPlus out, int version) throws IOException + public void serialize(TxnCondition condition, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt32(condition.kind.ordinal()); condition.kind.serializer().serialize(condition, out, version); } @Override - public TxnCondition deserialize(DataInputPlus in, int version) throws IOException + public TxnCondition deserialize(DataInputPlus in, Version version) throws IOException { Kind kind = Kind.values()[in.readUnsignedVInt32()]; return kind.serializer().deserialize(in, version, kind); @@ -576,9 +578,10 @@ public abstract class TxnCondition @SuppressWarnings("unchecked") @Override - public long serializedSize(TxnCondition condition, int version) + public long serializedSize(TxnCondition condition, Version version) { - return TypeSizes.sizeofUnsignedVInt(condition.kind.ordinal()) + condition.kind.serializer().serializedSize(condition, version); + return TypeSizes.sizeofUnsignedVInt(condition.kind.ordinal()) + + condition.kind.serializer().serializedSize(condition, version); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnData.java b/src/java/org/apache/cassandra/service/accord/txn/TxnData.java index 80920faa89..27369dcaef 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnData.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnData.java @@ -27,9 +27,11 @@ import org.apache.cassandra.db.EmptyIterators; import org.apache.cassandra.db.SinglePartitionReadCommand; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.partitions.PartitionIterators; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.CollectionSerializers; import org.apache.cassandra.utils.Int32Serializer; import org.apache.cassandra.utils.NullableSerializer; @@ -170,26 +172,27 @@ public class TxnData extends Int2ObjectHashMap implements TxnResul return txn_data; } + private static final IVersionedSerializer INT32_SERIALIZER = IVersionedSerializer.fromSerializer(Int32Serializer.serializer); public static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnData data, DataOutputPlus out, int version) throws IOException + public void serialize(TxnData data, DataOutputPlus out, Version version) throws IOException { - CollectionSerializers.serializeMap(data, out, version, Int32Serializer.serializer, TxnDataValue.serializer); + CollectionSerializers.serializeMap(data, out, version, INT32_SERIALIZER, TxnDataValue.serializer); } @Override - public TxnData deserialize(DataInputPlus in, int version) throws IOException + public TxnData deserialize(DataInputPlus in, Version version) throws IOException { - return CollectionSerializers.deserializeMap(in, version, Int32Serializer.serializer, TxnDataValue.serializer, TxnData::newWithExpectedSize); + return CollectionSerializers.deserializeMap(in, version, INT32_SERIALIZER, TxnDataValue.serializer, TxnData::newWithExpectedSize); } @Override - public long serializedSize(TxnData data, int version) + public long serializedSize(TxnData data, Version version) { - return CollectionSerializers.serializedMapSize(data, version, Int32Serializer.serializer, TxnDataValue.serializer); + return CollectionSerializers.serializedMapSize(data, version, INT32_SERIALIZER, TxnDataValue.serializer); } }; - public static final IVersionedSerializer nullableSerializer = NullableSerializer.wrap(serializer); + public static final VersionedSerializer nullableSerializer = NullableSerializer.wrap(serializer); } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnDataKeyValue.java b/src/java/org/apache/cassandra/service/accord/txn/TxnDataKeyValue.java index 2fe6ec6ba4..ea8d014757 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnDataKeyValue.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnDataKeyValue.java @@ -32,6 +32,7 @@ import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.schema.TableMetadata; +import org.apache.cassandra.service.accord.serializers.Version; import static org.apache.cassandra.db.SerializationHeader.StableHeaderSerializer.STABLE; import static org.apache.cassandra.db.rows.DeserializationHelper.Flag.FROM_REMOTE; @@ -72,34 +73,34 @@ public class TxnDataKeyValue extends FilteredPartition implements TxnDataValue public static final TxnDataValueSerializer serializer = new TxnDataValueSerializer<>() { @Override - public void serialize(TxnDataKeyValue value, DataOutputPlus out, int version) throws IOException + public void serialize(TxnDataKeyValue value, DataOutputPlus out, Version version) throws IOException { value.metadata().id.serializeCompact(out); try (UnfilteredRowIterator iterator = value.unfilteredIterator()) { - UnfilteredRowIteratorSerializer.serializer.serialize(iterator, out, version, value.rowCount(), STABLE, null); + UnfilteredRowIteratorSerializer.serializer.serialize(iterator, out, version.messageVersion(), value.rowCount(), STABLE, null); } } @Override - public TxnDataKeyValue deserialize(DataInputPlus in, int version) throws IOException + public TxnDataKeyValue deserialize(DataInputPlus in, Version version) throws IOException { TableMetadata metadata = Schema.instance.getExistingTableMetadata(TableId.deserializeCompact(in)); - UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(metadata, in, version, FROM_REMOTE, STABLE, null); - try (UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version, metadata, FROM_REMOTE, header)) + UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(metadata, in, version.messageVersion(), FROM_REMOTE, STABLE, null); + try (UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version.messageVersion(), metadata, FROM_REMOTE, header)) { return new TxnDataKeyValue(UnfilteredRowIterators.filter(partition, 0)); } } @Override - public long serializedSize(TxnDataKeyValue value, int version) + public long serializedSize(TxnDataKeyValue value, Version version) { TableId tableId = value.metadata().id; long size = tableId.serializedCompactSize(); try (UnfilteredRowIterator iterator = value.unfilteredIterator()) { - return size + UnfilteredRowIteratorSerializer.serializer.serializedSize(iterator, version, value.rowCount(), STABLE, null); + return size + UnfilteredRowIteratorSerializer.serializer.serializedSize(iterator, version.messageVersion(), value.rowCount(), STABLE, null); } } }; diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnDataRangeValue.java b/src/java/org/apache/cassandra/service/accord/txn/TxnDataRangeValue.java index ff9b7a17a5..edb9ac7528 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnDataRangeValue.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnDataRangeValue.java @@ -40,6 +40,7 @@ import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.schema.TableMetadata; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ObjectSizes; import static com.google.common.base.Preconditions.checkState; @@ -121,25 +122,25 @@ public class TxnDataRangeValue extends ArrayList implements T public static final TxnDataValueSerializer serializer = new TxnDataValueSerializer<>() { @Override - public void serialize(TxnDataRangeValue value, DataOutputPlus out, int version) throws IOException + public void serialize(TxnDataRangeValue value, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt32(value.size()); if (value.isEmpty()) return; - TableId.serializer.serialize(value.tableId(), out, version); + TableId.serializer.serialize(value.tableId(), out, version.messageVersion()); for (FilteredPartition partition : value) { try (UnfilteredRowIterator iterator = partition.unfilteredIterator()) { - UnfilteredRowIteratorSerializer.serializer.serialize(iterator, out, version, partition.rowCount(), STABLE, null); + UnfilteredRowIteratorSerializer.serializer.serialize(iterator, out, version.messageVersion(), partition.rowCount(), STABLE, null); } } } @Override - public TxnDataRangeValue deserialize(DataInputPlus in, int version) throws IOException + public TxnDataRangeValue deserialize(DataInputPlus in, Version version) throws IOException { int numPartitions = in.readUnsignedVInt32(); TxnDataRangeValue value = new TxnDataRangeValue(numPartitions); @@ -148,8 +149,8 @@ public class TxnDataRangeValue extends ArrayList implements T TableMetadata metadata = Schema.instance.getExistingTableMetadata(TableId.deserialize(in)); for (int i = 0; i < numPartitions; i++) { - UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(metadata, in, version, FROM_REMOTE, STABLE, null); - try (UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version, metadata, FROM_REMOTE, header)) + UnfilteredRowIteratorSerializer.Header header = UnfilteredRowIteratorSerializer.serializer.deserializeHeader(metadata, in, version.messageVersion(), FROM_REMOTE, STABLE, null); + try (UnfilteredRowIterator partition = UnfilteredRowIteratorSerializer.serializer.deserialize(in, version.messageVersion(), metadata, FROM_REMOTE, header)) { value.add(new FilteredPartition(UnfilteredRowIterators.filter(partition, 0))); } @@ -158,17 +159,17 @@ public class TxnDataRangeValue extends ArrayList implements T } @Override - public long serializedSize(TxnDataRangeValue value, int version) + public long serializedSize(TxnDataRangeValue value, Version version) { long size = TypeSizes.sizeofUnsignedVInt(value.size()); if (value.size() == 0) return size; - size += TableId.serializer.serializedSize(value.tableId(), version); + size += TableId.serializer.serializedSize(value.tableId(), version.messageVersion()); for (FilteredPartition partition : value) { try (UnfilteredRowIterator iterator = partition.unfilteredIterator()) { - size += UnfilteredRowIteratorSerializer.serializer.serializedSize(iterator, version, partition.rowCount(), STABLE, null); + size += UnfilteredRowIteratorSerializer.serializer.serializedSize(iterator, version.messageVersion(), partition.rowCount(), STABLE, null); } } return size; diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnDataValue.java b/src/java/org/apache/cassandra/service/accord/txn/TxnDataValue.java index cc73b43ea8..bee1340854 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnDataValue.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnDataValue.java @@ -20,9 +20,10 @@ package org.apache.cassandra.service.accord.txn; import java.io.IOException; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import static org.apache.cassandra.db.TypeSizes.sizeof; @@ -31,7 +32,8 @@ import static org.apache.cassandra.db.TypeSizes.sizeof; */ public interface TxnDataValue { - interface TxnDataValueSerializer extends IVersionedSerializer {} + interface TxnDataValueSerializer extends IVersionedSerializer + {} enum Kind { @@ -68,14 +70,14 @@ public interface TxnDataValue { @SuppressWarnings("unchecked") @Override - public void serialize(TxnDataValue txnDataValue, DataOutputPlus out, int version) throws IOException + public void serialize(TxnDataValue txnDataValue, DataOutputPlus out, Version version) throws IOException { out.writeByte(txnDataValue.kind().ordinal()); txnDataValue.kind().serializer().serialize(txnDataValue, out, version); } @Override - public TxnDataValue deserialize(DataInputPlus in, int version) throws IOException + public TxnDataValue deserialize(DataInputPlus in, Version version) throws IOException { TxnDataValue.Kind kind = TxnDataValue.Kind.values()[in.readByte()]; return (TxnDataValue)kind.serializer().deserialize(in, version); @@ -83,7 +85,7 @@ public interface TxnDataValue @SuppressWarnings("unchecked") @Override - public long serializedSize(TxnDataValue txnDataValue, int version) + public long serializedSize(TxnDataValue txnDataValue, Version version) { return sizeof((byte)txnDataValue.kind().ordinal()) + txnDataValue.kind().serializer().serializedSize(txnDataValue, version); } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnNamedRead.java b/src/java/org/apache/cassandra/service/accord/txn/TxnNamedRead.java index 42baff2bb7..a5d6d9e7ff 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnNamedRead.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnNamedRead.java @@ -23,7 +23,6 @@ import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,7 +53,6 @@ import org.apache.cassandra.db.rows.RowIterator; import org.apache.cassandra.dht.AbstractBounds; import org.apache.cassandra.dht.Token; import org.apache.cassandra.dht.Token.KeyBound; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.TableId; @@ -62,7 +60,9 @@ import org.apache.cassandra.service.accord.AccordObjectSizes; import org.apache.cassandra.service.accord.TokenRange; import org.apache.cassandra.service.accord.api.TokenKey; import org.apache.cassandra.service.accord.api.PartitionKey; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.accord.txn.TxnData.TxnDataNameKind; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.Comparables; @@ -79,18 +79,33 @@ public class TxnNamedRead extends AbstractSerialized @SuppressWarnings("unused") private static final Logger logger = LoggerFactory.getLogger(TxnNamedRead.class); - private static final long EMPTY_SIZE = ObjectSizes.measure(new TxnNamedRead(0, null, (ByteBuffer) null)); + private static final long EMPTY_SIZE = ObjectSizes.measure(new TxnNamedRead(0, null, null, Version.LATEST)); private final int name; private final Seekable key; - public TxnNamedRead(int name, @Nullable SinglePartitionReadCommand value) + public TxnNamedRead(int name, SinglePartitionReadCommand value) { super(value); this.name = name; this.key = new PartitionKey(value.metadata().id, value.partitionKey()); } + public TxnNamedRead(int name, AbstractBounds range, PartitionRangeReadCommand value) + { + super(value); + TableId tableId = value.metadata().id; + this.name = name; + this.key = boundsAsAccordRange(range, tableId); + } + + public TxnNamedRead(int name, Seekable key, ByteBuffer bytes, Version version) + { + super(bytes, version); + this.name = name; + this.key = key; + } + public static TokenRange boundsAsAccordRange(AbstractBounds range, TableId tableId) { // Should already have been unwrapped @@ -127,33 +142,18 @@ public class TxnNamedRead extends AbstractSerialized return TokenRange.create(startTokenKey, stopTokenKey); } - public TxnNamedRead(int name, AbstractBounds range, PartitionRangeReadCommand value) - { - super(value); - TableId tableId = value.metadata().id; - this.name = name; - this.key = boundsAsAccordRange(range, tableId); - } - - public TxnNamedRead(int name, Seekable key, ByteBuffer bytes) - { - super(bytes); - this.name = name; - this.key = key; - } - public long estimatedSizeOnHeap() { long size = EMPTY_SIZE; size += AccordObjectSizes.seekable(key); - size += (bytes() != null ? ByteBufferUtil.estimatedSizeOnHeap(bytes()) : 0); + size += (unsafeBytes() != null ? ByteBufferUtil.estimatedSizeOnHeap(unsafeBytes()) : 0); return size; } @Override protected IVersionedSerializer serializer() { - return ReadCommand.serializer; + return readCommandSerializer; } @Override @@ -226,7 +226,7 @@ public class TxnNamedRead extends AbstractSerialized return this; Invariants.require(((Range)key).contains(range)); - return new TxnNamedRead(txnDataName(), range, bytes()); + return new TxnNamedRead(txnDataName(), range, unsafeBytes(), version); } public TxnNamedRead merge(TxnNamedRead with) @@ -241,7 +241,7 @@ public class TxnNamedRead extends AbstractSerialized RoutingKey start = Comparables.min(thisRange.start(), thatRange.start()); RoutingKey end = Comparables.max(thisRange.end(), thatRange.end()); Range range = thisRange.newRange(start, end); - return new TxnNamedRead(txnDataName(), range, bytes()); + return new TxnNamedRead(txnDataName(), range, unsafeBytes(), version); } public static boolean readsWithoutReconciliation(ConsistencyLevel consistencyLevel) @@ -433,15 +433,14 @@ public class TxnNamedRead extends AbstractSerialized static final IVersionedSerializer serializer = new IVersionedSerializer<>() { @Override - public void serialize(TxnNamedRead read, DataOutputPlus out, int version) throws IOException + public void serialize(TxnNamedRead read, DataOutputPlus out, Version version) throws IOException { out.writeInt(read.name); - KeySerializers.seekable.serialize(read.key, out, version); - - if (read.bytes() != null) + KeySerializers.seekable.serialize(read.key, out); + if (!read.isNull()) { out.write(0); - writeWithVIntLength(read.bytes(), out); + writeWithVIntLength(read.bytes(version), out); } else { @@ -450,24 +449,26 @@ public class TxnNamedRead extends AbstractSerialized } @Override - public TxnNamedRead deserialize(DataInputPlus in, int version) throws IOException + public TxnNamedRead deserialize(DataInputPlus in, Version version) throws IOException { int name = in.readInt(); - Seekable key = KeySerializers.seekable.deserialize(in, version); + Seekable key = KeySerializers.seekable.deserialize(in); ByteBuffer bytes = in.readByte() == 1 ? null : readWithVIntLength(in); - return new TxnNamedRead(name, key, bytes); + return new TxnNamedRead(name, key, bytes, version); } @Override - public long serializedSize(TxnNamedRead read, int version) + public long serializedSize(TxnNamedRead read, Version version) { long size = 0; size += TypeSizes.sizeof(read.name); - size += KeySerializers.seekable.serializedSize(read.key, version); + size += KeySerializers.seekable.serializedSize(read.key); size += TypeSizes.BYTE_SIZE; // is null - if (read.bytes() != null) - size += serializedSizeWithVIntLength(read.bytes()); + if (!read.isNull()) + size += serializedSizeWithVIntLength(read.bytes(version)); return size; } }; + + static final IVersionedSerializer readCommandSerializer = IVersionedSerializer.fromMessaging(ReadCommand.serializer); } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnQuery.java b/src/java/org/apache/cassandra/service/accord/txn/TxnQuery.java index 543fb49b33..fe487cc7d6 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnQuery.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnQuery.java @@ -38,7 +38,7 @@ import org.apache.cassandra.db.PartitionRangeReadCommand; import org.apache.cassandra.db.SinglePartitionReadCommand; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.partitions.PartitionIterator; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.metrics.ClientRequestsMetricsHolder; @@ -227,17 +227,17 @@ public abstract class TxnQuery implements Query return SIZE; } - public static final IVersionedSerializer serializer = new IVersionedSerializer() + public static final UnversionedSerializer serializer = new UnversionedSerializer() { @Override - public void serialize(TxnQuery query, DataOutputPlus out, int version) throws IOException + public void serialize(TxnQuery query, DataOutputPlus out) throws IOException { Preconditions.checkArgument(query == null | query == ALL | query == NONE | query == CONDITION | query == UNSAFE_EMPTY | query == RANGE_QUERY); out.writeByte(query == null ? 0 : query.type()); } @Override - public TxnQuery deserialize(DataInputPlus in, int version) throws IOException + public TxnQuery deserialize(DataInputPlus in) throws IOException { switch (in.readByte()) { @@ -252,7 +252,7 @@ public abstract class TxnQuery implements Query } @Override - public long serializedSize(TxnQuery query, int version) + public long serializedSize(TxnQuery query) { Preconditions.checkArgument(query == null | query == ALL | query == NONE | query == CONDITION | query == UNSAFE_EMPTY | query == RANGE_QUERY); return TypeSizes.sizeof((byte)2); diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnRead.java b/src/java/org/apache/cassandra/service/accord/txn/TxnRead.java index ee106e216e..e35267fb28 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnRead.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnRead.java @@ -49,10 +49,11 @@ import org.apache.cassandra.db.PartitionPosition; import org.apache.cassandra.db.PartitionRangeReadCommand; import org.apache.cassandra.db.SinglePartitionReadCommand; import org.apache.cassandra.dht.AbstractBounds; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.api.PartitionKey; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.tcm.ClusterMetadata; import org.apache.cassandra.utils.ObjectSizes; @@ -165,7 +166,7 @@ public class TxnRead extends AbstractKeySorted implements Read { List reads = new ArrayList<>(keys.size()); for (int i = 0; i < keys.size(); i++) - reads.add(new TxnNamedRead(txnDataName(USER, i), keys.get(i), null)); + reads.add(new TxnNamedRead(txnDataName(USER, i), keys.get(i), null, Version.LATEST)); return new TxnRead(reads, null); } @@ -393,13 +394,13 @@ public class TxnRead extends AbstractKeySorted implements Read public static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnRead read, DataOutputPlus out, int version) throws IOException + public void serialize(TxnRead read, DataOutputPlus out, Version version) throws IOException { if (read.items.length > 0) { out.write(TYPE_NOT_EMPTY); serializeArray(read.items, out, version, TxnNamedRead.serializer); - serializeNullable(read.cassandraConsistencyLevel, out, version, consistencyLevelSerializer); + serializeNullable(read.cassandraConsistencyLevel, out, consistencyLevelSerializer); } else { @@ -408,7 +409,7 @@ public class TxnRead extends AbstractKeySorted implements Read } @Override - public TxnRead deserialize(DataInputPlus in, int version) throws IOException + public TxnRead deserialize(DataInputPlus in, Version version) throws IOException { byte type = in.readByte(); switch (type) @@ -421,19 +422,19 @@ public class TxnRead extends AbstractKeySorted implements Read return EMPTY_RANGE; case TYPE_NOT_EMPTY: TxnNamedRead[] items = deserializeArray(in, version, TxnNamedRead.serializer, TxnNamedRead[]::new); - ConsistencyLevel consistencyLevel = deserializeNullable(in, version, consistencyLevelSerializer); + ConsistencyLevel consistencyLevel = deserializeNullable(in, consistencyLevelSerializer); return new TxnRead(items, consistencyLevel); } } @Override - public long serializedSize(TxnRead read, int version) + public long serializedSize(TxnRead read, Version version) { long size = 1; // type if (read.items.length > 0) { size += serializedArraySize(read.items, version, TxnNamedRead.serializer); - size += serializedNullableSize(read.cassandraConsistencyLevel, version, consistencyLevelSerializer); + size += serializedNullableSize(read.cassandraConsistencyLevel, consistencyLevelSerializer); } return size; } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnReference.java b/src/java/org/apache/cassandra/service/accord/txn/TxnReference.java index 0f1e37e90c..52017beba7 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnReference.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnReference.java @@ -35,10 +35,11 @@ import org.apache.cassandra.db.rows.CellPath; import org.apache.cassandra.db.rows.ColumnData; import org.apache.cassandra.db.rows.ComplexColumnData; import org.apache.cassandra.db.rows.Row; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.ColumnMetadata; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ByteBufferUtil; import static org.apache.cassandra.db.marshal.CollectionType.Kind.SET; @@ -46,18 +47,18 @@ import static org.apache.cassandra.service.accord.AccordSerializers.columnMetada public class TxnReference { - private final Integer tuple; + private final int tuple; private final ColumnMetadata column; private final CellPath path; - public TxnReference(Integer tuple, ColumnMetadata column, CellPath path) + public TxnReference(int tuple, ColumnMetadata column, CellPath path) { this.tuple = tuple; this.column = column; this.path = path; } - public TxnReference(Integer tuple, ColumnMetadata column) + public TxnReference(int tuple, ColumnMetadata column) { this(tuple, column, null); } @@ -68,7 +69,7 @@ public class TxnReference if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TxnReference reference = (TxnReference) o; - return tuple.equals(reference.tuple) && Objects.equals(column, reference.column) && Objects.equals(path, reference.path); + return tuple == reference.tuple && Objects.equals(column, reference.column) && Objects.equals(path, reference.path); } @Override @@ -290,34 +291,35 @@ public class TxnReference static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnReference reference, DataOutputPlus out, int version) throws IOException + public void serialize(TxnReference reference, DataOutputPlus out, Version version) throws IOException { out.writeInt(reference.tuple); out.writeBoolean(reference.column != null); if (reference.column != null) - columnMetadataSerializer.serialize(reference.column, out, version); + columnMetadataSerializer.serialize(reference.column, out); out.writeBoolean(reference.path != null); if (reference.path != null) CollectionType.cellPathSerializer.serialize(reference.path, out); } @Override - public TxnReference deserialize(DataInputPlus in, int version) throws IOException + public TxnReference deserialize(DataInputPlus in, Version version) throws IOException { int name = in.readInt(); - ColumnMetadata column = in.readBoolean() ? columnMetadataSerializer.deserialize(in, version) : null; + ColumnMetadata column = in.readBoolean() ? columnMetadataSerializer.deserialize(in) : null; CellPath path = in.readBoolean() ? CollectionType.cellPathSerializer.deserialize(in) : null; return new TxnReference(name, column, path); } @Override - public long serializedSize(TxnReference reference, int version) + public long serializedSize(TxnReference reference, Version version) { long size = 0; size += TypeSizes.INT_SIZE; size += TypeSizes.BOOL_SIZE; if (reference.column != null) - size += columnMetadataSerializer.serializedSize(reference.column, version); + size += columnMetadataSerializer.serializedSize(reference.column); + size += TypeSizes.BOOL_SIZE; if (reference.path != null) size += CollectionType.cellPathSerializer.serializedSize(reference.path); return size; diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperation.java b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperation.java index e49c1803dc..397c4deada 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperation.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperation.java @@ -43,11 +43,12 @@ import org.apache.cassandra.db.marshal.SetType; import org.apache.cassandra.db.marshal.TupleType; import org.apache.cassandra.db.marshal.UserType; import org.apache.cassandra.db.rows.CellPath; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.service.accord.AccordSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ByteBufferUtil; import static org.apache.cassandra.db.marshal.CollectionType.Kind.MAP; @@ -257,10 +258,10 @@ public class TxnReferenceOperation static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnReferenceOperation operation, DataOutputPlus out, int version) throws IOException + public void serialize(TxnReferenceOperation operation, DataOutputPlus out, Version version) throws IOException { out.writeByte(operation.kind.id); - columnMetadataSerializer.serialize(operation.receiver, out, version); + columnMetadataSerializer.serialize(operation.receiver, out); TxnReferenceValue.serializer.serialize(operation.value, out, version); out.writeBoolean(operation.key != null); @@ -273,10 +274,10 @@ public class TxnReferenceOperation } @Override - public TxnReferenceOperation deserialize(DataInputPlus in, int version) throws IOException + public TxnReferenceOperation deserialize(DataInputPlus in, Version version) throws IOException { Kind kind = Kind.from(in.readByte()); - ColumnMetadata receiver = columnMetadataSerializer.deserialize(in, version); + ColumnMetadata receiver = columnMetadataSerializer.deserialize(in); TxnReferenceValue value = TxnReferenceValue.serializer.deserialize(in, version); ByteBuffer key = in.readBoolean() ? ByteBufferUtil.readWithVIntLength(in) : null; ByteBuffer field = in.readBoolean() ? ByteBufferUtil.readWithVIntLength(in) : null; @@ -284,10 +285,10 @@ public class TxnReferenceOperation } @Override - public long serializedSize(TxnReferenceOperation operation, int version) + public long serializedSize(TxnReferenceOperation operation, Version version) { long size = Byte.BYTES; - size += columnMetadataSerializer.serializedSize(operation.receiver, version); + size += columnMetadataSerializer.serializedSize(operation.receiver); size += TxnReferenceValue.serializer.serializedSize(operation.value, version); if (operation.key != null) diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperations.java b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperations.java index f926ad3df1..b326ba61db 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperations.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceOperations.java @@ -27,10 +27,11 @@ import com.google.common.base.Preconditions; import org.apache.cassandra.db.Clustering; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.TableMetadata; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import static org.apache.cassandra.utils.CollectionSerializers.deserializeList; import static org.apache.cassandra.utils.CollectionSerializers.serializeList; @@ -89,7 +90,7 @@ public class TxnReferenceOperations static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnReferenceOperations operations, DataOutputPlus out, int version) throws IOException + public void serialize(TxnReferenceOperations operations, DataOutputPlus out, Version version) throws IOException { out.writeBoolean(!operations.isEmpty()); if (operations.isEmpty()) @@ -97,25 +98,25 @@ public class TxnReferenceOperations tableMetadataSerializer.serialize(operations.metadata, out, version); out.writeBoolean(operations.clustering != null); if (operations.clustering != null) - Clustering.serializer.serialize(operations.clustering, out, version, operations.metadata.comparator.subtypes()); + Clustering.serializer.serialize(operations.clustering, out, version.messageVersion(), operations.metadata.comparator.subtypes()); serializeList(operations.regulars, out, version, TxnReferenceOperation.serializer); serializeList(operations.statics, out, version, TxnReferenceOperation.serializer); } @Override - public TxnReferenceOperations deserialize(DataInputPlus in, int version) throws IOException + public TxnReferenceOperations deserialize(DataInputPlus in, Version version) throws IOException { if (!in.readBoolean()) return TxnReferenceOperations.empty(); TableMetadata metadata = tableMetadataSerializer.deserialize(in, version); - Clustering clustering = in.readBoolean() ? Clustering.serializer.deserialize(in, version, metadata.comparator.subtypes()) : null; + Clustering clustering = in.readBoolean() ? Clustering.serializer.deserialize(in, version.messageVersion(), metadata.comparator.subtypes()) : null; return new TxnReferenceOperations(metadata, clustering, deserializeList(in, version, TxnReferenceOperation.serializer), deserializeList(in, version, TxnReferenceOperation.serializer)); } @Override - public long serializedSize(TxnReferenceOperations operations, int version) + public long serializedSize(TxnReferenceOperations operations, Version version) { long size = TypeSizes.BOOL_SIZE; if (operations.isEmpty()) @@ -123,7 +124,7 @@ public class TxnReferenceOperations size += tableMetadataSerializer.serializedSize(operations.metadata, version); size += TypeSizes.BOOL_SIZE; if (operations.clustering != null) - size += Clustering.serializer.serializedSize(operations.clustering, version, operations.metadata.comparator.subtypes()); + size += Clustering.serializer.serializedSize(operations.clustering, version.messageVersion(), operations.metadata.comparator.subtypes()); size += serializedListSize(operations.regulars, version, TxnReferenceOperation.serializer); size += serializedListSize(operations.statics, version, TxnReferenceOperation.serializer); return size; diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceValue.java b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceValue.java index 73033fe61c..e778adf4e9 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceValue.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnReferenceValue.java @@ -24,18 +24,19 @@ import java.util.Objects; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.marshal.AbstractType; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.ByteBufferUtil; public abstract class TxnReferenceValue { private interface Serializer { - void serialize(T t, DataOutputPlus out, int version) throws IOException; - T deserialize(DataInputPlus in, int version, Kind kind) throws IOException; - long serializedSize(T t, int version); + void serialize(T t, DataOutputPlus out, Version version) throws IOException; + T deserialize(DataInputPlus in, Version version, Kind kind) throws IOException; + long serializedSize(T t, Version version); } enum Kind @@ -105,19 +106,19 @@ public abstract class TxnReferenceValue private static final Serializer serializer = new Serializer() { @Override - public void serialize(Constant constant, DataOutputPlus out, int version) throws IOException + public void serialize(Constant constant, DataOutputPlus out, Version version) throws IOException { ByteBufferUtil.writeWithVIntLength(constant.value, out); } @Override - public Constant deserialize(DataInputPlus in, int version, Kind kind) throws IOException + public Constant deserialize(DataInputPlus in, Version version, Kind kind) throws IOException { return new Constant(ByteBufferUtil.readWithVIntLength(in)); } @Override - public long serializedSize(Constant constant, int version) + public long serializedSize(Constant constant, Version version) { return ByteBufferUtil.serializedSizeWithVIntLength(constant.value); } @@ -169,19 +170,19 @@ public abstract class TxnReferenceValue private static final Serializer serializer = new Serializer() { @Override - public void serialize(Substitution substitution, DataOutputPlus out, int version) throws IOException + public void serialize(Substitution substitution, DataOutputPlus out, Version version) throws IOException { TxnReference.serializer.serialize(substitution.reference, out, version); } @Override - public Substitution deserialize(DataInputPlus in, int version, Kind kind) throws IOException + public Substitution deserialize(DataInputPlus in, Version version, Kind kind) throws IOException { return new Substitution(TxnReference.serializer.deserialize(in, version)); } @Override - public long serializedSize(Substitution substitution, int version) + public long serializedSize(Substitution substitution, Version version) { return TxnReference.serializer.serializedSize(substitution.reference, version); } @@ -192,14 +193,14 @@ public abstract class TxnReferenceValue { @SuppressWarnings("unchecked") @Override - public void serialize(TxnReferenceValue value, DataOutputPlus out, int version) throws IOException + public void serialize(TxnReferenceValue value, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt32(value.kind().ordinal()); value.kind().serializer.serialize(value, out, version); } @Override - public TxnReferenceValue deserialize(DataInputPlus in, int version) throws IOException + public TxnReferenceValue deserialize(DataInputPlus in, Version version) throws IOException { Kind kind = Kind.values()[in.readUnsignedVInt32()]; return kind.serializer.deserialize(in, version, kind); @@ -207,7 +208,7 @@ public abstract class TxnReferenceValue @SuppressWarnings("unchecked") @Override - public long serializedSize(TxnReferenceValue value, int version) + public long serializedSize(TxnReferenceValue value, Version version) { return TypeSizes.sizeofUnsignedVInt(value.kind().ordinal()) + value.kind().serializer.serializedSize(value, version); } diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnUpdate.java b/src/java/org/apache/cassandra/service/accord/txn/TxnUpdate.java index ffdb99e21e..be9e8b5622 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnUpdate.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnUpdate.java @@ -39,16 +39,15 @@ import accord.primitives.Timestamp; import org.apache.cassandra.cql3.QueryOptions; import org.apache.cassandra.db.ConsistencyLevel; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputBuffer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.DataOutputPlus; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.service.accord.AccordObjectSizes; -import org.apache.cassandra.service.accord.AccordSerializers; import org.apache.cassandra.service.accord.IAccordService; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.tcm.ClusterMetadata; import org.apache.cassandra.transport.ProtocolVersion; import org.apache.cassandra.utils.ByteBufferUtil; @@ -58,7 +57,6 @@ import static accord.utils.Invariants.requireArgument; import static accord.utils.SortedArrays.Search.CEIL; import static com.google.common.base.Preconditions.checkState; import static org.apache.cassandra.service.accord.AccordSerializers.consistencyLevelSerializer; -import static org.apache.cassandra.service.accord.AccordSerializers.serialize; import static org.apache.cassandra.utils.ArraySerializers.deserializeArray; import static org.apache.cassandra.utils.ArraySerializers.serializeArray; import static org.apache.cassandra.utils.ArraySerializers.serializedArraySize; @@ -76,7 +74,7 @@ public class TxnUpdate extends AccordUpdate private final Keys keys; private final ByteBuffer[] fragments; - private final ByteBuffer condition; + private final AbstractSerialized condition; @Nullable private final ConsistencyLevel cassandraCommitCL; @@ -95,13 +93,16 @@ public class TxnUpdate extends AccordUpdate // TODO: Figure out a way to shove keys into TxnCondition, and have it implement slice/merge. this.keys = Keys.of(fragments, fragment -> fragment.key); fragments.sort(TxnWrite.Fragment::compareKeys); - this.fragments = toSerializedValuesArray(keys, fragments, fragment -> fragment.key, TxnWrite.Fragment.serializer); - this.condition = serialize(condition, TxnCondition.serializer); + //TODO (correctness): this node could be on version N while the peers are on N-1, which would have issues as the peers wouldn't know about N yet. + // Can not eagerly serialize until we know the "correct" version, else we need a way to fallback on mismatch. + this.fragments = toSerializedValuesArray(keys, fragments, fragment -> fragment.key, Version.LATEST, TxnWrite.Fragment.serializer); + this.condition = AbstractSerialized.of(TxnCondition.serializer, condition); + this.condition.unmemoize(); this.cassandraCommitCL = cassandraCommitCL; this.preserveTimestamps = preserveTimestamps; } - private TxnUpdate(Keys keys, ByteBuffer[] fragments, ByteBuffer condition, ConsistencyLevel cassandraCommitCL, boolean preserveTimestamps) + private TxnUpdate(Keys keys, ByteBuffer[] fragments, AbstractSerialized condition, ConsistencyLevel cassandraCommitCL, boolean preserveTimestamps) { this.keys = keys; this.fragments = fragments; @@ -118,7 +119,7 @@ public class TxnUpdate extends AccordUpdate @Override public long estimatedSizeOnHeap() { - long size = EMPTY_SIZE + ByteBufferUtil.estimatedSizeOnHeap(condition); + long size = EMPTY_SIZE + condition.estimatedSizeOnHeap(); for (ByteBuffer update : fragments) size += ByteBufferUtil.estimatedSizeOnHeap(update); size += AccordObjectSizes.keys(keys); @@ -129,7 +130,7 @@ public class TxnUpdate extends AccordUpdate public String toString() { return "TxnUpdate{updates=" + deserialize(fragments, TxnWrite.Fragment.serializer) + - ", condition=" + AccordSerializers.deserialize(condition, TxnCondition.serializer) + '}'; + ", condition=" + condition.get() + '}'; } @Override @@ -257,41 +258,40 @@ public class TxnUpdate extends AccordUpdate public static final AccordUpdateSerializer serializer = new AccordUpdateSerializer() { @Override - public void serialize(TxnUpdate update, DataOutputPlus out, int version) throws IOException + public void serialize(TxnUpdate update, DataOutputPlus out, Version version) throws IOException { out.writeByte(update.preserveTimestamps ? FLAG_PRESERVE_TIMESTAMPS : 0); - KeySerializers.keys.serialize(update.keys, out, version); - writeWithVIntLength(update.condition, out); - serializeArray(update.fragments, out, version, ByteBufferUtil.byteBufferSerializer); - serializeNullable(update.cassandraCommitCL, out, version, consistencyLevelSerializer); + KeySerializers.keys.serialize(update.keys, out); + writeWithVIntLength(update.condition.bytes(version), out); + serializeArray(update.fragments, out, ByteBufferUtil.byteBufferSerializer); + serializeNullable(update.cassandraCommitCL, out, consistencyLevelSerializer); } @Override - public TxnUpdate deserialize(DataInputPlus in, int version) throws IOException + public TxnUpdate deserialize(DataInputPlus in, Version version) throws IOException { int flags = in.readByte(); boolean preserveTimestamps = (FLAG_PRESERVE_TIMESTAMPS & flags) == 1; - Keys keys = KeySerializers.keys.deserialize(in, version); + Keys keys = KeySerializers.keys.deserialize(in); ByteBuffer condition = readWithVIntLength(in); - ByteBuffer[] fragments = deserializeArray(in, version, ByteBufferUtil.byteBufferSerializer, ByteBuffer[]::new); - ConsistencyLevel consistencyLevel = deserializeNullable(in, version, consistencyLevelSerializer); - return new TxnUpdate(keys, fragments, condition, consistencyLevel, preserveTimestamps); + ByteBuffer[] fragments = deserializeArray(in, ByteBufferUtil.byteBufferSerializer, ByteBuffer[]::new); + ConsistencyLevel consistencyLevel = deserializeNullable(in, consistencyLevelSerializer); + return new TxnUpdate(keys, fragments, AbstractSerialized.fromBytes(TxnCondition.serializer, condition, version), consistencyLevel, preserveTimestamps); } @Override - public long serializedSize(TxnUpdate update, int version) + public long serializedSize(TxnUpdate update, Version version) { long size = 1; // flags - size += KeySerializers.keys.serializedSize(update.keys, version); - size += serializedSizeWithVIntLength(update.condition); - size += serializedArraySize(update.fragments, version, ByteBufferUtil.byteBufferSerializer); - size += serializedNullableSize(update.cassandraCommitCL, version, consistencyLevelSerializer); - assert(ByteBufferUtil.serialized(this, update, version).remaining() == size); + size += KeySerializers.keys.serializedSize(update.keys); + size += serializedSizeWithVIntLength(update.condition.bytes(version)); + size += serializedArraySize(update.fragments, ByteBufferUtil.byteBufferSerializer); + size += serializedNullableSize(update.cassandraCommitCL, consistencyLevelSerializer); return size; } }; - private static ByteBuffer[] toSerializedValuesArray(Keys keys, List items, Function toKey, IVersionedSerializer serializer) + private static ByteBuffer[] toSerializedValuesArray(Keys keys, List items, Function toKey, Version version, IVersionedSerializer serializer) { ByteBuffer[] result = new ByteBuffer[keys.size()]; int i = 0, mi = items.size(), ki = 0; @@ -305,22 +305,22 @@ public class TxnUpdate extends AccordUpdate int nextki = keys.findNext(ki, key, CEIL); Arrays.fill(result, ki, nextki, ByteBufferUtil.EMPTY_BYTE_BUFFER); ki = nextki; - result[ki++] = toSerializedValues(items, i, j, serializer, MessagingService.current_version); + result[ki++] = toSerializedValues(items, i, j, serializer, version); i = j; } Arrays.fill(result, ki, result.length, ByteBufferUtil.EMPTY_BYTE_BUFFER); return result; } - private static ByteBuffer toSerializedValues(List items, int start, int end, IVersionedSerializer serializer, int version) + private static ByteBuffer toSerializedValues(List items, int start, int end, IVersionedSerializer serializer, Version version) { - long size = TypeSizes.sizeofUnsignedVInt(version) + TypeSizes.sizeofUnsignedVInt(end - start); + long size = TypeSizes.sizeofUnsignedVInt(version.version) + TypeSizes.sizeofUnsignedVInt(end - start); for (int i = start ; i < end ; ++i) size += serializer.serializedSize(items.get(i), version); try (DataOutputBuffer out = new DataOutputBuffer((int) size)) { - out.writeUnsignedVInt32(version); + out.writeUnsignedVInt32(version.version); out.writeUnsignedVInt32(end - start); for (int i = start ; i < end ; ++i) serializer.serialize(items.get(i), out, version); @@ -339,7 +339,7 @@ public class TxnUpdate extends AccordUpdate try (DataInputBuffer in = new DataInputBuffer(bytes, true)) { - int version = in.readUnsignedVInt32(); + Version version = Version.fromVersion(in.readUnsignedVInt32()); int count = in.readUnsignedVInt32(); switch (count) { @@ -372,7 +372,7 @@ public class TxnUpdate extends AccordUpdate // Assert data that was memoized is same as data that is provided? if (conditionResult != null) return conditionResult; - TxnCondition condition = AccordSerializers.deserialize(this.condition, TxnCondition.serializer); + TxnCondition condition = this.condition.get(); if (condition == TxnCondition.none()) return conditionResult = true; return conditionResult = condition.applies((TxnData) data); diff --git a/src/java/org/apache/cassandra/service/accord/txn/TxnWrite.java b/src/java/org/apache/cassandra/service/accord/txn/TxnWrite.java index 8b1611dd7a..d8e7da61e7 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/TxnWrite.java +++ b/src/java/org/apache/cassandra/service/accord/txn/TxnWrite.java @@ -54,12 +54,13 @@ import org.apache.cassandra.db.RegularAndStaticColumns; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.partitions.PartitionUpdate; import org.apache.cassandra.db.rows.Row; -import org.apache.cassandra.io.IVersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.service.accord.AccordObjectSizes; import org.apache.cassandra.service.accord.api.PartitionKey; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.BooleanSerializer; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.ObjectSizes; @@ -81,7 +82,7 @@ public class TxnWrite extends AbstractKeySorted implements Writ public static class Update extends AbstractSerialized { - private static final long EMPTY_SIZE = ObjectSizes.measure(new Update(null, 0, (ByteBuffer) null)); + private static final long EMPTY_SIZE = ObjectSizes.measure(new Update(null, 0, ByteBufferUtil.EMPTY_BYTE_BUFFER, Version.LATEST)); public final PartitionKey key; public final int index; @@ -92,18 +93,19 @@ public class TxnWrite extends AbstractKeySorted implements Writ this.index = index; } - private Update(PartitionKey key, int index, ByteBuffer bytes) + private Update(PartitionKey key, int index, ByteBuffer bytes, Version version) { - super(bytes); + super(bytes, version); this.key = key; this.index = index; } - long estimatedSizeOnHeap() + @Override + public long estimatedSizeOnHeap() { return EMPTY_SIZE + AccordObjectSizes.key(key) - + ByteBufferUtil.estimatedSizeOnHeap(bytes()); + + ByteBufferUtil.estimatedSizeOnHeap(unsafeBytes()); } @Override @@ -150,29 +152,29 @@ public class TxnWrite extends AbstractKeySorted implements Writ public static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(Update write, DataOutputPlus out, int version) throws IOException + public void serialize(Update write, DataOutputPlus out, Version version) throws IOException { - PartitionKey.serializer.serialize(write.key, out, version); + PartitionKey.serializer.serialize(write.key, out); out.writeInt(write.index); - ByteBufferUtil.writeWithVIntLength(write.bytes(), out); + ByteBufferUtil.writeWithVIntLength(write.bytes(version), out); } @Override - public Update deserialize(DataInputPlus in, int version) throws IOException + public Update deserialize(DataInputPlus in, Version version) throws IOException { - PartitionKey key = PartitionKey.serializer.deserialize(in, version); + PartitionKey key = PartitionKey.serializer.deserialize(in); int index = in.readInt(); ByteBuffer bytes = ByteBufferUtil.readWithVIntLength(in); - return new Update(key, index, bytes); + return new Update(key, index, bytes, version); } @Override - public long serializedSize(Update write, int version) + public long serializedSize(Update write, Version version) { long size = 0; - size += PartitionKey.serializer.serializedSize(write.key, version); + size += PartitionKey.serializer.serializedSize(write.key); size += TypeSizes.INT_SIZE; - size += ByteBufferUtil.serializedSizeWithVIntLength(write.bytes()); + size += ByteBufferUtil.serializedSizeWithVIntLength(write.bytes(version)); return size; } }; @@ -302,18 +304,18 @@ public class TxnWrite extends AbstractKeySorted implements Writ static final IVersionedSerializer serializer = new IVersionedSerializer<>() { @Override - public void serialize(Fragment fragment, DataOutputPlus out, int version) throws IOException + public void serialize(Fragment fragment, DataOutputPlus out, Version version) throws IOException { - PartitionKey.serializer.serialize(fragment.key, out, version); + PartitionKey.serializer.serialize(fragment.key, out); out.writeUnsignedVInt32(fragment.index); partitionUpdateSerializer.serialize(fragment.baseUpdate, out, version); TxnReferenceOperations.serializer.serialize(fragment.referenceOps, out, version); } @Override - public Fragment deserialize(DataInputPlus in, int version) throws IOException + public Fragment deserialize(DataInputPlus in, Version version) throws IOException { - PartitionKey key = PartitionKey.serializer.deserialize(in, version); + PartitionKey key = PartitionKey.serializer.deserialize(in); int idx = in.readUnsignedVInt32(); PartitionUpdate baseUpdate = partitionUpdateSerializer.deserialize(in, version); TxnReferenceOperations referenceOps = TxnReferenceOperations.serializer.deserialize(in, version); @@ -321,10 +323,10 @@ public class TxnWrite extends AbstractKeySorted implements Writ } @Override - public long serializedSize(Fragment fragment, int version) + public long serializedSize(Fragment fragment, Version version) { long size = 0; - size += PartitionKey.serializer.serializedSize(fragment.key, version); + size += PartitionKey.serializer.serializedSize(fragment.key); size += TypeSizes.sizeofUnsignedVInt(fragment.index); size += partitionUpdateSerializer.serializedSize(fragment.baseUpdate, version); size += TxnReferenceOperations.serializer.serializedSize(fragment.referenceOps, version); @@ -423,23 +425,23 @@ public class TxnWrite extends AbstractKeySorted implements Writ public static final IVersionedSerializer serializer = new IVersionedSerializer() { @Override - public void serialize(TxnWrite write, DataOutputPlus out, int version) throws IOException + public void serialize(TxnWrite write, DataOutputPlus out, Version version) throws IOException { - BooleanSerializer.serializer.serialize(write.isConditionMet, out, version); + BooleanSerializer.serializer.serialize(write.isConditionMet, out); serializeArray(write.items, out, version, Update.serializer); } @Override - public TxnWrite deserialize(DataInputPlus in, int version) throws IOException + public TxnWrite deserialize(DataInputPlus in, Version version) throws IOException { - boolean isConditionMet = BooleanSerializer.serializer.deserialize(in, version); + boolean isConditionMet = BooleanSerializer.serializer.deserialize(in); return new TxnWrite(deserializeArray(in, version, Update.serializer, Update[]::new), isConditionMet); } @Override - public long serializedSize(TxnWrite write, int version) + public long serializedSize(TxnWrite write, Version version) { - return BooleanSerializer.serializer.serializedSize(write.isConditionMet, version) + serializedArraySize(write.items, version, Update.serializer); + return BooleanSerializer.serializer.serializedSize(write.isConditionMet) + serializedArraySize(write.items, version, Update.serializer); } }; } diff --git a/src/java/org/apache/cassandra/service/accord/txn/UnrecoverableRepairUpdate.java b/src/java/org/apache/cassandra/service/accord/txn/UnrecoverableRepairUpdate.java index dfd35f93e2..b1193179b9 100644 --- a/src/java/org/apache/cassandra/service/accord/txn/UnrecoverableRepairUpdate.java +++ b/src/java/org/apache/cassandra/service/accord/txn/UnrecoverableRepairUpdate.java @@ -40,6 +40,7 @@ import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.Endpoints; import org.apache.cassandra.locator.Replica; import org.apache.cassandra.locator.ReplicaPlan; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.reads.ReadCoordinator; import org.apache.cassandra.service.reads.repair.BlockingReadRepair; @@ -181,18 +182,18 @@ public class UnrecoverableRepairUpdate, P extends Replica public static final AccordUpdateSerializer serializer = new AccordUpdateSerializer<>() { @Override - public void serialize(UnrecoverableRepairUpdate update, DataOutputPlus out, int version) + public void serialize(UnrecoverableRepairUpdate update, DataOutputPlus out, Version version) { } @Override - public UnrecoverableRepairUpdate deserialize(DataInputPlus in, int version) + public UnrecoverableRepairUpdate deserialize(DataInputPlus in, Version version) { return null; } @Override - public long serializedSize(UnrecoverableRepairUpdate update, int version) + public long serializedSize(UnrecoverableRepairUpdate update, Version version) { return 0; } diff --git a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusKeyMigrationState.java b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusKeyMigrationState.java index 5f3df247bd..4078b379b2 100644 --- a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusKeyMigrationState.java +++ b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusKeyMigrationState.java @@ -48,7 +48,7 @@ import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.WriteType; import org.apache.cassandra.exceptions.CasWriteTimeoutException; import org.apache.cassandra.exceptions.RetryOnDifferentSystemException; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.EndpointsForToken; @@ -118,31 +118,31 @@ public abstract class ConsensusKeyMigrationState this.consensusMigratedAt = consensusMigratedAt; } - public static final IVersionedSerializer serializer = new IVersionedSerializer() + public static final UnversionedSerializer serializer = new UnversionedSerializer() { @Override - public void serialize(ConsensusKeyMigrationFinished t, DataOutputPlus out, int version) throws IOException + public void serialize(ConsensusKeyMigrationFinished t, DataOutputPlus out) throws IOException { - UUIDSerializer.serializer.serialize(t.tableId, out, version); + UUIDSerializer.serializer.serialize(t.tableId, out); ByteBufferUtil.writeWithVIntLength(t.partitionKey, out); - ConsensusMigratedAt.serializer.serialize(t.consensusMigratedAt, out, version); + ConsensusMigratedAt.serializer.serialize(t.consensusMigratedAt, out); } @Override - public ConsensusKeyMigrationFinished deserialize(DataInputPlus in, int version) throws IOException + public ConsensusKeyMigrationFinished deserialize(DataInputPlus in) throws IOException { - UUID tableId = UUIDSerializer.serializer.deserialize(in, version); + UUID tableId = UUIDSerializer.serializer.deserialize(in); ByteBuffer partitionKey = ByteBufferUtil.readWithVIntLength(in); - ConsensusMigratedAt consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in, version); + ConsensusMigratedAt consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in); return new ConsensusKeyMigrationFinished(tableId, partitionKey, consensusMigratedAt); } @Override - public long serializedSize(ConsensusKeyMigrationFinished t, int version) + public long serializedSize(ConsensusKeyMigrationFinished t) { - return UUIDSerializer.serializer.serializedSize(t.tableId, version) + return UUIDSerializer.serializer.serializedSize(t.tableId) + ByteBufferUtil.serializedSizeWithVIntLength(t.partitionKey) - + ConsensusMigratedAt.serializer.serializedSize(t.consensusMigratedAt, version); + + ConsensusMigratedAt.serializer.serializedSize(t.consensusMigratedAt); } }; } diff --git a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusMigratedAt.java b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusMigratedAt.java index 2b995bdcc6..bf3e798466 100644 --- a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusMigratedAt.java +++ b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusMigratedAt.java @@ -22,7 +22,7 @@ import java.io.IOException; import javax.annotation.Nullable; import org.apache.cassandra.db.TypeSizes; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.tcm.Epoch; @@ -30,28 +30,28 @@ import org.apache.cassandra.utils.NullableSerializer; public class ConsensusMigratedAt { - public static final IVersionedSerializer serializer = NullableSerializer.wrap(new IVersionedSerializer() + public static final UnversionedSerializer serializer = NullableSerializer.wrap(new UnversionedSerializer() { @Override - public void serialize(ConsensusMigratedAt t, DataOutputPlus out, int version) throws IOException + public void serialize(ConsensusMigratedAt t, DataOutputPlus out) throws IOException { - Epoch.messageSerializer.serialize(t.migratedAtEpoch, out, version); + Epoch.serializer.serialize(t.migratedAtEpoch, out); out.writeByte(t.migratedAtTarget.value); } @Override - public ConsensusMigratedAt deserialize(DataInputPlus in, int version) throws IOException + public ConsensusMigratedAt deserialize(DataInputPlus in) throws IOException { - Epoch migratedAtEpoch = Epoch.messageSerializer.deserialize(in, version); + Epoch migratedAtEpoch = Epoch.serializer.deserialize(in); ConsensusMigrationTarget target = ConsensusMigrationTarget.fromValue(in.readByte()); return new ConsensusMigratedAt(migratedAtEpoch, target); } @Override - public long serializedSize(ConsensusMigratedAt t, int version) + public long serializedSize(ConsensusMigratedAt t) { return TypeSizes.sizeof(ConsensusMigrationTarget.accord.value) - + Epoch.messageSerializer.serializedSize(t.migratedAtEpoch, version); + + Epoch.serializer.serializedSize(t.migratedAtEpoch); } }); diff --git a/src/java/org/apache/cassandra/service/paxos/PaxosPrepare.java b/src/java/org/apache/cassandra/service/paxos/PaxosPrepare.java index 02efebbeb2..b1fb0e5cd6 100644 --- a/src/java/org/apache/cassandra/service/paxos/PaxosPrepare.java +++ b/src/java/org/apache/cassandra/service/paxos/PaxosPrepare.java @@ -1291,7 +1291,7 @@ public class PaxosPrepare extends PaxosRequestCallback im promised.supersededBy.serialize(out); } if (version >= MessagingService.VERSION_51) - ConsensusMigratedAt.serializer.serialize(response.maybeConsenusMigratedAt, out, version); + ConsensusMigratedAt.serializer.serialize(response.maybeConsenusMigratedAt, out); } public Response deserialize(DataInputPlus in, int version) throws IOException @@ -1302,7 +1302,7 @@ public class PaxosPrepare extends PaxosRequestCallback im Ballot supersededBy = Ballot.deserialize(in); ConsensusMigratedAt consensusMigratedAt = null; if (version >= MessagingService.VERSION_51) - consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in, version); + consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in); return new Rejected(supersededBy, consensusMigratedAt); } else @@ -1320,7 +1320,7 @@ public class PaxosPrepare extends PaxosRequestCallback im supersededBy = Ballot.deserialize(in); ConsensusMigratedAt consensusMigratedAt = null; if (version >= MessagingService.VERSION_51) - consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in, version); + consensusMigratedAt = ConsensusMigratedAt.serializer.deserialize(in); return new Permitted(outcome, consensusMigratedAt, lowBound, acceptedNotCommitted, committed, readResponse, hasProposalStability, gossipInfo, electorateEpoch, supersededBy); } } @@ -1344,7 +1344,7 @@ public class PaxosPrepare extends PaxosRequestCallback im + (permitted.outcome == PERMIT_READ ? Ballot.sizeInBytes() : 0); } if (version >= MessagingService.VERSION_51) - size += ConsensusMigratedAt.serializer.serializedSize(response.maybeConsenusMigratedAt, version); + size += ConsensusMigratedAt.serializer.serializedSize(response.maybeConsenusMigratedAt); return size; } diff --git a/src/java/org/apache/cassandra/tcm/Epoch.java b/src/java/org/apache/cassandra/tcm/Epoch.java index 6ddc86b456..c7e9fe7194 100644 --- a/src/java/org/apache/cassandra/tcm/Epoch.java +++ b/src/java/org/apache/cassandra/tcm/Epoch.java @@ -26,6 +26,7 @@ import java.util.Set; import com.google.common.collect.Sets; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.tcm.serialization.MetadataSerializer; @@ -176,34 +177,40 @@ public class Epoch implements Comparable, Serializable return epoch; } - public static class EpochSerializer implements MetadataSerializer + public static class EpochSerializer implements MetadataSerializer, UnversionedSerializer { // convenience methods for messageSerializer et al + @Override public void serialize(Epoch t, DataOutputPlus out) throws IOException { serialize(t, out, Version.V0); } + @Override public Epoch deserialize(DataInputPlus in) throws IOException { return deserialize(in, Version.V0); } + @Override public long serializedSize(Epoch t) { return serializedSize(t, Version.V0); } + @Override public void serialize(Epoch t, DataOutputPlus out, Version version) throws IOException { out.writeUnsignedVInt(t.epoch); } + @Override public Epoch deserialize(DataInputPlus in, Version version) throws IOException { return Epoch.create(in.readUnsignedVInt()); } + @Override public long serializedSize(Epoch t, Version version) { return VIntCoding.computeUnsignedVIntSize(t.epoch); diff --git a/src/java/org/apache/cassandra/tcm/transformations/ReconfigureAccordFastPath.java b/src/java/org/apache/cassandra/tcm/transformations/ReconfigureAccordFastPath.java index 32478c0d76..e8feef342b 100644 --- a/src/java/org/apache/cassandra/tcm/transformations/ReconfigureAccordFastPath.java +++ b/src/java/org/apache/cassandra/tcm/transformations/ReconfigureAccordFastPath.java @@ -82,7 +82,7 @@ public class ReconfigureAccordFastPath implements Transformation public void serialize(Transformation t, DataOutputPlus out, Version version) throws IOException { ReconfigureAccordFastPath update = (ReconfigureAccordFastPath) t; - TopologySerializers.nodeId.serialize(update.node, out, version); + TopologySerializers.nodeId.serialize(update.node, out); AccordFastPath.Status.serializer.serialize(update.status, out, version); out.writeUnsignedVInt(update.updateTimeMillis); out.writeUnsignedVInt(update.updateDelayMillis); @@ -91,7 +91,7 @@ public class ReconfigureAccordFastPath implements Transformation public ReconfigureAccordFastPath deserialize(DataInputPlus in, Version version) throws IOException { - return new ReconfigureAccordFastPath(TopologySerializers.nodeId.deserialize(in, version), + return new ReconfigureAccordFastPath(TopologySerializers.nodeId.deserialize(in), AccordFastPath.Status.serializer.deserialize(in, version), in.readUnsignedVInt(), in.readUnsignedVInt()); } @@ -99,7 +99,7 @@ public class ReconfigureAccordFastPath implements Transformation public long serializedSize(Transformation t, Version version) { ReconfigureAccordFastPath update = (ReconfigureAccordFastPath) t; - return TopologySerializers.nodeId.serializedSize(update.node, version) + + return TopologySerializers.nodeId.serializedSize(update.node) + AccordFastPath.Status.serializer.serializedSize(update.status, version) + TypeSizes.sizeofUnsignedVInt(update.updateTimeMillis) + TypeSizes.sizeofUnsignedVInt(update.updateDelayMillis); diff --git a/src/java/org/apache/cassandra/utils/ArraySerializers.java b/src/java/org/apache/cassandra/utils/ArraySerializers.java index 63ee3029c7..5f40dac7ef 100644 --- a/src/java/org/apache/cassandra/utils/ArraySerializers.java +++ b/src/java/org/apache/cassandra/utils/ArraySerializers.java @@ -21,7 +21,9 @@ package org.apache.cassandra.utils; import java.io.IOException; import java.util.function.IntFunction; +import org.apache.cassandra.io.AsymmetricVersionedSerializer; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; @@ -29,6 +31,13 @@ import static org.apache.cassandra.db.TypeSizes.sizeofUnsignedVInt; public class ArraySerializers { + public static void serializeArray(T[] items, DataOutputPlus out, UnversionedSerializer serializer) throws IOException + { + out.writeUnsignedVInt32(items.length); + for (T item : items) + serializer.serialize(item, out); + } + public static void serializeArray(T[] items, DataOutputPlus out, int version, IVersionedSerializer serializer) throws IOException { out.writeUnsignedVInt32(items.length); @@ -36,6 +45,22 @@ public class ArraySerializers serializer.serialize(item, out, version); } + public static void serializeArray(T[] items, DataOutputPlus out, Version version, AsymmetricVersionedSerializer serializer) throws IOException + { + out.writeUnsignedVInt32(items.length); + for (T item : items) + serializer.serialize(item, out, version); + } + + public static T[] deserializeArray(DataInputPlus in, UnversionedSerializer serializer, IntFunction arrayFactory) throws IOException + { + int size = in.readUnsignedVInt32(); + T[] items = arrayFactory.apply(size); + for (int i = 0; i < size; i++) + items[i] = serializer.deserialize(in); + return items; + } + public static T[] deserializeArray(DataInputPlus in, int version, IVersionedSerializer serializer, IntFunction arrayFactory) throws IOException { int size = in.readUnsignedVInt32(); @@ -45,6 +70,23 @@ public class ArraySerializers return items; } + public static T[] deserializeArray(DataInputPlus in, Version version, AsymmetricVersionedSerializer serializer, IntFunction arrayFactory) throws IOException + { + int size = in.readUnsignedVInt32(); + T[] items = arrayFactory.apply(size); + for (int i = 0; i < size; i++) + items[i] = serializer.deserialize(in, version); + return items; + } + + public static long serializedArraySize(T[] array, UnversionedSerializer serializer) + { + long size = sizeofUnsignedVInt(array.length); + for (T item : array) + size += serializer.serializedSize(item); + return size; + } + public static long serializedArraySize(T[] array, int version, IVersionedSerializer serializer) { long size = sizeofUnsignedVInt(array.length); @@ -52,4 +94,12 @@ public class ArraySerializers size += serializer.serializedSize(item, version); return size; } + + public static long serializedArraySize(T[] array, Version version, AsymmetricVersionedSerializer serializer) + { + long size = sizeofUnsignedVInt(array.length); + for (T item : array) + size += serializer.serializedSize(item, version); + return size; + } } diff --git a/src/java/org/apache/cassandra/utils/BooleanSerializer.java b/src/java/org/apache/cassandra/utils/BooleanSerializer.java index 1fe7702068..f130edea15 100644 --- a/src/java/org/apache/cassandra/utils/BooleanSerializer.java +++ b/src/java/org/apache/cassandra/utils/BooleanSerializer.java @@ -20,24 +20,26 @@ package org.apache.cassandra.utils; import java.io.IOException; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; -public class BooleanSerializer implements IVersionedSerializer +public class BooleanSerializer implements UnversionedSerializer { public static BooleanSerializer serializer = new BooleanSerializer(); + public static IVersionedSerializer messagingSerializer = IVersionedSerializer.from(serializer); - public void serialize(Boolean b, DataOutputPlus out, int version) throws IOException + public void serialize(Boolean b, DataOutputPlus out) throws IOException { out.writeBoolean(b); } - public Boolean deserialize(DataInputPlus in, int version) throws IOException + public Boolean deserialize(DataInputPlus in) throws IOException { return in.readBoolean(); } - public long serializedSize(Boolean aBoolean, int version) + public long serializedSize(Boolean aBoolean) { return 1; } diff --git a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java index 332dcf955a..6bdea57d68 100644 --- a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java +++ b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java @@ -54,10 +54,9 @@ import org.apache.cassandra.db.marshal.ListType; import org.apache.cassandra.db.marshal.MapType; import org.apache.cassandra.db.marshal.SetType; import org.apache.cassandra.db.marshal.TimestampType; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.compress.BufferType; import org.apache.cassandra.io.util.DataInputPlus; -import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.io.util.FileUtils; @@ -1020,19 +1019,6 @@ public class ByteBufferUtil } } - public static ByteBuffer serialized(IVersionedSerializer serializer, T value, int version) - { - try (DataOutputBuffer dob = new DataOutputBuffer()) - { - serializer.serialize(value, dob, version); - return dob.buffer(); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - public static void writeLeastSignificantBytes(long register, int bytes, ByteBuffer out) { writeMostSignificantBytes(register << ((8 - bytes)*8), bytes, out); @@ -1131,26 +1117,26 @@ public class ByteBufferUtil } } - public static final IVersionedSerializer byteBufferSerializer = new IVersionedSerializer() + public static final UnversionedSerializer byteBufferSerializer = new UnversionedSerializer() { @Override - public void serialize(ByteBuffer bytes, DataOutputPlus out, int version) throws IOException + public void serialize(ByteBuffer bytes, DataOutputPlus out) throws IOException { writeWithVIntLength(bytes, out); } @Override - public ByteBuffer deserialize(DataInputPlus in, int version) throws IOException + public ByteBuffer deserialize(DataInputPlus in) throws IOException { return readWithVIntLength(in); } @Override - public long serializedSize(ByteBuffer bytes, int version) + public long serializedSize(ByteBuffer bytes) { return serializedSizeWithVIntLength(bytes); } }; - public static final IVersionedSerializer nullableByteBufferSerializer = NullableSerializer.wrap(byteBufferSerializer); + public static final UnversionedSerializer nullableByteBufferSerializer = NullableSerializer.wrap(byteBufferSerializer); } \ No newline at end of file diff --git a/src/java/org/apache/cassandra/utils/CastingSerializer.java b/src/java/org/apache/cassandra/utils/CastingSerializer.java index 6dccb40bbe..a180aa24e3 100644 --- a/src/java/org/apache/cassandra/utils/CastingSerializer.java +++ b/src/java/org/apache/cassandra/utils/CastingSerializer.java @@ -20,45 +20,90 @@ package org.apache.cassandra.utils; import java.io.IOException; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; /** * Utility for serializing/deserializing from/into generic interface fields where we know (and require) the * generic fields to be implementation specific classes - * @param - * @param */ -public class CastingSerializer implements IVersionedSerializer +public class CastingSerializer { - private final Class specificClass; - private final IVersionedSerializer specificSerializer; - - public CastingSerializer(Class specificClass, IVersionedSerializer specificSerializer) + public static VersionedSerializer create(Class specificClass, VersionedSerializer specificSerializer) { - this.specificClass = specificClass; - this.specificSerializer = specificSerializer; + return new Versioned<>(specificClass, specificSerializer); } - @Override - public void serialize(Generic generic, DataOutputPlus out, int version) throws IOException + public static UnversionedSerializer create(Class specificClass, UnversionedSerializer specificSerializer) { - specificSerializer.serialize(specificClass.cast(generic), out, version); + return new Unversioned<>(specificClass, specificSerializer); } - @Override - public Generic deserialize(DataInputPlus in, int version) throws IOException + private static final class Versioned implements VersionedSerializer { - Generic result = specificSerializer.deserialize(in, version); - if (result != null && !specificClass.isInstance(result)) - throw new IllegalStateException("Expected instance of " + specificClass.getName()); - return result; + private final Class specificClass; + private final VersionedSerializer specificSerializer; + + private Versioned(Class specificClass, VersionedSerializer specificSerializer) + { + this.specificClass = specificClass; + this.specificSerializer = specificSerializer; + } + + @Override + public void serialize(Generic generic, DataOutputPlus out, Version version) throws IOException + { + specificSerializer.serialize(specificClass.cast(generic), out, version); + } + + @Override + public Generic deserialize(DataInputPlus in, Version version) throws IOException + { + Generic result = specificSerializer.deserialize(in, version); + if (result != null && !specificClass.isInstance(result)) + throw new IllegalStateException("Expected instance of " + specificClass.getName()); + return result; + } + + @Override + public long serializedSize(Generic generic, Version version) + { + return specificSerializer.serializedSize(specificClass.cast(generic), version); + } } - @Override - public long serializedSize(Generic generic, int version) + private static final class Unversioned implements UnversionedSerializer { - return specificSerializer.serializedSize(specificClass.cast(generic), version); + private final Class specificClass; + private final UnversionedSerializer specificSerializer; + + private Unversioned(Class specificClass, UnversionedSerializer specificSerializer) + { + this.specificClass = specificClass; + this.specificSerializer = specificSerializer; + } + + @Override + public void serialize(Generic generic, DataOutputPlus out) throws IOException + { + specificSerializer.serialize(specificClass.cast(generic), out); + } + + @Override + public Generic deserialize(DataInputPlus in) throws IOException + { + Generic result = specificSerializer.deserialize(in); + if (result != null && !specificClass.isInstance(result)) + throw new IllegalStateException("Expected instance of " + specificClass.getName()); + return result; + } + + @Override + public long serializedSize(Generic generic) + { + return specificSerializer.serializedSize(specificClass.cast(generic)); + } } } diff --git a/src/java/org/apache/cassandra/utils/CollectionSerializers.java b/src/java/org/apache/cassandra/utils/CollectionSerializers.java index fe5cc78031..2b61377bb8 100644 --- a/src/java/org/apache/cassandra/utils/CollectionSerializers.java +++ b/src/java/org/apache/cassandra/utils/CollectionSerializers.java @@ -34,7 +34,10 @@ import com.google.common.collect.Sets; import accord.utils.SortedArrays.SortedArrayList; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.IPartitionerDependentSerializer; +import org.apache.cassandra.io.AsymmetricVersionedSerializer; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.tcm.serialization.MetadataSerializer; @@ -44,6 +47,13 @@ import static org.apache.cassandra.db.TypeSizes.sizeofUnsignedVInt; public class CollectionSerializers { + public static void serializeCollection(Collection values, DataOutputPlus out, UnversionedSerializer valueSerializer) throws IOException + { + out.writeUnsignedVInt32(values.size()); + for (V value : values) + valueSerializer.serialize(value, out); + } + public static void serializeCollection(Collection values, DataOutputPlus out, int version, IVersionedSerializer valueSerializer) throws IOException { out.writeUnsignedVInt32(values.size()); @@ -51,6 +61,13 @@ public class CollectionSerializers valueSerializer.serialize(value, out, version); } + public static void serializeCollection(Collection values, DataOutputPlus out, Version version, AsymmetricVersionedSerializer valueSerializer) throws IOException + { + out.writeUnsignedVInt32(values.size()); + for (V value : values) + valueSerializer.serialize(value, out, version); + } + public static void serializeCollection(Collection values, DataOutputPlus out, Version version, MetadataSerializer valueSerializer) throws IOException { out.writeUnsignedVInt32(values.size()); @@ -65,6 +82,14 @@ public class CollectionSerializers valueSerializer.serialize(value, out, version); } + public static > void serializeList(L values, DataOutputPlus out, UnversionedSerializer valueSerializer) throws IOException + { + int size = values.size(); + out.writeUnsignedVInt32(size); + for (int i = 0 ; i < size ; ++i) + valueSerializer.serialize(values.get(i), out); + } + public static > void serializeList(L values, DataOutputPlus out, int version, IVersionedSerializer valueSerializer) throws IOException { int size = values.size(); @@ -73,17 +98,33 @@ public class CollectionSerializers valueSerializer.serialize(values.get(i), out, version); } - public static void serializeMap(Map map, DataOutputPlus out, int version, IVersionedSerializer keySerializer, IVersionedSerializer valueSerializer) throws IOException + public static , Version> void serializeList(L values, DataOutputPlus out, Version version, AsymmetricVersionedSerializer valueSerializer) throws IOException + { + int size = values.size(); + out.writeUnsignedVInt32(size); + for (int i = 0 ; i < size ; ++i) + valueSerializer.serialize(values.get(i), out, version); + } + + public static > void serializeList(L values, DataOutputPlus out, Version version, MetadataSerializer valueSerializer) throws IOException + { + int size = values.size(); + out.writeUnsignedVInt32(size); + for (int i = 0 ; i < size ; ++i) + valueSerializer.serialize(values.get(i), out, version); + } + + public static void serializeMap(Map map, DataOutputPlus out, UnversionedSerializer keySerializer, UnversionedSerializer valueSerializer) throws IOException { out.writeUnsignedVInt32(map.size()); for (Map.Entry e : map.entrySet()) { - keySerializer.serialize(e.getKey(), out, version); - valueSerializer.serialize(e.getValue(), out, version); + keySerializer.serialize(e.getKey(), out); + valueSerializer.serialize(e.getValue(), out); } } - public static void serializeMap(Map map, DataOutputPlus out, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer) throws IOException + public static void serializeMap(Map map, DataOutputPlus out, int version, IVersionedSerializer keySerializer, IVersionedSerializer valueSerializer) throws IOException { out.writeUnsignedVInt32(map.size()); for (Map.Entry e : map.entrySet()) @@ -103,20 +144,50 @@ public class CollectionSerializers } } - public static > SortedArrayList deserializeSortedArrayList(DataInputPlus in, int version, IVersionedSerializer serializer, IntFunction allocator) throws IOException + public static void serializeMap(Map map, DataOutputPlus out, Version version, AsymmetricVersionedSerializer keySerializer, AsymmetricVersionedSerializer valueSerializer) throws IOException + { + out.writeUnsignedVInt32(map.size()); + for (Map.Entry e : map.entrySet()) + { + keySerializer.serialize(e.getKey(), out, version); + valueSerializer.serialize(e.getValue(), out, version); + } + } + + public static void serializeMap(Map map, DataOutputPlus out, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer) throws IOException + { + out.writeUnsignedVInt32(map.size()); + for (Map.Entry e : map.entrySet()) + { + keySerializer.serialize(e.getKey(), out, version); + valueSerializer.serialize(e.getValue(), out, version); + } + } + + public static > SortedArrayList deserializeSortedArrayList(DataInputPlus in, UnversionedSerializer serializer, IntFunction allocator) throws IOException { int size = in.readUnsignedVInt32(); V[] array = allocator.apply(size); for (int i = 0 ; i < array.length ; ++i) - array[i] = serializer.deserialize(in, version); + array[i] = serializer.deserialize(in); return new SortedArrayList<>(array); } + public static List deserializeList(DataInputPlus in, UnversionedSerializer serializer) throws IOException + { + return deserializeCollection(in, serializer, newArrayList()); + } + public static List deserializeList(DataInputPlus in, int version, IVersionedSerializer serializer) throws IOException { return deserializeCollection(in, version, serializer, newArrayList()); } + public static List deserializeList(DataInputPlus in, Version version, AsymmetricVersionedSerializer serializer) throws IOException + { + return deserializeCollection(in, version, serializer, newArrayList()); + } + public static List deserializeList(DataInputPlus in, Version version, MetadataSerializer serializer) throws IOException { return deserializeCollection(in, version, serializer, newArrayList()); @@ -127,6 +198,11 @@ public class CollectionSerializers return deserializeCollection(in, partitioner, version, serializer, newArrayList()); } + public static Set deserializeSet(DataInputPlus in, UnversionedSerializer serializer) throws IOException + { + return deserializeCollection(in, serializer, newHashSet()); + } + public static Set deserializeSet(DataInputPlus in, int version, IVersionedSerializer serializer) throws IOException { return deserializeCollection(in, version, serializer, newHashSet()); @@ -137,11 +213,29 @@ public class CollectionSerializers return deserializeCollection(in, partitioner, version, serializer, newHashSet()); } + public static Set deserializeSet(DataInputPlus in, Version version, AsymmetricVersionedSerializer serializer) throws IOException + { + return deserializeCollection(in, version, serializer, newHashSet()); + } + public static Set deserializeSet(DataInputPlus in, Version version, MetadataSerializer serializer) throws IOException { return deserializeCollection(in, version, serializer, newHashSet()); } + public static > M deserializeMap(DataInputPlus in, UnversionedSerializer keySerializer, UnversionedSerializer valueSerializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + M result = factory.apply(size); + while (size-- > 0) + { + K key = keySerializer.deserialize(in); + V value = valueSerializer.deserialize(in); + result.put(key, value); + } + return result; + } + public static > M deserializeMap(DataInputPlus in, int version, IVersionedSerializer keySerializer, IVersionedSerializer valueSerializer, IntFunction factory) throws IOException { int size = in.readUnsignedVInt32(); @@ -155,19 +249,6 @@ public class CollectionSerializers return result; } - public static Map deserializeMap(DataInputPlus in, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer, IntFunction> factory) throws IOException - { - int size = in.readUnsignedVInt32(); - Map result = factory.apply(size); - while (size-- > 0) - { - K key = keySerializer.deserialize(in, version); - V value = valueSerializer.deserialize(in, version); - result.put(key, value); - } - return result; - } - public static Map deserializeMap(DataInputPlus in, IPartitioner partitioner, int version, IVersionedSerializer keySerializer, IPartitionerDependentSerializer valueSerializer, IntFunction> factory) throws IOException { int size = in.readUnsignedVInt32(); @@ -181,20 +262,61 @@ public class CollectionSerializers return result; } + public static , Version> M deserializeMap(DataInputPlus in, Version version, AsymmetricVersionedSerializer keySerializer, AsymmetricVersionedSerializer valueSerializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + M result = factory.apply(size); + while (size-- > 0) + { + K key = keySerializer.deserialize(in, version); + V value = valueSerializer.deserialize(in, version); + result.put(key, value); + } + return result; + } + + public static > M deserializeMap(DataInputPlus in, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + M result = factory.apply(size); + while (size-- > 0) + { + K key = keySerializer.deserialize(in, version); + V value = valueSerializer.deserialize(in, version); + result.put(key, value); + } + return result; + } + + public static Map deserializeMap(DataInputPlus in, UnversionedSerializer keySerializer, UnversionedSerializer valueSerializer) throws IOException + { + return deserializeMap(in, keySerializer, valueSerializer, Maps::newHashMapWithExpectedSize); + } + public static Map deserializeMap(DataInputPlus in, int version, IVersionedSerializer keySerializer, IVersionedSerializer valueSerializer) throws IOException { return deserializeMap(in, version, keySerializer, valueSerializer, Maps::newHashMapWithExpectedSize); } - public static long serializedCollectionSize(Collection values, int version, IVersionedSerializer valueSerializer) + public static Map deserializeMap(DataInputPlus in, Version version, AsymmetricVersionedSerializer keySerializer, AsymmetricVersionedSerializer valueSerializer) throws IOException + { + return deserializeMap(in, version, keySerializer, valueSerializer, Maps::newHashMapWithExpectedSize); + } + + public static Map deserializeMap(DataInputPlus in, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer) throws IOException + { + return deserializeMap(in, version, keySerializer, valueSerializer, Maps::newHashMapWithExpectedSize); + } + + public static long serializedCollectionSize(Collection values, UnversionedSerializer valueSerializer) { long size = sizeofUnsignedVInt(values.size()); for (V value : values) - size += valueSerializer.serializedSize(value, version); + size += valueSerializer.serializedSize(value); return size; } - public static long serializedCollectionSize(Collection values, Version version, MetadataSerializer valueSerializer) + public static long serializedCollectionSize(Collection values, int version, IVersionedSerializer valueSerializer) { long size = sizeofUnsignedVInt(values.size()); for (V value : values) @@ -210,6 +332,31 @@ public class CollectionSerializers return size; } + public static long serializedCollectionSize(Collection values, Version version, AsymmetricVersionedSerializer valueSerializer) + { + long size = sizeofUnsignedVInt(values.size()); + for (V value : values) + size += valueSerializer.serializedSize(value, version); + return size; + } + + public static long serializedCollectionSize(Collection values, Version version, MetadataSerializer valueSerializer) + { + long size = sizeofUnsignedVInt(values.size()); + for (V value : values) + size += valueSerializer.serializedSize(value, version); + return size; + } + + public static > long serializedListSize(L values, UnversionedSerializer valueSerializer) + { + int items = values.size(); + long size = sizeofUnsignedVInt(items); + for (int i = 0 ; i < items ; ++i) + size += valueSerializer.serializedSize(values.get(i)); + return size; + } + public static > long serializedListSize(L values, int version, IVersionedSerializer valueSerializer) { int items = values.size(); @@ -219,6 +366,33 @@ public class CollectionSerializers return size; } + public static , Version> long serializedListSize(L values, Version version, AsymmetricVersionedSerializer valueSerializer) + { + int items = values.size(); + long size = sizeofUnsignedVInt(items); + for (int i = 0 ; i < items ; ++i) + size += valueSerializer.serializedSize(values.get(i), version); + return size; + } + + public static > long serializedListSize(L values, Version version, MetadataSerializer valueSerializer) + { + int items = values.size(); + long size = sizeofUnsignedVInt(items); + for (int i = 0 ; i < items ; ++i) + size += valueSerializer.serializedSize(values.get(i), version); + return size; + } + + public static long serializedMapSize(Map map, UnversionedSerializer keySerializer, UnversionedSerializer valueSerializer) + { + long size = sizeofUnsignedVInt(map.size()); + for (Map.Entry e : map.entrySet()) + size += keySerializer.serializedSize(e.getKey()) + + valueSerializer.serializedSize(e.getValue()); + return size; + } + public static long serializedMapSize(Map map, int version, IVersionedSerializer keySerializer, IVersionedSerializer valueSerializer) { long size = sizeofUnsignedVInt(map.size()); @@ -228,7 +402,7 @@ public class CollectionSerializers return size; } - public static long serializedMapSize(Map map, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer) + public static long serializedMapSize(Map map, int version, IVersionedSerializer keySerializer, IPartitionerDependentSerializer valueSerializer) { long size = sizeofUnsignedVInt(map.size()); for (Map.Entry e : map.entrySet()) @@ -237,7 +411,16 @@ public class CollectionSerializers return size; } - public static long serializedMapSize(Map map, int version, IVersionedSerializer keySerializer, IPartitionerDependentSerializer valueSerializer) + public static long serializedMapSize(Map map, Version version, AsymmetricVersionedSerializer keySerializer, AsymmetricVersionedSerializer valueSerializer) + { + long size = sizeofUnsignedVInt(map.size()); + for (Map.Entry e : map.entrySet()) + size += keySerializer.serializedSize(e.getKey(), version) + + valueSerializer.serializedSize(e.getValue(), version); + return size; + } + + public static long serializedMapSize(Map map, Version version, MetadataSerializer keySerializer, MetadataSerializer valueSerializer) { long size = sizeofUnsignedVInt(map.size()); for (Map.Entry e : map.entrySet()) @@ -266,6 +449,19 @@ public class CollectionSerializers return in.readUnsignedVInt32(); } + /* + * Private to push auto-complete to the convenience methods + * Feel free to make public if there is a weird collection you want to use + */ + private static > C deserializeCollection(DataInputPlus in, UnversionedSerializer serializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + C result = factory.apply(size); + while (size-- > 0) + result.add(serializer.deserialize(in)); + return result; + } + /* * Private to push auto-complete to the convenience methods * Feel free to make public if there is a weird collection you want to use @@ -279,6 +475,57 @@ public class CollectionSerializers return result; } + private static > C deserializeCollection(DataInputPlus in, IPartitioner partitioner, int version, IPartitionerDependentSerializer serializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + C result = factory.apply(size); + while (size-- > 0) + result.add(serializer.deserialize(in, partitioner, version)); + return result; + } + + private static , Version> C deserializeCollection(DataInputPlus in, Version version, AsymmetricVersionedSerializer serializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + C result = factory.apply(size); + while (size-- > 0) + result.add(serializer.deserialize(in, version)); + return result; + } + + private static > C deserializeCollection(DataInputPlus in, Version version, MetadataSerializer serializer, IntFunction factory) throws IOException + { + int size = in.readUnsignedVInt32(); + C result = factory.apply(size); + while (size-- > 0) + result.add(serializer.deserialize(in, version)); + return result; + } + + public static UnversionedSerializer> newListSerializer(UnversionedSerializer itemSerializer) + { + return new UnversionedSerializer>() + { + @Override + public void serialize(List list, DataOutputPlus out) throws IOException + { + serializeList(list, out, itemSerializer); + } + + @Override + public List deserialize(DataInputPlus in) throws IOException + { + return deserializeList(in, itemSerializer); + } + + @Override + public long serializedSize(List t) + { + return serializedListSize(t, itemSerializer); + } + }; + } + public static IVersionedSerializer> newListSerializer(IVersionedSerializer itemSerializer) { return new IVersionedSerializer>() @@ -303,22 +550,28 @@ public class CollectionSerializers }; } - private static > C deserializeCollection(DataInputPlus in, IPartitioner partitioner, int version, IPartitionerDependentSerializer serializer, IntFunction factory) throws IOException + public static VersionedSerializer, Version> newListSerializer(@Nonnull final VersionedSerializer serializer) { - int size = in.readUnsignedVInt32(); - C result = factory.apply(size); - while (size-- > 0) - result.add(serializer.deserialize(in, partitioner, version)); - return result; - } + return new VersionedSerializer, Version>() + { + @Override + public void serialize(List t, DataOutputPlus out, Version version) throws IOException + { + serializeCollection(t, out, version, serializer); + } - private static > C deserializeCollection(DataInputPlus in, Version version, MetadataSerializer serializer, IntFunction factory) throws IOException - { - int size = in.readUnsignedVInt32(); - C result = factory.apply(size); - while (size-- > 0) - result.add(serializer.deserialize(in, version)); - return result; + @Override + public List deserialize(DataInputPlus in, Version version) throws IOException + { + return deserializeList(in, version, serializer); + } + + @Override + public long serializedSize(List t, Version version) + { + return serializedCollectionSize(t, version, serializer); + } + }; } public static IPartitionerDependentSerializer> newCollectionSerializer(@Nonnull final IPartitionerDependentSerializer serializer) @@ -344,28 +597,4 @@ public class CollectionSerializers } }; } - - public static MetadataSerializer> newListSerializer(@Nonnull final MetadataSerializer serializer) - { - return new MetadataSerializer>() - { - @Override - public void serialize(List t, DataOutputPlus out, Version version) throws IOException - { - serializeCollection(t, out, version, serializer); - } - - @Override - public List deserialize(DataInputPlus in, Version version) throws IOException - { - return deserializeList(in, version, serializer); - } - - @Override - public long serializedSize(List t, Version version) - { - return serializedCollectionSize(t, version, serializer); - } - }; - } } diff --git a/src/java/org/apache/cassandra/utils/Int32Serializer.java b/src/java/org/apache/cassandra/utils/Int32Serializer.java index 731f5aa038..d264d6ebca 100644 --- a/src/java/org/apache/cassandra/utils/Int32Serializer.java +++ b/src/java/org/apache/cassandra/utils/Int32Serializer.java @@ -22,25 +22,44 @@ import java.io.IOException; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; -public class Int32Serializer implements IVersionedSerializer +public class Int32Serializer implements UnversionedSerializer, IVersionedSerializer { public static final Int32Serializer serializer = new Int32Serializer(); - public void serialize(Integer t, DataOutputPlus out, int version) throws IOException + public void serialize(Integer t, DataOutputPlus out) throws IOException { out.writeInt(t); } - public Integer deserialize(DataInputPlus in, int version) throws IOException + @Override + public void serialize(Integer t, DataOutputPlus out, int version) throws IOException + { + serialize(t, out); + } + + public Integer deserialize(DataInputPlus in) throws IOException { return in.readInt(); } - public long serializedSize(Integer t, int version) + @Override + public Integer deserialize(DataInputPlus in, int version) throws IOException + { + return deserialize(in); + } + + public long serializedSize(Integer t) { return TypeSizes.sizeof(t.intValue()); } + + @Override + public long serializedSize(Integer t, int version) + { + return serializedSize(t); + } } diff --git a/src/java/org/apache/cassandra/utils/NullableSerializer.java b/src/java/org/apache/cassandra/utils/NullableSerializer.java index 7d834be995..8392bf19dc 100644 --- a/src/java/org/apache/cassandra/utils/NullableSerializer.java +++ b/src/java/org/apache/cassandra/utils/NullableSerializer.java @@ -22,11 +22,20 @@ import java.io.IOException; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; public class NullableSerializer { + public static void serializeNullable(T value, DataOutputPlus out, UnversionedSerializer serializer) throws IOException + { + out.writeBoolean(value != null); + if (value != null) + serializer.serialize(value, out); + } + public static void serializeNullable(T value, DataOutputPlus out, int version, IVersionedSerializer serializer) throws IOException { out.writeBoolean(value != null); @@ -34,11 +43,35 @@ public class NullableSerializer serializer.serialize(value, out, version); } + public static void serializeNullable(T value, DataOutputPlus out, Version version, VersionedSerializer serializer) throws IOException + { + out.writeBoolean(value != null); + if (value != null) + serializer.serialize(value, out, version); + } + + public static T deserializeNullable(DataInputPlus in, UnversionedSerializer serializer) throws IOException + { + return in.readBoolean() ? serializer.deserialize(in) : null; + } + public static T deserializeNullable(DataInputPlus in, int version, IVersionedSerializer serializer) throws IOException { return in.readBoolean() ? serializer.deserialize(in, version) : null; } + public static T deserializeNullable(DataInputPlus in, Version version, VersionedSerializer serializer) throws IOException + { + return in.readBoolean() ? serializer.deserialize(in, version) : null; + } + + public static long serializedNullableSize(T value, UnversionedSerializer serializer) + { + return value != null + ? TypeSizes.sizeof(true) + serializer.serializedSize(value) + : TypeSizes.sizeof(false); + } + public static long serializedNullableSize(T value, int version, IVersionedSerializer serializer) { return value != null @@ -46,6 +79,37 @@ public class NullableSerializer : TypeSizes.sizeof(false); } + public static long serializedNullableSize(T value, Version version, VersionedSerializer serializer) + { + return value != null + ? TypeSizes.sizeof(true) + serializer.serializedSize(value, version) + : TypeSizes.sizeof(false); + } + + public static UnversionedSerializer wrap(UnversionedSerializer wrap) + { + return new UnversionedSerializer<>() + { + @Override + public void serialize(T t, DataOutputPlus out) throws IOException + { + serializeNullable(t, out, wrap); + } + + @Override + public T deserialize(DataInputPlus in) throws IOException + { + return deserializeNullable(in, wrap); + } + + @Override + public long serializedSize(T t) + { + return serializedNullableSize(t, wrap); + } + }; + } + public static IVersionedSerializer wrap(IVersionedSerializer wrap) { return new IVersionedSerializer() { @@ -65,4 +129,27 @@ public class NullableSerializer } }; } + + public static VersionedSerializer wrap(VersionedSerializer wrap) + { + return new VersionedSerializer<>() { + @Override + public void serialize(T t, DataOutputPlus out, Version version) throws IOException + { + serializeNullable(t, out, version, wrap); + } + + @Override + public T deserialize(DataInputPlus in, Version version) throws IOException + { + return deserializeNullable(in, version, wrap); + } + + @Override + public long serializedSize(T t, Version version) + { + return serializedNullableSize(t, version, wrap); + } + }; + } } diff --git a/src/java/org/apache/cassandra/utils/TimeUUID.java b/src/java/org/apache/cassandra/utils/TimeUUID.java index 49c31478e1..a0b9698848 100644 --- a/src/java/org/apache/cassandra/utils/TimeUUID.java +++ b/src/java/org/apache/cassandra/utils/TimeUUID.java @@ -46,6 +46,7 @@ import com.google.common.hash.Hashing; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.marshal.ValueAccessor; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.locator.InetAddressAndPort; @@ -361,7 +362,7 @@ public class TimeUUID implements Serializable, Comparable } } - public static class Serializer extends AbstractSerializer implements IVersionedSerializer + public static class Serializer extends AbstractSerializer implements IVersionedSerializer, UnversionedSerializer { public static final Serializer instance = new Serializer(); @@ -381,17 +382,35 @@ public class TimeUUID implements Serializable, Comparable t.serialize(out); } + @Override + public void serialize(TimeUUID t, DataOutputPlus out) throws IOException + { + t.serialize(out); + } + @Override public TimeUUID deserialize(DataInputPlus in, int version) throws IOException { return TimeUUID.deserialize(in); } + @Override + public TimeUUID deserialize(DataInputPlus in) throws IOException + { + return TimeUUID.deserialize(in); + } + @Override public long serializedSize(TimeUUID t, int version) { return 16; } + + @Override + public long serializedSize(TimeUUID t) + { + return 16; + } } public static class Generator diff --git a/src/java/org/apache/cassandra/utils/UUIDSerializer.java b/src/java/org/apache/cassandra/utils/UUIDSerializer.java index 47b6f8c565..f1cd26d15f 100644 --- a/src/java/org/apache/cassandra/utils/UUIDSerializer.java +++ b/src/java/org/apache/cassandra/utils/UUIDSerializer.java @@ -22,25 +22,47 @@ import java.util.UUID; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; -public class UUIDSerializer implements IVersionedSerializer +public class UUIDSerializer implements IVersionedSerializer, UnversionedSerializer { public static UUIDSerializer serializer = new UUIDSerializer(); + @Override public void serialize(UUID uuid, DataOutputPlus out, int version) throws IOException + { + serialize(uuid, out); + } + + @Override + public void serialize(UUID uuid, DataOutputPlus out) throws IOException { out.writeLong(uuid.getMostSignificantBits()); out.writeLong(uuid.getLeastSignificantBits()); } + @Override public UUID deserialize(DataInputPlus in, int version) throws IOException + { + return deserialize(in); + } + + @Override + public UUID deserialize(DataInputPlus in) throws IOException { return new UUID(in.readLong(), in.readLong()); } + @Override public long serializedSize(UUID uuid, int version) + { + return serializedSize(uuid); + } + + @Override + public long serializedSize(UUID uuid) { return TypeSizes.sizeof(uuid.getMostSignificantBits()) + TypeSizes.sizeof(uuid.getLeastSignificantBits()); } diff --git a/test/distributed/org/apache/cassandra/distributed/impl/Instance.java b/test/distributed/org/apache/cassandra/distributed/impl/Instance.java index b4a0c8666e..575482c5a0 100644 --- a/test/distributed/org/apache/cassandra/distributed/impl/Instance.java +++ b/test/distributed/org/apache/cassandra/distributed/impl/Instance.java @@ -395,12 +395,14 @@ public class Instance extends IsolatedExecutor implements IInvokableInstance MessagingService.instance().outboundSink.add((message, to) -> { if (isShutdown()) return false; // TODO: Simulator needs this to trigger a failure - IMessage serialzied = serializeMessage(message.from(), to, message); int fromNum = config.num(); // since this instance is sending the message, from will always be this instance IInstance toInstance = cluster.get(fromCassandraInetAddressAndPort(to)); if (toInstance == null) return true; // TODO: Simulator needs this to trigger a failure + if (!cluster.filters().hasInbound() && !cluster.filters().hasOutbound()) + return true; // no filters... nothing to see here int toNum = toInstance.config().num(); + IMessage serialzied = serializeMessage(message.from(), to, message); return cluster.filters().permitOutbound(fromNum, toNum, serialzied); }); } diff --git a/test/distributed/org/apache/cassandra/service/accord/AccordJournalBurnTest.java b/test/distributed/org/apache/cassandra/service/accord/AccordJournalBurnTest.java index 6c983eea0c..f60026b892 100644 --- a/test/distributed/org/apache/cassandra/service/accord/AccordJournalBurnTest.java +++ b/test/distributed/org/apache/cassandra/service/accord/AccordJournalBurnTest.java @@ -59,10 +59,8 @@ import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.io.sstable.ISSTableScanner; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.util.File; -import org.apache.cassandra.journal.Params; import org.apache.cassandra.journal.SegmentCompactor; import org.apache.cassandra.journal.StaticSegment; -import org.apache.cassandra.journal.TestParams; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableMetadata; import org.apache.cassandra.schema.Tables; @@ -73,6 +71,7 @@ import org.apache.cassandra.service.accord.serializers.DepsSerializers; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.ResultSerializers; import org.apache.cassandra.service.accord.serializers.TopologySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.tools.FieldUtil; import static accord.impl.PrefixedIntHashKey.ranges; @@ -171,7 +170,7 @@ public class AccordJournalBurnTest extends BurnTestBase directory.deleteRecursiveOnExit(); ColumnFamilyStore cfs = ks.getColumnFamilyStore("journal_" + node); cfs.disableAutoCompaction(); - AccordJournal journal = new AccordJournal(new TestParams() + AccordJournal journal = new AccordJournal(new AccordJournalTestParams() { @Override public int segmentSize() @@ -206,9 +205,9 @@ public class AccordJournalBurnTest extends BurnTestBase } @Override - protected SegmentCompactor compactor(ColumnFamilyStore cfs, Params params) + protected SegmentCompactor compactor(ColumnFamilyStore cfs, Version userVersion) { - return new NemesisAccordSegmentCompactor<>(params.userVersion(), cfs, randomSource.fork()) + return new NemesisAccordSegmentCompactor<>(userVersion, cfs, randomSource.fork()) { @Nullable @Override diff --git a/test/distributed/org/apache/cassandra/service/accord/AccordJournalCompactionTest.java b/test/distributed/org/apache/cassandra/service/accord/AccordJournalCompactionTest.java index c93f320c1c..6844f58827 100644 --- a/test/distributed/org/apache/cassandra/service/accord/AccordJournalCompactionTest.java +++ b/test/distributed/org/apache/cassandra/service/accord/AccordJournalCompactionTest.java @@ -32,7 +32,6 @@ import accord.local.DurableBefore; import accord.local.RedundantBefore; import accord.primitives.Deps; import accord.primitives.KeyDeps; -import accord.primitives.Range; import accord.primitives.Ranges; import accord.primitives.Timestamp; import accord.primitives.TxnId; @@ -46,7 +45,6 @@ import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.io.util.File; -import org.apache.cassandra.journal.TestParams; import org.apache.cassandra.schema.SchemaConstants; import org.apache.cassandra.service.StorageService; import org.apache.cassandra.service.accord.api.AccordAgent; @@ -92,14 +90,11 @@ public class AccordJournalCompactionTest NavigableMap bootstrapBeganAtAccumulator = ImmutableSortedMap.of(TxnId.NONE, Ranges.EMPTY); RangesForEpoch rangesForEpochAccumulator = null; - Gen redundantBeforeGen = AccordGenerators.redundantBefore(DatabaseDescriptor.getPartitioner()); Gen durableBeforeGen = AccordGenerators.durableBeforeGen(DatabaseDescriptor.getPartitioner()); Gen> safeToReadGen = AccordGenerators.safeToReadGen(DatabaseDescriptor.getPartitioner()); Gen rangesForEpochGen = AccordGenerators.rangesForEpoch(DatabaseDescriptor.getPartitioner()); - Gen rangeGen = AccordGenerators.range(DatabaseDescriptor.getPartitioner()); - Gen historicalTransactionsGen = depsGen(); - AccordJournal journal = new AccordJournal(new TestParams() + AccordJournal journal = new AccordJournal(new AccordJournalTestParams() { @Override public int segmentSize() diff --git a/test/distributed/org/apache/cassandra/service/accord/BurnTestKeySerializers.java b/test/distributed/org/apache/cassandra/service/accord/BurnTestKeySerializers.java index 5f7b747cab..7e732566e0 100644 --- a/test/distributed/org/apache/cassandra/service/accord/BurnTestKeySerializers.java +++ b/test/distributed/org/apache/cassandra/service/accord/BurnTestKeySerializers.java @@ -41,14 +41,18 @@ import accord.primitives.Keys; import accord.primitives.Range; import accord.primitives.Seekables; import accord.primitives.TxnId; -import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.EmbeddedAsymmetricVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.service.accord.api.AccordRoutableKey; import org.apache.cassandra.service.accord.api.AccordRoutableKey.AccordSearchableKeySerializer; import org.apache.cassandra.service.accord.serializers.CommandSerializers; +import org.apache.cassandra.service.accord.serializers.IVersionedSerializer; import org.apache.cassandra.service.accord.serializers.KeySerializers; import org.apache.cassandra.service.accord.serializers.TopologySerializers; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.utils.CastingSerializer; @SuppressWarnings("unchecked") @@ -61,7 +65,8 @@ public class BurnTestKeySerializers (AccordSearchableKeySerializer) new AccordSearchableKeySerializer() { - public void serialize(PrefixedIntHashKey t, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(PrefixedIntHashKey t, DataOutputPlus out) throws IOException { assert t instanceof PrefixedIntHashKey.Key; out.writeInt(t.prefix); @@ -69,7 +74,8 @@ public class BurnTestKeySerializers out.writeInt(t.hash); } - public PrefixedIntHashKey deserialize(DataInputPlus in, int version) throws IOException + @Override + public PrefixedIntHashKey deserialize(DataInputPlus in) throws IOException { int prefix = in.readInt(); int key = in.readInt(); @@ -77,12 +83,14 @@ public class BurnTestKeySerializers return PrefixedIntHashKey.key(prefix, key, hash); } - public long serializedSize(PrefixedIntHashKey t, int version) + @Override + public long serializedSize(PrefixedIntHashKey t) { return 3 * Integer.BYTES; } - public void skip(DataInputPlus in, int version) throws IOException + @Override + public void skip(DataInputPlus in) throws IOException { in.skipBytesFully(3 * Integer.BYTES); } @@ -106,26 +114,26 @@ public class BurnTestKeySerializers } @Override - public void serializePrefix(Object prefix, DataOutputPlus out, int version) throws IOException + public void serializePrefix(Object prefix, DataOutputPlus out) throws IOException { out.writeInt((Integer) prefix); } @Override - public void serializeWithoutPrefixOrLength(PrefixedIntHashKey key, DataOutputPlus out, int version) throws IOException + public void serializeWithoutPrefixOrLength(PrefixedIntHashKey key, DataOutputPlus out) throws IOException { out.writeInt(key.hash); out.writeInt(key.key); } @Override - public Object deserializePrefix(DataInputPlus in, int version) throws IOException + public Object deserializePrefix(DataInputPlus in) throws IOException { return in.readInt(); } @Override - public PrefixedIntHashKey deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException + public PrefixedIntHashKey deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException { int key = in.readInt(); int hash = in.readInt(); @@ -138,25 +146,25 @@ public class BurnTestKeySerializers (AccordSearchableKeySerializer) new AccordSearchableKeySerializer() { - public void serialize(PrefixedIntHashKey.Hash t, DataOutputPlus out, int version) throws IOException + public void serialize(PrefixedIntHashKey.Hash t, DataOutputPlus out) throws IOException { out.writeInt(t.prefix); out.writeInt(t.hash); } - public PrefixedIntHashKey.Hash deserialize(DataInputPlus in, int version) throws IOException + public PrefixedIntHashKey.Hash deserialize(DataInputPlus in) throws IOException { int prefix = in.readInt(); int hash = in.readInt(); return new PrefixedIntHashKey.Hash(prefix, hash); } - public long serializedSize(PrefixedIntHashKey.Hash t, int version) + public long serializedSize(PrefixedIntHashKey.Hash t) { return 2 * Integer.BYTES; } - public void skip(DataInputPlus in, int version) throws IOException + public void skip(DataInputPlus in) throws IOException { in.skipBytesFully(2 * Integer.BYTES); } @@ -180,84 +188,87 @@ public class BurnTestKeySerializers } @Override - public void serializePrefix(Object prefix, DataOutputPlus out, int version) throws IOException + public void serializePrefix(Object prefix, DataOutputPlus out) throws IOException { out.writeInt((Integer) prefix); } @Override - public void serializeWithoutPrefixOrLength(PrefixedIntHashKey.Hash key, DataOutputPlus out, int version) throws IOException + public void serializeWithoutPrefixOrLength(PrefixedIntHashKey.Hash key, DataOutputPlus out) throws IOException { out.writeInt(key.hash); } @Override - public Object deserializePrefix(DataInputPlus in, int version) throws IOException + public Object deserializePrefix(DataInputPlus in) throws IOException { return in.readInt(); } @Override - public PrefixedIntHashKey.Hash deserializeWithPrefix(Object prefix, int length, DataInputPlus in, int version) throws IOException + public PrefixedIntHashKey.Hash deserializeWithPrefix(Object prefix, int length, DataInputPlus in) throws IOException { int hash = in.readInt(); return PrefixedIntHashKey.forHash((Integer)prefix, hash); } }; - public static final IVersionedSerializer range = - (IVersionedSerializer) - (IVersionedSerializer) - new IVersionedSerializer() + public static final UnversionedSerializer range = + (UnversionedSerializer) + (UnversionedSerializer) + new UnversionedSerializer() { @Override - public void serialize(PrefixedIntHashKey.Range t, DataOutputPlus out, int version) throws IOException + public void serialize(PrefixedIntHashKey.Range t, DataOutputPlus out) throws IOException { - routingKey.serialize(t.start(), out, version); - routingKey.serialize(t.end(), out, version); + routingKey.serialize(t.start(), out); + routingKey.serialize(t.end(), out); } @Override - public PrefixedIntHashKey.Range deserialize(DataInputPlus in, int version) throws IOException + public PrefixedIntHashKey.Range deserialize(DataInputPlus in) throws IOException { - RoutingKey start = routingKey.deserialize(in, version); - RoutingKey end = routingKey.deserialize(in, version); + RoutingKey start = routingKey.deserialize(in); + RoutingKey end = routingKey.deserialize(in); return PrefixedIntHashKey.range((PrefixedIntHashKey.PrefixedIntRoutingKey) start, (PrefixedIntHashKey.PrefixedIntRoutingKey) end); } @Override - public long serializedSize(PrefixedIntHashKey.Range t, int version) + public long serializedSize(PrefixedIntHashKey.Range t) { throw new RuntimeException("not implemented"); } }; - public static final IVersionedSerializer read = new CastingSerializer<>(ListRead.class, new IVersionedSerializer<>() + public static final VersionedSerializer read = CastingSerializer.create(ListRead.class, new IVersionedSerializer<>() { - public void serialize(ListRead t, DataOutputPlus out, int version) throws IOException + @Override + public void serialize(ListRead t, DataOutputPlus out, Version version) throws IOException { out.writeBoolean(t.isEphemeralRead); - KeySerializers.seekables.serialize(t.userReadKeys, out, version); - KeySerializers.seekables.serialize(t.keys, out, version); + KeySerializers.seekables.serialize(t.userReadKeys, out); + KeySerializers.seekables.serialize(t.keys, out); } - public ListRead deserialize(DataInputPlus in, int version) throws IOException + @Override + public ListRead deserialize(DataInputPlus in, Version version) throws IOException { boolean isEphemeralRead = in.readBoolean(); - Seekables userReadKeys = KeySerializers.seekables.deserialize(in, version); - Seekables keys = KeySerializers.seekables.deserialize(in, version); + Seekables userReadKeys = KeySerializers.seekables.deserialize(in); + Seekables keys = KeySerializers.seekables.deserialize(in); return new ListRead(Function.identity(), isEphemeralRead, userReadKeys, keys); } - public long serializedSize(ListRead t, int version) + @Override + public long serializedSize(ListRead t, Version version) { throw new RuntimeException("not implemented"); } }); - public static final IVersionedSerializer query = new CastingSerializer<>(ListQuery.class, new IVersionedSerializer<>() + public static final UnversionedSerializer query = CastingSerializer.create(ListQuery.class, new UnversionedSerializer<>() { - public void serialize(ListQuery t, DataOutputPlus out, int version) throws IOException + public void serialize(ListQuery t, DataOutputPlus out) throws IOException { if (t == null) { @@ -265,12 +276,12 @@ public class BurnTestKeySerializers return; } out.writeByte(1); - TopologySerializers.NodeIdSerializer.serialize(t.client, out); + TopologySerializers.nodeId.serialize(t.client, out); out.writeLong(t.requestId); out.writeBoolean(t.isEphemeralRead); } - public ListQuery deserialize(DataInputPlus in, int version) throws IOException + public ListQuery deserialize(DataInputPlus in) throws IOException { switch (in.readByte()) { @@ -282,70 +293,70 @@ public class BurnTestKeySerializers throw new AssertionError(); } - Node.Id client = TopologySerializers.NodeIdSerializer.deserialize(in); + Node.Id client = TopologySerializers.nodeId.deserialize(in); long requestId = in.readLong(); boolean isEphemeralRead = in.readBoolean(); return new ListQuery(client, requestId, isEphemeralRead); } - public long serializedSize(ListQuery t, int version) + public long serializedSize(ListQuery t) { throw new RuntimeException("not implemented"); } }); - public static final IVersionedSerializer update = new CastingSerializer<>(ListUpdate.class, new IVersionedSerializer<>() + public static final VersionedSerializer update = CastingSerializer.create(ListUpdate.class, new IVersionedSerializer<>() { - public void serialize(ListUpdate t, DataOutputPlus out, int version) throws IOException + public void serialize(ListUpdate t, DataOutputPlus out, Version version) throws IOException { out.writeInt(t.size()); for (Map.Entry e : t.entrySet()) { - KeySerializers.key.serialize(e.getKey(), out, version); + KeySerializers.key.serialize(e.getKey(), out); out.writeInt(e.getValue()); } } - public ListUpdate deserialize(DataInputPlus in, int version) throws IOException + public ListUpdate deserialize(DataInputPlus in, Version version) throws IOException { int size = in.readInt(); ListUpdate listUpdate = new ListUpdate(Function.identity()); for (int i = 0; i < size; i++) { - Key k = KeySerializers.key.deserialize(in, version); + Key k = KeySerializers.key.deserialize(in); int v = in.readInt(); listUpdate.put(k, v); } return listUpdate; } - public long serializedSize(ListUpdate t, int version) + public long serializedSize(ListUpdate t, Version version) { throw new RuntimeException("not implemented"); } }); - public static final IVersionedSerializer write = new CastingSerializer<>(ListWrite.class, new IVersionedSerializer<>() + public static final VersionedSerializer write = CastingSerializer.create(ListWrite.class, new IVersionedSerializer<>() { - public void serialize(ListWrite t, DataOutputPlus out, int version) throws IOException + public void serialize(ListWrite t, DataOutputPlus out, Version version) throws IOException { out.writeInt(t.size()); for (Map.Entry e : t.entrySet()) { - KeySerializers.key.serialize(e.getKey(), out, version); + KeySerializers.key.serialize(e.getKey(), out); out.writeInt(e.getValue().length); for (int v : e.getValue()) out.writeInt(v); } } - public ListWrite deserialize(DataInputPlus in, int version) throws IOException + public ListWrite deserialize(DataInputPlus in, Version version) throws IOException { int size = in.readInt(); ListWrite write = new ListWrite(Function.identity()); for (int i = 0; i < size; i++) { - Key k = KeySerializers.key.deserialize(in, version); + Key k = KeySerializers.key.deserialize(in); int len = in.readInt(); int[] vals = new int[len]; for (int j = 0; j < len; j++) @@ -355,22 +366,24 @@ public class BurnTestKeySerializers return write; } - public long serializedSize(ListWrite t, int version) + public long serializedSize(ListWrite t, Version version) { throw new RuntimeException("not implemented"); } }); - public static final IVersionedSerializer result = new CastingSerializer<>(ListResult.class, new IVersionedSerializer<>() + public static final UnversionedSerializer result = CastingSerializer.create(ListResult.class, new UnversionedSerializer<>() { - public void serialize(ListResult t, DataOutputPlus out, int version) throws IOException - { - TopologySerializers.NodeIdSerializer.serialize(t.client, out); - out.writeLong(t.requestId); - CommandSerializers.txnId.serialize(t.txnId, out, version); + private final EmbeddedAsymmetricVersionedSerializer unversionedUpdate = AccordSerializers.embedded(Version.LATEST, update); - KeySerializers.seekables.serialize(t.readKeys, out, version); - KeySerializers.keys.serialize(t.responseKeys, out, version); + public void serialize(ListResult t, DataOutputPlus out) throws IOException + { + TopologySerializers.nodeId.serialize(t.client, out); + out.writeLong(t.requestId); + CommandSerializers.txnId.serialize(t.txnId, out); + + KeySerializers.seekables.serialize(t.readKeys, out); + KeySerializers.keys.serialize(t.responseKeys, out); out.writeInt(t.read.length); for (int[] ints : t.read) @@ -382,18 +395,18 @@ public class BurnTestKeySerializers out.writeInt(t.update == null ? 0 : 1); if (t.update != null) - update.serialize(t.update, out, version); + unversionedUpdate.serialize(t.update, out); out.writeInt(t.status.ordinal()); } - public ListResult deserialize(DataInputPlus in, int version) throws IOException + public ListResult deserialize(DataInputPlus in) throws IOException { - Node.Id client = TopologySerializers.NodeIdSerializer.deserialize(in); + Node.Id client = TopologySerializers.nodeId.deserialize(in); long requestId = in.readLong(); TxnId txnId = CommandSerializers.txnId.deserialize(in); - Seekables readKeys = KeySerializers.seekables.deserialize(in, version); - Keys responseKeys = KeySerializers.keys.deserialize(in, version); + Seekables readKeys = KeySerializers.seekables.deserialize(in); + Keys responseKeys = KeySerializers.keys.deserialize(in); int[][] read = new int[in.readInt()][]; for (int i = 0; i < read.length; i++) { @@ -406,12 +419,12 @@ public class BurnTestKeySerializers } ListUpdate update = null; if (in.readInt() != 0) - update = (ListUpdate) BurnTestKeySerializers.update.deserialize(in, version); + update = (ListUpdate) unversionedUpdate.deserialize(in); ListResult.Status status = ListResult.Status.values()[in.readInt()]; return new ListResult(status, client, requestId, txnId, readKeys, responseKeys, read, update); } - public long serializedSize(ListResult t, int version) + public long serializedSize(ListResult t) { throw new RuntimeException("not implemented"); } diff --git a/test/distributed/org/apache/cassandra/service/accord/NemesisAccordSegmentCompactor.java b/test/distributed/org/apache/cassandra/service/accord/NemesisAccordSegmentCompactor.java index 12f8554df7..b1e2407991 100644 --- a/test/distributed/org/apache/cassandra/service/accord/NemesisAccordSegmentCompactor.java +++ b/test/distributed/org/apache/cassandra/service/accord/NemesisAccordSegmentCompactor.java @@ -28,6 +28,7 @@ import org.apache.cassandra.db.SerializationHeader; import org.apache.cassandra.db.rows.EncodingStats; import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.SSTableTxnWriter; +import org.apache.cassandra.service.accord.serializers.Version; /** * Nemesis compactor: a compactor that will distribute your keys over a large(r) number of SSTables. @@ -40,7 +41,7 @@ public class NemesisAccordSegmentCompactor extends AbstractAccordSegmentCompa private final SSTableTxnWriter[] writers; private final Set written = new HashSet<>(); - public NemesisAccordSegmentCompactor(int userVersion, ColumnFamilyStore cfs, RandomSource randomSource) + public NemesisAccordSegmentCompactor(Version userVersion, ColumnFamilyStore cfs, RandomSource randomSource) { super(userVersion, cfs); this.randomSource = randomSource; diff --git a/test/harry/main/org/apache/cassandra/harry/model/QuiescentChecker.java b/test/harry/main/org/apache/cassandra/harry/model/QuiescentChecker.java index 91526e5d72..1b2efb14e9 100644 --- a/test/harry/main/org/apache/cassandra/harry/model/QuiescentChecker.java +++ b/test/harry/main/org/apache/cassandra/harry/model/QuiescentChecker.java @@ -148,7 +148,7 @@ public class QuiescentChecker implements Model "\nExpected: %s" + "\nActual: %s", expectedRowState.toString(valueGenerators), - actualRowState); + actualRowState.toString(valueGenerators)); } if (!vdsEqual(expectedRowState.vds, actualRowState.vds)) diff --git a/test/simulator/test/org/apache/cassandra/simulator/test/ShortAccordSimulationTest.java b/test/simulator/test/org/apache/cassandra/simulator/test/ShortAccordSimulationTest.java index a51fa078ad..cb83160be8 100644 --- a/test/simulator/test/org/apache/cassandra/simulator/test/ShortAccordSimulationTest.java +++ b/test/simulator/test/org/apache/cassandra/simulator/test/ShortAccordSimulationTest.java @@ -24,6 +24,74 @@ import org.junit.Test; import org.apache.cassandra.simulator.paxos.AccordSimulationRunner; +/** + * In order to run these tests in your IDE, you need to first build a simulator jara + * + * ant simulator-jars + * + * And then run your test using the following settings (omit add-* if you are running on jdk8): + * + -Dstorage-config=$MODULE_DIR$/test/conf + -Djava.awt.headless=true + -javaagent:$MODULE_DIR$/lib/jamm-0.4.0.jar + -ea + -Dcassandra.debugrefcount=true + -Xss384k + -XX:SoftRefLRUPolicyMSPerMB=0 + -XX:ActiveProcessorCount=2 + -XX:HeapDumpPath=build/test + -Dcassandra.test.driver.connection_timeout_ms=10000 + -Dcassandra.test.driver.read_timeout_ms=24000 + -Dcassandra.memtable_row_overhead_computation_step=100 + -Dcassandra.test.use_prepared=true + -Dcassandra.test.sstableformatdevelopment=true + -Djava.security.egd=file:/dev/urandom + -Dcassandra.testtag=.jdk11 + -Dcassandra.keepBriefBrief=true + -Dcassandra.allow_simplestrategy=true + -Dcassandra.strict.runtime.checks=true + -Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true + -Dcassandra.test.flush_local_schema_changes=false + -Dcassandra.test.messagingService.nonGracefulShutdown=true + -Dcassandra.use_nix_recursive_delete=true + -Dcie-cassandra.disable_schema_drop_log=true + -Dlogback.configurationFile=file://$MODULE_DIR$/test/conf/logback-simulator.xml + -Dcassandra.ring_delay_ms=10000 + -Dcassandra.tolerate_sstable_size=true + -Dcassandra.skip_sync=true + -Dcassandra.debugrefcount=false + -Dcassandra.test.simulator.determinismcheck=strict + -Dcassandra.test.simulator.print_asm=none + -javaagent:$MODULE_DIR$/build/test/lib/jars/simulator-asm.jar + -Xbootclasspath/a:$MODULE_DIR$/build/test/lib/jars/simulator-bootstrap.jar + -XX:ActiveProcessorCount=4 + -XX:-TieredCompilation + -XX:-BackgroundCompilation + -XX:CICompilerCount=1 + -XX:Tier4CompileThreshold=1000 + -XX:ReservedCodeCacheSize=256M + -Xmx16G + -Xmx4G + --add-exports java.base/jdk.internal.misc=ALL-UNNAMED + --add-exports java.base/jdk.internal.ref=ALL-UNNAMED + --add-exports java.base/sun.nio.ch=ALL-UNNAMED + --add-exports java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED + --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED + --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED + --add-exports java.sql/java.sql=ALL-UNNAMED + --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED + --add-opens java.base/java.lang.module=ALL-UNNAMED + --add-opens java.base/java.net=ALL-UNNAMED + --add-opens java.base/jdk.internal.loader=ALL-UNNAMED + --add-opens java.base/jdk.internal.ref=ALL-UNNAMED + --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED + --add-opens java.base/jdk.internal.math=ALL-UNNAMED + --add-opens java.base/jdk.internal.module=ALL-UNNAMED + --add-opens java.base/jdk.internal.util.jar=ALL-UNNAMED + --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED + --add-opens jdk.management.jfr/jdk.management.jfr=ALL-UNNAMED + --add-opens java.desktop/com.sun.beans.introspect=ALL-UNNAMED + */ public class ShortAccordSimulationTest { @Test diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java index 6190d8253f..7d27271a0d 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java @@ -224,6 +224,7 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.gms.IFailureDetector", "org.apache.cassandra.io.FSError", "org.apache.cassandra.io.FSWriteError", + "org.apache.cassandra.io.MessageVersionProvider", "org.apache.cassandra.io.compress.ICompressor", "org.apache.cassandra.io.compress.ICompressor$Uses", "org.apache.cassandra.io.compress.LZ4Compressor", @@ -297,10 +298,12 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.locator.SeedProvider", "org.apache.cassandra.locator.SimpleSeedProvider", "org.apache.cassandra.locator.SnitchAdapter", + "org.apache.cassandra.net.MessagingService$Version", "org.apache.cassandra.security.AbstractCryptoProvider", "org.apache.cassandra.security.EncryptionContext", "org.apache.cassandra.security.ISslContextFactory", "org.apache.cassandra.security.SSLFactory", + "org.apache.cassandra.service.accord.serializers.Version", "org.apache.cassandra.service.CacheService$CacheType", "org.apache.cassandra.security.AbstractCryptoProvider", "org.apache.cassandra.tcm.RegistrationStateCallbacks", diff --git a/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java b/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java index 30d90b2265..510cc622cb 100644 --- a/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java +++ b/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java @@ -18,16 +18,33 @@ package org.apache.cassandra.cql3.conditions; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.junit.Assert; +import org.junit.Test; import accord.utils.Gen; import accord.utils.Gens; import accord.utils.RandomSource; -import org.apache.cassandra.cql3.terms.*; -import org.junit.Assert; -import org.junit.Test; - -import org.apache.cassandra.cql3.*; +import org.apache.cassandra.cql3.ColumnIdentifier; +import org.apache.cassandra.cql3.ColumnsExpression; +import org.apache.cassandra.cql3.FieldIdentifier; +import org.apache.cassandra.cql3.Operator; +import org.apache.cassandra.cql3.QueryOptions; +import org.apache.cassandra.cql3.terms.Constants; +import org.apache.cassandra.cql3.terms.InMarker; +import org.apache.cassandra.cql3.terms.Marker; +import org.apache.cassandra.cql3.terms.MultiElements; +import org.apache.cassandra.cql3.terms.Sets; +import org.apache.cassandra.cql3.terms.Term; +import org.apache.cassandra.cql3.terms.Terms; import org.apache.cassandra.db.Clustering; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.marshal.Int32Type; @@ -35,11 +52,14 @@ import org.apache.cassandra.db.marshal.ListType; import org.apache.cassandra.db.marshal.MapType; import org.apache.cassandra.db.marshal.SetType; import org.apache.cassandra.db.marshal.UserType; -import org.apache.cassandra.db.rows.*; +import org.apache.cassandra.db.rows.BTreeRow; +import org.apache.cassandra.db.rows.BufferCell; +import org.apache.cassandra.db.rows.Cell; +import org.apache.cassandra.db.rows.CellPath; +import org.apache.cassandra.db.rows.Row; import org.apache.cassandra.exceptions.InvalidRequestException; -import org.apache.cassandra.io.IVersionedSerializers; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.SchemaProvider; @@ -54,25 +74,24 @@ import org.mockito.Mockito; import org.quicktheories.generators.SourceDSL; import static accord.utils.Property.qt; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; import static java.util.Arrays.asList; - -import static org.apache.cassandra.cql3.Operator.EQ; -import static org.apache.cassandra.cql3.Operator.NEQ; -import static org.apache.cassandra.cql3.Operator.LT; -import static org.apache.cassandra.cql3.Operator.LTE; -import static org.apache.cassandra.cql3.Operator.GT; -import static org.apache.cassandra.cql3.Operator.GTE; import static org.apache.cassandra.cql3.Operator.CONTAINS; import static org.apache.cassandra.cql3.Operator.CONTAINS_KEY; -import static org.apache.cassandra.cql3.conditions.ColumnCondition.Raw.simpleCondition; +import static org.apache.cassandra.cql3.Operator.EQ; +import static org.apache.cassandra.cql3.Operator.GT; +import static org.apache.cassandra.cql3.Operator.GTE; +import static org.apache.cassandra.cql3.Operator.LT; +import static org.apache.cassandra.cql3.Operator.LTE; +import static org.apache.cassandra.cql3.Operator.NEQ; import static org.apache.cassandra.cql3.conditions.ColumnCondition.Raw.collectionElementCondition; +import static org.apache.cassandra.cql3.conditions.ColumnCondition.Raw.simpleCondition; import static org.apache.cassandra.cql3.conditions.ColumnCondition.Raw.udtFieldCondition; import static org.apache.cassandra.utils.ByteBufferUtil.EMPTY_BYTE_BUFFER; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class ColumnConditionTest @@ -888,8 +907,7 @@ public class ColumnConditionTest qt().forAll(boundGen()).check(bounds -> { Schema.instance = Mockito.mock(SchemaProvider.class); Mockito.when(Schema.instance.getColumnMetadata(Mockito.eq(bounds.column.ksName), Mockito.eq(bounds.column.cfName), Mockito.eq(bounds.column.name.bytes))).thenReturn(bounds.column); - for (MessagingService.Version version : MessagingService.Version.MIN_ACCORD_VERSION.greaterThanOrEqual()) - IVersionedSerializers.testSerde(out, ColumnCondition.Bound.serializer, bounds, version.value); + Serializers.testSerde(out, ColumnCondition.Bound.serializer, bounds); }); } @@ -930,11 +948,11 @@ public class ColumnConditionTest } } - private static Gen boundGen() + public static Gen boundGen() { Gen kindGen = Gens.enums().all(ColumnCondition.BoundKind.class); Gen operatorGen = Gens.enums().all(Operator.class); - Gen nonNullValuesGen = Generators.toGen(Generators.bytes(1, 100)); + Gen nonNullValuesGen = Generators.toGen(Generators.directAndHeapBytes(1, 100)); Gen valueGen = rs -> { if (rs.decide(.2)) return null; return nonNullValuesGen.next(rs); diff --git a/test/unit/org/apache/cassandra/dht/AccordSplitterTest.java b/test/unit/org/apache/cassandra/dht/AccordSplitterTest.java index 30341f6d2f..ec05ebc6fa 100644 --- a/test/unit/org/apache/cassandra/dht/AccordSplitterTest.java +++ b/test/unit/org/apache/cassandra/dht/AccordSplitterTest.java @@ -52,7 +52,7 @@ public class AccordSplitterTest qt().forAll(AccordGenerators.range(), Gens.random()).check((range, rs) -> { TokenKey startKey = (TokenKey) range.start(); TokenKey endKey = (TokenKey) range.end(); - IPartitioner partitioner = getPartitioner(range, rs); + IPartitioner partitioner = startKey.token().getPartitioner(); // this section is filtering out known bugs // TODO (now): fix the fact accordSplitter returns AccordBytesSplitter which will fail for java.lang.ClassCastException: org.apache.cassandra.dht.LocalPartitioner$LocalToken cannot be cast to org.apache.cassandra.dht.ByteOrderedPartitioner$BytesToken // spoke with Benedict and he agrees that it doesn't make sense to split a local partitioner range, but this requires pushing this back into the API (similar to how C* returns Optional) @@ -118,15 +118,4 @@ public class AccordSplitterTest Ranges missing = topLevel.without(split); Assertions.assertThat(missing).isEmpty(); } - - private static IPartitioner getPartitioner(Range range, RandomSource rs) - { - TokenKey key = (TokenKey) range.start(); - if (key.isTableSentinel()) - key = (TokenKey) range.end(); - if (key.isTableSentinel()) - return AccordGenerators.partitioner().next(rs); - - return key.token().getPartitioner(); - } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/dht/TokenTest.java b/test/unit/org/apache/cassandra/dht/TokenTest.java index 234747c2cd..fa934e2065 100644 --- a/test/unit/org/apache/cassandra/dht/TokenTest.java +++ b/test/unit/org/apache/cassandra/dht/TokenTest.java @@ -21,7 +21,7 @@ package org.apache.cassandra.dht; import org.junit.Test; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.io.IVersionedSerializers; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.utils.AccordGenerators; @@ -45,7 +45,7 @@ public class TokenTest DatabaseDescriptor.setPartitionerUnsafe(partitioner); Token token = AccordGenerators.fromQT(CassandraGenerators.token(partitioner)).next(rs); for (MessagingService.Version version : MessagingService.Version.values()) - IVersionedSerializers.testSerde(output, Token.compactSerializer, token, version.value); + Serializers.testSerde(output, Token.compactSerializer, token, version.value); }); } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/io/Serializers.java b/test/unit/org/apache/cassandra/io/Serializers.java new file mode 100644 index 0000000000..d911e07aed --- /dev/null +++ b/test/unit/org/apache/cassandra/io/Serializers.java @@ -0,0 +1,90 @@ +/* + * 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.io; + +import java.io.IOException; + +import accord.utils.LazyToString; +import accord.utils.ReflectionUtils; +import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.assertj.core.api.Assertions; + +public class Serializers +{ + // When using a shard buffer the following is the recommend thing to copy/paste + // @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + + public static void testSerde(DataOutputBuffer output, AsymmetricUnversionedSerializer serializer, T input) throws IOException + { + output.clear(); + long expectedSize = serializer.serializedSize(input); + serializer.serialize(input, output); + Assertions.assertThat(output.getLength()).describedAs("The serialized size and bytes written do not match").isEqualTo(expectedSize); + DataInputBuffer in = new DataInputBuffer(output.unsafeGetBufferAndFlip(), false); + T read = serializer.deserialize(in); + Assertions.assertThat(read).describedAs("The deserialized output does not match the serialized input; difference %s", new LazyToString(() -> ReflectionUtils.recursiveEquals(read, input).toString())).isEqualTo(input); + } + + public static void testSerde(AsymmetricUnversionedSerializer serializer, T input) throws IOException + { + try (DataOutputBuffer output = new DataOutputBuffer(Math.toIntExact(serializer.serializedSize(input)))) + { + testSerde(output, serializer, input); + } + } + + public static void testSerde(DataOutputBuffer output, IVersionedAsymmetricSerializer serializer, T input, int version) throws IOException + { + output.clear(); + long expectedSize = serializer.serializedSize(input, version); + serializer.serialize(input, output, version); + Assertions.assertThat(output.getLength()).describedAs("The serialized size and bytes written do not match").isEqualTo(expectedSize); + DataInputBuffer in = new DataInputBuffer(output.unsafeGetBufferAndFlip(), false); + T read = serializer.deserialize(in, version); + Assertions.assertThat(read).describedAs("The deserialized output does not match the serialized input; difference %s", new LazyToString(() -> ReflectionUtils.recursiveEquals(read, input).toString())).isEqualTo(input); + } + + public static void testSerde(IVersionedAsymmetricSerializer serializer, T input, int version) throws IOException + { + try (DataOutputBuffer output = new DataOutputBuffer(Math.toIntExact(serializer.serializedSize(input, version)))) + { + testSerde(output, serializer, input, version); + } + } + + public static void testSerde(DataOutputBuffer output, AsymmetricVersionedSerializer serializer, T input, Version version) throws IOException + { + output.clear(); + long expectedSize = serializer.serializedSize(input, version); + serializer.serialize(input, output, version); + Assertions.assertThat(output.getLength()).describedAs("The serialized size and bytes written do not match").isEqualTo(expectedSize); + DataInputBuffer in = new DataInputBuffer(output.unsafeGetBufferAndFlip(), false); + T read = serializer.deserialize(in, version); + Assertions.assertThat(read).describedAs("The deserialized output does not match the serialized input; difference %s", new LazyToString(() -> ReflectionUtils.recursiveEquals(read, input).toString())).isEqualTo(input); + } + + public static void testSerde(AsymmetricVersionedSerializer serializer, T input, Version version) throws IOException + { + try (DataOutputBuffer output = new DataOutputBuffer(Math.toIntExact(serializer.serializedSize(input, version)))) + { + testSerde(output, serializer, input, version); + } + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/io/util/DataOutputInputPlusTest.java b/test/unit/org/apache/cassandra/io/util/DataOutputInputPlusTest.java new file mode 100644 index 0000000000..8be57b5faa --- /dev/null +++ b/test/unit/org/apache/cassandra/io/util/DataOutputInputPlusTest.java @@ -0,0 +1,50 @@ +/* + * 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.io.util; + +import org.junit.Test; + +import accord.utils.Gens; +import org.assertj.core.api.Assertions; + +import static accord.utils.Property.qt; + +public class DataOutputInputPlusTest +{ + @Test + public void leastSignificantBytes() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(Gens.longs().all()).check(expected -> { + output.clear(); + + int expectedSize = numberOfBytes(expected); + output.writeLeastSignificantBytes(expected, expectedSize); + Assertions.assertThat(output.getLength()).describedAs("The serialized size and bytes written do not match").isEqualTo(expectedSize); + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataInputBuffer in = new DataInputBuffer(output.unsafeGetBufferAndFlip(), false); + long read = in.readLeastSignificantBytes(expectedSize); + Assertions.assertThat(read).describedAs("The deserialized output does not match the serialized input").isEqualTo(expected); + }); + } + + private static int numberOfBytes(long value) + { + return (64 + 7 - Long.numberOfLeadingZeros(value)) / 8; + } +} diff --git a/test/unit/org/apache/cassandra/journal/TestParams.java b/test/unit/org/apache/cassandra/journal/TestParams.java index 0cab7bcd6d..72c64b0e51 100644 --- a/test/unit/org/apache/cassandra/journal/TestParams.java +++ b/test/unit/org/apache/cassandra/journal/TestParams.java @@ -19,7 +19,7 @@ package org.apache.cassandra.journal; import java.util.concurrent.TimeUnit; -import org.apache.cassandra.net.MessagingService; +import org.apache.cassandra.service.accord.serializers.Version; public class TestParams implements Params { @@ -70,6 +70,6 @@ public class TestParams implements Params @Override public int userVersion() { - return MessagingService.current_version; + return Version.LATEST.version; } } diff --git a/test/unit/org/apache/cassandra/service/accord/AccordConfigurationServiceTest.java b/test/unit/org/apache/cassandra/service/accord/AccordConfigurationServiceTest.java index 09ca44d9d8..b2d9c07ad2 100644 --- a/test/unit/org/apache/cassandra/service/accord/AccordConfigurationServiceTest.java +++ b/test/unit/org/apache/cassandra/service/accord/AccordConfigurationServiceTest.java @@ -218,7 +218,8 @@ public class AccordConfigurationServiceTest } finally { - journal.shutdown(); + if (journal != null) + journal.shutdown(); } } diff --git a/test/unit/org/apache/cassandra/service/accord/AccordJournalOrderTest.java b/test/unit/org/apache/cassandra/service/accord/AccordJournalOrderTest.java index 14e162955d..0445e3d75e 100644 --- a/test/unit/org/apache/cassandra/service/accord/AccordJournalOrderTest.java +++ b/test/unit/org/apache/cassandra/service/accord/AccordJournalOrderTest.java @@ -43,7 +43,6 @@ import org.apache.cassandra.config.CassandraRelevantProperties; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.ByteOrderedPartitioner; import org.apache.cassandra.io.util.File; -import org.apache.cassandra.journal.TestParams; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; @@ -75,7 +74,7 @@ public class AccordJournalOrderTest { if (new File(DatabaseDescriptor.getAccordJournalDirectory()).exists()) ServerTestUtils.cleanupDirectory(DatabaseDescriptor.getAccordJournalDirectory()); - AccordJournal accordJournal = new AccordJournal(TestParams.INSTANCE, new AccordAgent()); + AccordJournal accordJournal = new AccordJournal(AccordJournalTestParams.INSTANCE, new AccordAgent()); accordJournal.start(null); RandomSource randomSource = RandomSource.wrap(new Random(0)); TxnId id1 = AccordGens.txnIds().next(randomSource); diff --git a/test/unit/org/apache/cassandra/service/accord/AccordJournalTestParams.java b/test/unit/org/apache/cassandra/service/accord/AccordJournalTestParams.java new file mode 100644 index 0000000000..c9a14efd7f --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/AccordJournalTestParams.java @@ -0,0 +1,77 @@ +/* + * 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.service.accord; + +import java.util.concurrent.TimeUnit; + +import org.apache.cassandra.journal.Params; +import org.apache.cassandra.service.accord.serializers.Version; + +public class AccordJournalTestParams implements Params +{ + public static final AccordJournalTestParams INSTANCE = new AccordJournalTestParams(); + + @Override + public int segmentSize() + { + return 32 << 20; + } + + @Override + public FailurePolicy failurePolicy() + { + return FailurePolicy.STOP; + } + + @Override + public FlushMode flushMode() + { + return FlushMode.GROUP; + } + + @Override + public boolean enableCompaction() + { + return false; + } + + @Override + public long compactionPeriod(TimeUnit units) + { + return units.convert(60, TimeUnit.SECONDS); + } + + @Override + public long flushPeriod(TimeUnit units) + { + return units.convert(1, TimeUnit.SECONDS); + } + + @Override + public long periodicBlockPeriod(TimeUnit units) + { + return units.convert(2, TimeUnit.SECONDS); + } + + @Override + public int userVersion() + { + return Version.LATEST.version; + } +} diff --git a/test/unit/org/apache/cassandra/service/accord/AccordSerializersTest.java b/test/unit/org/apache/cassandra/service/accord/AccordSerializersTest.java new file mode 100644 index 0000000000..44908a0fa1 --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/AccordSerializersTest.java @@ -0,0 +1,40 @@ +/* + * 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.service.accord; + +import org.junit.Test; + +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.utils.CassandraGenerators; +import org.apache.cassandra.utils.Generators; + +import static accord.utils.Property.qt; + +public class AccordSerializersTest +{ + @Test + public void clustering() + { + DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(Generators.toGen(CassandraGenerators.CLUSTERING_GEN)).check(clustering -> { + Serializers.testSerde(output, AccordSerializers.clusteringSerializer, clustering); + }); + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/CommandChangeTest.java b/test/unit/org/apache/cassandra/service/accord/CommandChangeTest.java index facb15357f..d87ca5292f 100644 --- a/test/unit/org/apache/cassandra/service/accord/CommandChangeTest.java +++ b/test/unit/org/apache/cassandra/service/accord/CommandChangeTest.java @@ -41,6 +41,7 @@ import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableMetadata; import org.apache.cassandra.service.StorageService; +import org.apache.cassandra.service.accord.serializers.Version; import org.apache.cassandra.service.consensus.TransactionalMode; import org.apache.cassandra.utils.AccordGenerators; import org.assertj.core.api.SoftAssertions; @@ -91,26 +92,28 @@ public class CommandChangeTest { qt().forAll(gen) .check(cmdBuilder -> { - int userVersion = 1; //TODO (maintenance): where can we fetch all supported versions? - SoftAssertions checks = new SoftAssertions(); - for (SaveStatus saveStatus : SaveStatus.values()) - { - out.clear(); - Command orig = cmdBuilder.build(saveStatus); + for (Version version : Version.V1.greaterThanOrEqual()) + { + SoftAssertions checks = new SoftAssertions(); + for (SaveStatus saveStatus : SaveStatus.values()) + { + out.clear(); + Command orig = cmdBuilder.build(saveStatus); - AccordJournal.Writer.make(null, orig).write(out, userVersion); - AccordJournal.Builder builder = new AccordJournal.Builder(orig.txnId(), Load.ALL); - builder.deserializeNext(new DataInputBuffer(out.unsafeGetBufferAndFlip(), false), userVersion); - // We are not persisting the result, so force it for strict equality - builder.forceResult(orig.result()); + AccordJournal.Writer.make(null, orig).write(out, version); + AccordJournal.Builder builder = new AccordJournal.Builder(orig.txnId(), Load.ALL); + builder.deserializeNext(new DataInputBuffer(out.unsafeGetBufferAndFlip(), false), version); + // We are not persisting the result, so force it for strict equality + builder.forceResult(orig.result()); - Command reconstructed = builder.construct(RedundantBefore.EMPTY); + Command reconstructed = builder.construct(RedundantBefore.EMPTY); - checks.assertThat(reconstructed) - .describedAs("lhs=expected\nrhs=actual\n%s", new LazyToString(() -> ReflectionUtils.recursiveEquals(orig, reconstructed).toString())) - .isEqualTo(orig); - } - checks.assertAll(); + checks.assertThat(reconstructed) + .describedAs("lhs=expected\nrhs=actual\n%s", new LazyToString(() -> ReflectionUtils.recursiveEquals(orig, reconstructed).toString())) + .isEqualTo(orig); + } + checks.assertAll(); + } }); } } diff --git a/test/unit/org/apache/cassandra/service/accord/WatermarkCollectorTest.java b/test/unit/org/apache/cassandra/service/accord/WatermarkCollectorTest.java new file mode 100644 index 0000000000..06af98f5bc --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/WatermarkCollectorTest.java @@ -0,0 +1,111 @@ +/* + * 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.service.accord; + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.collect.Sets; +import org.junit.Test; + +import accord.local.Node; +import accord.primitives.Range; +import accord.utils.AccordGens; +import accord.utils.Gen; +import accord.utils.Gens; +import accord.utils.Invariants; +import org.agrona.collections.Int2ObjectHashMap; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.dht.IPartitioner; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.utils.AccordGenerators; + +import static accord.utils.Property.qt; + +public class WatermarkCollectorTest +{ + static + { + DatabaseDescriptor.clientInitialization(); + } + + @Test + public void snapshotSerializer() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(snapshotGen()).check(expected -> { + maybeUpdatePartitioner(expected); + Serializers.testSerde(output, WatermarkCollector.serializer, expected); + }); + } + + private static void maybeUpdatePartitioner(WatermarkCollector.Snapshot snapshot) + { + for (Range range : Sets.union(snapshot.closed.keySet(), snapshot.retired.keySet())) + { + TokenRange tr = (TokenRange) range; + DatabaseDescriptor.setPartitionerUnsafe(tr.start().token().getPartitioner()); + break; + } + } + + private Gen snapshotGen() + { + Gen partitionerGen = AccordGenerators.partitioner(); + Gen.LongGen epochGen = AccordGens.epochs(); + Gen> syncedGen = syncedGen(); + return rs -> { + IPartitioner partitioner = partitionerGen.next(rs); + Gen rangeGen = AccordGenerators.range(partitioner); + Gen> mapGen = mapGen(Gens.ints().between(0, 10), rangeGen, epochGen); + return new WatermarkCollector.Snapshot(mapGen.next(rs), mapGen.next(rs), syncedGen.next(rs)); + }; + } + + private static Gen> syncedGen() + { + Gen.IntGen sizeGen = Gens.ints().between(0, 10); + Gen idGen = AccordGens.nodes(); + Gen.LongGen epochGen = AccordGens.epochs(); + return rs -> { + Int2ObjectHashMap map = new Int2ObjectHashMap<>(); + Gen uniqueIdGen = idGen.filter(id -> !map.containsKey(id.id)); + for (int i = 0, size = sizeGen.nextInt(rs); i < size; i++) + map.put(uniqueIdGen.next(rs).id, epochGen.next(rs)); + return map; + }; + } + + private static Gen> mapGen(Gen.IntGen sizeGen, Gen keyGen, Gen valueGen) + { + //TODO (ux): should move this to Gens + return rs -> { + int size = sizeGen.nextInt(rs); + Invariants.require(size >= 0, "Only 0 and possitive allowed; given %d", size); + if (size == 0) + return Map.of(); + Map map = new HashMap<>(); + Gen uniqueKeyGen = keyGen.filter(k -> !map.containsKey(k)); + for (int i = 0; i < size; i++) + map.put(uniqueKeyGen.next(rs), valueGen.next(rs)); + return map; + }; + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/api/AccordKeyTest.java b/test/unit/org/apache/cassandra/service/accord/api/AccordKeyTest.java index 47a0a9f26c..d27c00b1c8 100644 --- a/test/unit/org/apache/cassandra/service/accord/api/AccordKeyTest.java +++ b/test/unit/org/apache/cassandra/service/accord/api/AccordKeyTest.java @@ -18,6 +18,8 @@ package org.apache.cassandra.service.accord.api; +import java.io.IOException; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -25,11 +27,11 @@ import org.junit.Test; import org.apache.cassandra.SchemaLoader; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.dht.IPartitioner; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.TableId; import org.apache.cassandra.utils.ByteBufferUtil; -import org.apache.cassandra.utils.SerializerTestUtils; import static org.apache.cassandra.cql3.statements.schema.CreateTableStatement.parse; @@ -54,19 +56,19 @@ public class AccordKeyTest } @Test - public void partitionKeyTest() + public void partitionKeyTest() throws IOException { DecoratedKey dk = partitioner(TABLE1).decorateKey(ByteBufferUtil.bytes(5)); PartitionKey pk = new PartitionKey(TABLE1, dk); - SerializerTestUtils.assertSerializerIOEquality(pk, PartitionKey.serializer); + Serializers.testSerde(PartitionKey.serializer, pk); } @Test - public void tokenKeyTest() + public void tokenKeyTest() throws IOException { DecoratedKey dk = partitioner(TABLE1).decorateKey(ByteBufferUtil.bytes(5)); TokenKey pk = new TokenKey(TABLE1, dk.getToken()); - SerializerTestUtils.assertSerializerIOEquality(pk, TokenKey.serializer); + Serializers.testSerde(TokenKey.serializer, pk); } @Test diff --git a/test/unit/org/apache/cassandra/service/accord/journal/AccordTopologyUpdateTest.java b/test/unit/org/apache/cassandra/service/accord/journal/AccordTopologyUpdateTest.java new file mode 100644 index 0000000000..c9ed1c5af3 --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/journal/AccordTopologyUpdateTest.java @@ -0,0 +1,175 @@ +/* + * 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.service.accord.journal; + +import org.junit.Before; +import org.junit.Test; + +import accord.api.Journal; +import accord.local.CommandStores; +import accord.local.Node; +import accord.primitives.Ranges; +import accord.topology.Topology; +import accord.utils.AccordGens; +import accord.utils.Gen; +import accord.utils.Gens; +import org.agrona.collections.Int2ObjectHashMap; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.dht.IPartitioner; +import org.apache.cassandra.dht.Murmur3Partitioner; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.schema.TableId; +import org.apache.cassandra.utils.AccordGenerators; + +import static accord.utils.Property.qt; + +public class AccordTopologyUpdateTest +{ + private static final long[] EPOCHS = new long[0]; + private static final Ranges[] RANGES = new Ranges[0]; + private static final TableId TBL1 = TableId.fromRaw(0, 0); + + static + { + DatabaseDescriptor.clientInitialization(); + } + + @Before + public void before() + { + DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); + } + + @Test + public void rangesForEpoch() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(rangesForEpochGen()).check(expected -> { + maybeUpdatePartitioner(expected); + Serializers.testSerde(output, AccordTopologyUpdate.RangesForEpochSerializer.instance, expected); + }); + } + + @Test + public void topologyUpdate() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(topologyUpdateGen()).check(expected -> { + maybeUpdatePartitioner(expected); + Serializers.testSerde(output, AccordTopologyUpdate.TopologyUpdateSerializer.instance, expected); + }); + } + + @Test + public void accordTopologyUpdate() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(accordTopologyUpdateGen()).check(expected -> { + maybeUpdatePartitioner(expected); + Serializers.testSerde(output, AccordTopologyUpdate.Serializer.instance, expected); + }); + } + + private static Gen rangesForEpochGen() + { + return AccordGenerators.partitioner().flatMap(p -> rangesForEpochGen(AccordGenerators.rangesSplitOrArbitrary(p))); + } + + private static Gen rangesForEpochGen(Gen rangesGen) + { + Gen.IntGen sizeGen = Gens.ints().between(0, 10); + Gen.LongGen epochGen = AccordGens.epochs(); + return rs -> { + int size = sizeGen.nextInt(rs); + if (size == 0) + return new CommandStores.RangesForEpoch(EPOCHS, RANGES); + long epoch = epochGen.nextLong(rs); + long[] epochs = new long[size]; + Ranges[] ranges = new Ranges[size]; + for (int i = 0; i < size; i++) + { + epochs[i] = epoch++; + ranges[i] = rangesGen.next(rs); + } + return new CommandStores.RangesForEpoch(epochs, ranges); + }; + } + + private static Gen topologyUpdateGen() + { + Gen partitionerGen = AccordGenerators.partitioner(); + return rs -> { + IPartitioner partitioner = partitionerGen.next(rs); + Gen rangesGen = AccordGenerators.ranges(TBL1, partitioner); + Gen rangesForEpochGen = rangesForEpochGen(rangesGen); + Topology topology = AccordGenerators.topologyGen(rangesGen).next(rs); + + Int2ObjectHashMap commandStores = new Int2ObjectHashMap<>(); + for (Node.Id node : topology.nodes()) + commandStores.put(node.id, rangesForEpochGen.next(rs)); + + Node.Id self = rs.pick(topology.nodes()); + + return new Journal.TopologyUpdate(commandStores, topology.forNode(self), topology); + }; + } + + private static Gen accordTopologyUpdateGen() + { + Gen.LongGen epochGen = AccordGens.epochs(); + Gen topologyUpdateGen = topologyUpdateGen(); + Gen kindGen = Gens.enums().all(AccordTopologyUpdate.Kind.class); + return rs -> { + AccordTopologyUpdate.Kind kind = kindGen.next(rs); + switch (kind) + { + case NewTopology: return new AccordTopologyUpdate.NewTopology(topologyUpdateGen.next(rs)); + case Topologies: return new AccordTopologyUpdate.TopologyImage(epochGen.nextLong(rs)); + default: throw new AssertionError("Unknown kind: " + kind); + } + }; + } + + private static void maybeUpdatePartitioner(Journal.TopologyUpdate expected) + { + AccordGenerators.maybeUpdatePartitioner(expected.global.ranges()); + } + + private static void maybeUpdatePartitioner(AccordTopologyUpdate expected) + { + if (expected instanceof AccordTopologyUpdate.NewTopology) + { + maybeUpdatePartitioner(((AccordTopologyUpdate.NewTopology) expected).update); + } + } + + private void maybeUpdatePartitioner(CommandStores.RangesForEpoch expected) + { + if (expected.size() > 0) + { + for (int i = 0; i < expected.size(); i++) + { + Ranges ranges = expected.rangesAtIndex(i); + if (AccordGenerators.maybeUpdatePartitioner(ranges)) + return; + } + } + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/CheckStatusSerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/CheckStatusSerializersTest.java index 66779e2b47..7079de790e 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/CheckStatusSerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/CheckStatusSerializersTest.java @@ -18,7 +18,6 @@ package org.apache.cassandra.service.accord.serializers; -import java.io.IOException; import java.util.Comparator; import java.util.List; @@ -36,14 +35,11 @@ import accord.utils.Gen; import accord.utils.Gens; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.Murmur3Partitioner; -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.service.accord.api.TokenKey; import org.apache.cassandra.utils.AccordGenerators; import org.apache.cassandra.utils.CassandraGenerators; -import org.assertj.core.api.Assertions; import static accord.utils.Property.qt; import static org.apache.cassandra.utils.AccordGenerators.fromQT; @@ -60,19 +56,7 @@ public class CheckStatusSerializersTest public void serde() { DataOutputBuffer buffer = new DataOutputBuffer(); - qt().forAll(foundKnownMap()).check(map -> Assertions.assertThat(serde(CheckStatusSerializers.knownMap, MessagingService.Version.CURRENT.value, buffer, map)).isEqualTo(map)); - } - - private static T serde(IVersionedSerializer serializer, int version, DataOutputBuffer buffer, T value) throws IOException - { - buffer.clear(); - long expectedSize = serializer.serializedSize(value, version); - serializer.serialize(value, buffer, version); - Assertions.assertThat(buffer.getLength()).isEqualTo(expectedSize); - try (DataInputBuffer in = new DataInputBuffer(buffer.unsafeGetBufferAndFlip(), false)) - { - return serializer.deserialize(in, version); - } + qt().forAll(foundKnownMap()).check(map -> Serializers.testSerde(buffer, CheckStatusSerializers.knownMap, map)); } private static Gen foundKnownMap() @@ -86,7 +70,7 @@ public class CheckStatusSerializersTest { case Key: // TODO (coverage): don't hard code murmur - Gen keyGen = AccordGenerators.routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), Gens.constant(TokenKey.RoutingKeyKind.TOKEN), fromQT(CassandraGenerators.murmurToken()), Murmur3Partitioner.instance); + Gen keyGen = AccordGenerators.routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), Gens.constant(AccordGenerators.RoutingKeyKind.TOKEN), fromQT(CassandraGenerators.murmurToken()), Murmur3Partitioner.instance); TokenKey homeKey = keyGen.next(rs); List forOrdering = Gens.lists(keyGen).unique().ofSizeBetween(1, 10).next(rs); forOrdering.sort(Comparator.naturalOrder()); diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/CommandSerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/CommandSerializersTest.java index e10588645d..18fee68f5f 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/CommandSerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/CommandSerializersTest.java @@ -18,19 +18,24 @@ package org.apache.cassandra.service.accord.serializers; +import java.io.IOException; + import org.junit.BeforeClass; import org.junit.Test; import accord.primitives.PartialTxn; import accord.primitives.Ranges; import accord.primitives.Txn; +import accord.utils.AccordGens; import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.service.accord.AccordTestUtils; import org.apache.cassandra.service.accord.TokenRange; import org.apache.cassandra.service.accord.api.PartitionKey; -import org.apache.cassandra.utils.SerializerTestUtils; +import static accord.utils.Property.qt; import static org.apache.cassandra.config.DatabaseDescriptor.getPartitioner; import static org.apache.cassandra.cql3.statements.schema.CreateTableStatement.parse; @@ -46,7 +51,7 @@ public class CommandSerializersTest } @Test - public void txnSerializer() + public void txnSerializer() throws IOException { Txn txn = AccordTestUtils.createTxn("BEGIN TRANSACTION\n" + " LET row1 = (SELECT * FROM ks.tbl WHERE k=0 AND c=0);\n" + @@ -57,6 +62,13 @@ public class CommandSerializersTest "COMMIT TRANSACTION"); PartitionKey key = (PartitionKey) txn.keys().get(0); PartialTxn expected = txn.slice(Ranges.of(TokenRange.fullRange(key.table(), getPartitioner())), true); - SerializerTestUtils.assertSerializerIOEquality(expected, CommandSerializers.partialTxn); + Serializers.testSerde(CommandSerializers.partialTxn, expected, Version.LATEST); + } + + @Test + public void txnIdSerde() + { + DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(AccordGens.txnIds()).check(txnId -> Serializers.testSerde(output, CommandSerializers.txnId, txnId)); } } diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/CommandStoreSerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/CommandStoreSerializersTest.java index 35b0cee6a5..6b1211c98f 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/CommandStoreSerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/CommandStoreSerializersTest.java @@ -18,21 +18,17 @@ package org.apache.cassandra.service.accord.serializers; -import java.util.List; - import org.junit.Test; import accord.local.RedundantBefore; import accord.utils.Gens; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.Murmur3Partitioner; -import org.apache.cassandra.io.IVersionedSerializers; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService.Version; import org.apache.cassandra.utils.AccordGenerators; import static accord.utils.Property.qt; -import static org.apache.cassandra.net.MessagingService.Version.VERSION_51; public class CommandStoreSerializersTest { @@ -42,8 +38,6 @@ public class CommandStoreSerializersTest DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); } - private static final List SUPPORTED_VERSIONS = VERSION_51.greaterThanOrEqual(); - @Test public void redundantBeforeEntry() { @@ -51,8 +45,7 @@ public class CommandStoreSerializersTest qt().forAll(Gens.random(), AccordGenerators.partitioner()).check((rs, partitioner) -> { DatabaseDescriptor.setPartitionerUnsafe(partitioner); RedundantBefore.Bounds entry = AccordGenerators.redundantBeforeEntry(partitioner).next(rs); - for (Version version : SUPPORTED_VERSIONS) - IVersionedSerializers.testSerde(buffer, CommandStoreSerializers.redundantBeforeEntry, entry, version.value); + Serializers.testSerde(buffer, CommandStoreSerializers.redundantBeforeEntry, entry); }); } @@ -64,8 +57,7 @@ public class CommandStoreSerializersTest DatabaseDescriptor.setPartitionerUnsafe(partitioner); // serializer doesn't support the empty set, so filter out RedundantBefore redundantBefore = AccordGenerators.redundantBefore(partitioner).filter(r -> r.size() != 0).next(rs); - for (Version version : SUPPORTED_VERSIONS) - IVersionedSerializers.testSerde(buffer, CommandStoreSerializers.redundantBefore, redundantBefore, version.value); + Serializers.testSerde(buffer, CommandStoreSerializers.redundantBefore, redundantBefore); }); } diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/DepsSerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/DepsSerializersTest.java index 58c3f6f948..d68558f2c6 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/DepsSerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/DepsSerializersTest.java @@ -18,24 +18,20 @@ package org.apache.cassandra.service.accord.serializers; -import java.util.List; - import org.junit.Test; import accord.primitives.Deps; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Murmur3Partitioner; -import org.apache.cassandra.io.IVersionedSerializers; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.schema.Schema; import org.apache.cassandra.schema.SchemaProvider; import org.apache.cassandra.utils.AccordGenerators; import org.mockito.Mockito; import static accord.utils.Property.qt; -import static org.apache.cassandra.net.MessagingService.Version.VERSION_51; public class DepsSerializersTest { @@ -45,8 +41,6 @@ public class DepsSerializersTest DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); } - private static final List SUPPORTED_VERSIONS = VERSION_51.greaterThanOrEqual(); - @Test public void serde() { @@ -57,8 +51,7 @@ public class DepsSerializersTest DatabaseDescriptor.setPartitionerUnsafe(partitioner); Mockito.when(Schema.instance.getExistingTablePartitioner(Mockito.any())).thenReturn(partitioner); Deps deps = AccordGenerators.depsGen(partitioner).next(rs); - for (MessagingService.Version version : SUPPORTED_VERSIONS) - IVersionedSerializers.testSerde(buffer, DepsSerializers.deps, deps, version.value); + Serializers.testSerde(buffer, DepsSerializers.deps, deps); }); } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32Test.java b/test/unit/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32Test.java new file mode 100644 index 0000000000..c2f65f8474 --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/serializers/EncodeAsVInt32Test.java @@ -0,0 +1,49 @@ +/* + * 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.service.accord.serializers; + +import org.junit.Test; + +import accord.utils.Gen; +import accord.utils.Gens; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; + +import static accord.utils.Property.qt; + +public class EncodeAsVInt32Test +{ + private static final Gen.IntGen ENUM_RANGE = Gens.ints().between(0, Integer.MAX_VALUE - 1); + + @Test + public void withNulls() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + EncodeAsVInt32 serializer = EncodeAsVInt32.withNulls(Integer::intValue, Integer::valueOf); + qt().forAll(ENUM_RANGE).check(expected -> Serializers.testSerde(output, serializer, expected)); + } + + @Test + public void withoutNulls() + { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + EncodeAsVInt32 serializer = EncodeAsVInt32.withoutNulls(Integer::intValue, Integer::valueOf); + qt().forAll(Gens.ints().all()).check(expected -> Serializers.testSerde(output, serializer, expected)); + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/KeySerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/KeySerializersTest.java index aed4805157..5b1d5ca42e 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/KeySerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/KeySerializersTest.java @@ -20,22 +20,24 @@ package org.apache.cassandra.service.accord.serializers; import org.junit.Test; -import accord.primitives.Range; import accord.primitives.Ranges; import accord.utils.Gen; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.io.IVersionedSerializers; +import org.apache.cassandra.dht.Murmur3Partitioner; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.service.accord.TokenRange; import org.apache.cassandra.utils.AccordGenerators; import static accord.utils.Property.qt; +import static org.apache.cassandra.utils.AccordGenerators.maybeUpdatePartitioner; public class KeySerializersTest { static { DatabaseDescriptor.clientInitialization(); + // If the first example is "[]" then need a partitioner for static init + DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); } @Test @@ -44,25 +46,13 @@ public class KeySerializersTest @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); qt().forAll(rangesGen()).check(expected -> { maybeUpdatePartitioner(expected); - IVersionedSerializers.testSerde(output, KeySerializers.ranges, expected, 0); + Serializers.testSerde(output, KeySerializers.ranges, expected); }); } private static Gen rangesGen() { return AccordGenerators.partitioner() - .flatMap(r -> AccordGenerators.ranges(r)); - } - - public static boolean maybeUpdatePartitioner(Ranges ranges) - { - if (ranges.isEmpty()) return false; - for (Range range : ranges) - { - TokenRange tr = (TokenRange) range; - DatabaseDescriptor.setPartitionerUnsafe(tr.start().token().getPartitioner()); - return true; - } - return false; + .flatMap(AccordGenerators::rangesSplitOrArbitrary); } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/LatestDepsSerializerTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/LatestDepsSerializerTest.java index a873957d64..b0e090ff2a 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/LatestDepsSerializerTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/LatestDepsSerializerTest.java @@ -18,53 +18,18 @@ package org.apache.cassandra.service.accord.serializers; -import java.nio.ByteBuffer; -import java.util.List; - -import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import accord.primitives.LatestDeps; -import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.dht.Murmur3Partitioner; -import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService.Version; - -import static org.apache.cassandra.net.MessagingService.Version.VERSION_51; - public class LatestDepsSerializerTest { - @BeforeClass - public static void setup() - { - DatabaseDescriptor.clientInitialization(); - DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); - } - - private static final List SUPPORTED_VERSIONS = VERSION_51.greaterThanOrEqual(); - @Test public void emptySerializerTest() throws Throwable { - for (Version ver : SUPPORTED_VERSIONS) - { - ByteBuffer bb = null; - try (DataOutputBuffer buf = new DataOutputBuffer()) - { - long expected = LatestDepsSerializers.latestDeps.serializedSize(LatestDeps.EMPTY, ver.value); - LatestDepsSerializers.latestDeps.serialize(LatestDeps.EMPTY, buf, ver.value); - bb = buf.asNewBuffer(); - Assert.assertEquals(expected, bb.capacity()); - } - - try (DataInputBuffer in = new DataInputBuffer(bb, false)) - { - LatestDeps roundTrip = LatestDepsSerializers.latestDeps.deserialize(in, ver.value); - Assert.assertEquals(roundTrip, LatestDeps.EMPTY); - } - } + DataOutputBuffer buf = new DataOutputBuffer(); + Serializers.testSerde(buf, LatestDepsSerializers.latestDeps, LatestDeps.EMPTY); } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/TokenKeyTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/TokenKeyTest.java index 9cecb33186..5d3e023b20 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/TokenKeyTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/TokenKeyTest.java @@ -18,17 +18,21 @@ package org.apache.cassandra.service.accord.serializers; +import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.junit.Before; import org.junit.Test; import accord.utils.Gen; import accord.utils.Gens; import accord.utils.Invariants; +import accord.utils.LazyToString; +import accord.utils.ReflectionUtils; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.marshal.ByteBufferAccessor; import org.apache.cassandra.dht.ByteOrderedPartitioner; @@ -38,6 +42,7 @@ import org.apache.cassandra.dht.Murmur3Partitioner.LongToken; import org.apache.cassandra.dht.RandomPartitioner; import org.apache.cassandra.dht.RandomPartitioner.BigIntegerToken; import org.apache.cassandra.dht.Token; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.io.util.DataInputBuffer; import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.schema.TableId; @@ -58,23 +63,75 @@ public class TokenKeyTest static { DatabaseDescriptor.clientInitialization(); + } + + @Before + public void before() + { // AccordRoutingKey$TokenKey reaches into DD to get partitioner, so need to set that up... DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); } + @Test + public void beforeIsTokenSentinel() + { + qt().forAll(simpleTokenKey()).check(tokenKey -> { + var t = tokenKey.before(); + Assertions.assertThat(t.isTokenSentinel()).isTrue(); + Assertions.assertThat(t.isTableSentinel()).isEqualTo(tokenKey.isTableSentinel()); + Assertions.assertThat(t.isMin()).isEqualTo(tokenKey.isMin()); + Assertions.assertThat(t.isMax()).isEqualTo(tokenKey.isMax()); + Assertions.assertThat(t.isBefore()).isTrue(); + Assertions.assertThat(t.isAfter()).isFalse(); + + Assertions.assertThatThrownBy(() -> t.before()); + Assertions.assertThatThrownBy(() -> t.after()); + + Assertions.assertThat(tokenKey.compareTo(t)).isGreaterThan(0); + Assertions.assertThat(t.compareTo(tokenKey)).isLessThan(0); + }); + } + + @Test + public void afterIsTokenSentinel() + { + qt().forAll(simpleTokenKey()).check(tokenKey -> { + var t = tokenKey.after(); + Assertions.assertThat(t.isTokenSentinel()).isTrue(); + Assertions.assertThat(t.isTableSentinel()).isEqualTo(tokenKey.isTableSentinel()); + Assertions.assertThat(t.isMin()).isEqualTo(tokenKey.isMin()); + Assertions.assertThat(t.isMax()).isEqualTo(tokenKey.isMax()); + Assertions.assertThat(t.isBefore()).isFalse(); + Assertions.assertThat(t.isAfter()).isTrue(); + + Assertions.assertThat(tokenKey.compareTo(t)).isLessThan(0); + Assertions.assertThat(t.compareTo(tokenKey)).isGreaterThan(0); + }); + } + + @Test + public void serdeSimple() + { + Gen tokenKeyGen = AccordGenerators.allowBeforeAndAfter(simpleTokenKey()); + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(tokenKeyGen).check(expected -> { + DatabaseDescriptor.setPartitionerUnsafe(expected.token().getPartitioner()); + Serializers.testSerde(output, serializer, expected); + testSerdePrefix(output, serializer, expected); + }); + } + @Test public void serde() { - qt().forAll(fromQT(partitioners().assuming(IPartitioner::accordSupported)).flatMap(partitioner -> routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(token(partitioner)), partitioner))) + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(tokenKeyWithBeforeAndAfterGen()) .check(key -> { IPartitioner partitioner = key.token().getPartitioner(); - { - ByteBuffer buffer = serializer.serialize(key); - TokenKey roundTrip = serializer.deserialize(buffer, partitioner); - TokenKey roundTrip2 = serializer.deserializeAndConsume(buffer, partitioner); - Assertions.assertThat(roundTrip).isEqualTo(key); - Assertions.assertThat(roundTrip2).isEqualTo(key); - } + DatabaseDescriptor.setPartitionerUnsafe(partitioner); + + Serializers.testSerde(output, serializer, key); + Assertions.assertThat(serializer.deserializeAndConsume(serializer.serialize(key), partitioner)).isEqualTo(key); { TokenKey roundTrip = serializer.deserializeWithPrefixAndImpliedLength(key.prefix(), serializer.serializeWithoutPrefixOrLength(key), partitioner); Assertions.assertThat(roundTrip).isEqualTo(key); @@ -91,22 +148,12 @@ public class TokenKeyTest TokenKey roundTrip = serializer.deserializeWithPrefix(key.prefix(), serializer.serializedSizeWithoutPrefix(key), serializer.serializeWithoutPrefixOrLength(key), ByteBufferAccessor.instance, 0, partitioner); Assertions.assertThat(roundTrip).isEqualTo(key); } - try (DataOutputBuffer buf = new DataOutputBuffer()) + output.clear(); + serializer.serialize(key, output); + try (DataInputBuffer in = new DataInputBuffer(output.toByteArray())) { - serializer.serialize(key, buf, 0); - byte[] bytes = buf.toByteArray(); - Assertions.assertThat(bytes.length).isEqualTo(serializer.serializedSize(key, 0)); - try (DataInputBuffer in = new DataInputBuffer(bytes)) - { - TokenKey roundTrip = serializer.deserialize(in, 0, partitioner); - Assertions.assertThat(roundTrip).isEqualTo(key); - Invariants.require(0 == in.available()); - } - try (DataInputBuffer in = new DataInputBuffer(bytes)) - { - serializer.skip(in, 0, partitioner); - Invariants.require(0 == in.available()); - } + serializer.skip(in, partitioner); + Invariants.require(0 == in.available()); } }); } @@ -114,7 +161,7 @@ public class TokenKeyTest @Test public void compare() { - qt().forAll(fromQT(partitioners().assuming(IPartitioner::accordSupported)).flatMap(partitioner -> routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(token(partitioner)), partitioner))) + qt().forAll(tokenKeyGen()) .check(key -> { ByteBuffer keyBytes = serializer.serialize(key); for (TokenKey test : mutateAfter(key)) @@ -132,6 +179,36 @@ public class TokenKeyTest }); } + private static Gen simpleTokenKey() + { + return AccordGenerators.partitioner().flatMap(p -> AccordGenerators.routingKeysGen(p)); + } + + private static void testSerdePrefix(DataOutputBuffer output, TokenKey.Serializer serializer, TokenKey input) throws IOException + { + output.clear(); + Object expected = input.prefix(); + long expectedSize = serializer.serializedSizeOfPrefix(expected); + serializer.serializePrefix(expected, output); + Assertions.assertThat(output.getLength()).describedAs("The serialized size and bytes written do not match").isEqualTo(expectedSize); + DataInputBuffer in = new DataInputBuffer(output.unsafeGetBufferAndFlip(), false); + Object read = serializer.deserializePrefix(in); + Assertions.assertThat(read) + .describedAs("The deserialized output does not match the serialized input; difference %s", new LazyToString(() -> ReflectionUtils.recursiveEquals(read, expected).toString())) + .isEqualTo(expected); + } + + private static Gen tokenKeyGen() + { + return fromQT(partitioners()).filter(IPartitioner::accordSupported) + .flatMap(partitioner -> routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(token(partitioner)), partitioner)); + } + + private static Gen tokenKeyWithBeforeAndAfterGen() + { + return AccordGenerators.allowBeforeAndAfter(tokenKeyGen()); + } + private List mutateAfter(TokenKey mutate) { List results = new ArrayList<>(); @@ -273,13 +350,16 @@ public class TokenKeyTest private static void add(List to, TokenKey vary) { to.add(vary); - to.add(vary.before()); - to.add(vary.after()); + if (!vary.isTokenSentinel()) + { + to.add(vary.before()); + to.add(vary.after()); + } } private static Gen routingKeyGen(Gen tableIdGen, Gen tokenGen, IPartitioner partitioner) { - Gen result = AccordGenerators.routingKeyGen(tableIdGen, Gens.enums().all(TokenKey.RoutingKeyKind.class), tokenGen, partitioner); + Gen result = AccordGenerators.routingKeyGen(tableIdGen, Gens.enums().all(AccordGenerators.RoutingKeyKind.class), tokenGen, partitioner); if (!(partitioner instanceof ByteOrderedPartitioner)) return result; return result.map((rs, k) -> { diff --git a/test/unit/org/apache/cassandra/service/accord/serializers/TopologySerializersTest.java b/test/unit/org/apache/cassandra/service/accord/serializers/TopologySerializersTest.java index b7f31883be..0740fae856 100644 --- a/test/unit/org/apache/cassandra/service/accord/serializers/TopologySerializersTest.java +++ b/test/unit/org/apache/cassandra/service/accord/serializers/TopologySerializersTest.java @@ -18,29 +18,43 @@ package org.apache.cassandra.service.accord.serializers; +import java.io.IOException; + import org.junit.Test; import accord.local.Node; +import accord.utils.AccordGens; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.utils.SerializerTestUtils; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.utils.AccordGenerators; + +import static accord.utils.Property.qt; public class TopologySerializersTest { static { - DatabaseDescriptor.toolInitialization(); + DatabaseDescriptor.clientInitialization(); } @Test - public void nodeId() + public void nodeId() throws IOException { - SerializerTestUtils.assertSerializerIOEquality(new Node.Id(1234567890), TopologySerializers.nodeId); + qt().forAll(AccordGens.nodes()).check(n -> Serializers.testSerde(TopologySerializers.nodeId, n)); } @Test - public void requestScopeTest() + public void topology() { + @SuppressWarnings({ "resource", "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(AccordGenerators.partitioner().flatMap(p -> AccordGenerators.topologyGen(p))).check(expected -> { + AccordGenerators.maybeUpdatePartitioner(expected.ranges()); + Serializers.testSerde(output, TopologySerializers.topology, expected); + for (Node.Id node : expected.nodes()) + Serializers.testSerde(output, TopologySerializers.topology, expected.forNode(node)); + }); } } diff --git a/test/unit/org/apache/cassandra/service/accord/txn/AccordUpdateTest.java b/test/unit/org/apache/cassandra/service/accord/txn/AccordUpdateTest.java index bad4074849..1ae22aaed3 100644 --- a/test/unit/org/apache/cassandra/service/accord/txn/AccordUpdateTest.java +++ b/test/unit/org/apache/cassandra/service/accord/txn/AccordUpdateTest.java @@ -18,16 +18,19 @@ package org.apache.cassandra.service.accord.txn; +import java.io.IOException; + import org.junit.BeforeClass; import org.junit.Test; import accord.primitives.Txn; import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.io.Serializers; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.service.accord.AccordTestUtils; +import org.apache.cassandra.service.accord.serializers.Version; import static org.apache.cassandra.cql3.statements.schema.CreateTableStatement.parse; -import static org.apache.cassandra.utils.SerializerTestUtils.assertSerializerIOEquality; public class AccordUpdateTest { @@ -41,10 +44,11 @@ public class AccordUpdateTest } @Test - public void predicateSerializer() + public void predicateSerializer() throws IOException { Txn txn = AccordTestUtils.createTxn(0, 0); AccordUpdate update = (AccordUpdate) txn.update(); - assertSerializerIOEquality(update, AccordUpdate.serializer); + for (Version version : Version.V1.greaterThanOrEqual()) + Serializers.testSerde(AccordUpdate.serializer, update, version); } } \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/service/accord/txn/TxnConditionTest.java b/test/unit/org/apache/cassandra/service/accord/txn/TxnConditionTest.java new file mode 100644 index 0000000000..5c77379411 --- /dev/null +++ b/test/unit/org/apache/cassandra/service/accord/txn/TxnConditionTest.java @@ -0,0 +1,173 @@ +/* + * 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.service.accord.txn; + +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nullable; + +import org.junit.Test; + +import accord.utils.Gen; +import accord.utils.Gens; +import org.apache.cassandra.cql3.conditions.ColumnCondition; +import org.apache.cassandra.cql3.conditions.ColumnConditionTest; +import org.apache.cassandra.db.Clustering; +import org.apache.cassandra.db.rows.CellPath; +import org.apache.cassandra.io.Serializers; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.schema.ColumnMetadata; +import org.apache.cassandra.schema.MockSchema; +import org.apache.cassandra.schema.Schema; +import org.apache.cassandra.service.accord.serializers.Version; +import org.apache.cassandra.transport.ProtocolVersion; +import org.apache.cassandra.utils.ByteBufferUtil; +import org.apache.cassandra.utils.CassandraGenerators; +import org.apache.cassandra.utils.Generators; + +import static accord.utils.Property.qt; + +//TOOD (maintaince): rather than copy the condition supported kinds, maybe references directly from the type? +public class TxnConditionTest +{ + private static final SchemaProvider SCHEMA = new SchemaProvider(); + static + { + // ColumnMetadata serializer only stores the ks/table/name and uses Schema to load it + Schema.instance = SCHEMA; + } + + private static Gen BOOLEAN_KIND_GEN = Gens.pick(TxnCondition.Kind.AND, TxnCondition.Kind.OR); + private static Gen EXISTS_KIND_GEN = Gens.pick(TxnCondition.Kind.IS_NOT_NULL, TxnCondition.Kind.IS_NULL); + private static Gen VALUE_KIND_GEN = Gens.pick(TxnCondition.Kind.EQUAL, TxnCondition.Kind.NOT_EQUAL, + TxnCondition.Kind.GREATER_THAN, TxnCondition.Kind.GREATER_THAN_OR_EQUAL, + TxnCondition.Kind.LESS_THAN, TxnCondition.Kind.LESS_THAN_OR_EQUAL); + private static Gen PROTOCOL_VERSION_GEN = Gens.enums().all(ProtocolVersion.class); + private static Gen COLUM_METADATA_GEN = Generators.toGen(CassandraGenerators.columnMetadataGen()).map(cm -> { + SCHEMA.add(cm); + return cm; + }); + private static Gen BYTES_GEN = Generators.toGen(Generators.directAndHeapBytes(0, 10)); + private static Gen TXN_REF_GEN = rs -> { + return rs.nextBoolean() ? new TxnReference(rs.nextInt(0, Integer.MAX_VALUE), COLUM_METADATA_GEN.next(rs)) + : new TxnReference(rs.nextInt(0, Integer.MAX_VALUE), COLUM_METADATA_GEN.next(rs), CellPath.create(BYTES_GEN.next(rs))); + }; + private static Gen> CLUSTERING_GEN = Generators.toGen(CassandraGenerators.CLUSTERING_GEN); + private static Gen BOUND_GEN = ColumnConditionTest.boundGen().map(b -> { + SCHEMA.add(b.column); + return b; + }); + + @Test + public void serde() + { + DataOutputBuffer output = new DataOutputBuffer(); + qt().forAll(txnConditionGen()).check(condition -> { + for (Version version : Version.V1.greaterThanOrEqual()) + Serializers.testSerde(output, TxnCondition.serializer, condition, version); + SCHEMA.clear(); + }); + } + + private Gen txnConditionGen() + { + return rs -> { + switch (rs.nextInt(1, 5)) + { + case 0: return TxnCondition.none(); + case 1: return new TxnCondition.Exists(TXN_REF_GEN.next(rs), EXISTS_KIND_GEN.next(rs)); + case 2: return new TxnCondition.Value(TXN_REF_GEN.next(rs), VALUE_KIND_GEN.next(rs), BYTES_GEN.next(rs), PROTOCOL_VERSION_GEN.next(rs)); + case 3: return new TxnCondition.ColumnConditionsAdapter(CLUSTERING_GEN.next(rs), Gens.lists(BOUND_GEN).ofSizeBetween(0, 3).next(rs)); + case 4: return new TxnCondition.BooleanGroup(BOOLEAN_KIND_GEN.next(rs), Gens.lists(txnConditionGen()).ofSizeBetween(0, 3).next(rs)); + default: throw new AssertionError(); + } + }; + } + + private static class SchemaProvider extends MockSchema.MockSchemaProvider + { + private final class Key + { + private final String keyspace, table; + private final ByteBuffer name; + + private Key(String keyspace, String table, ByteBuffer name) + { + this.keyspace = keyspace; + this.table = table; + this.name = name; + } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Key key = (Key) o; + return keyspace.equals(key.keyspace) && table.equals(key.table) && name.equals(key.name); + } + + @Override + public int hashCode() + { + return Objects.hash(keyspace, table, name); + } + + @Override + public String toString() + { + try + { + return keyspace + "." + table + "/" + ByteBufferUtil.string(name); + } + catch (CharacterCodingException e) + { + throw new RuntimeException(e); + } + } + } + private final Map columns = new HashMap<>(); + + public void add(ColumnMetadata cm) + { + columns.put(new Key(cm.ksName, cm.cfName, cm.name.bytes), cm); + } + + public void clear() + { + columns.clear(); + } + + @Nullable + @Override + public ColumnMetadata getColumnMetadata(String keyspace, String table, ByteBuffer name) + { + Key key = new Key(keyspace, table, name); + ColumnMetadata match = columns.get(key); + if (match == null) + { + throw new AssertionError("Unable to find ColumnMetadata for " + key + "; known columns are " + columns.keySet()); + } + return match; + } + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/utils/AccordGenerators.java b/test/unit/org/apache/cassandra/utils/AccordGenerators.java index ce6896fa33..03c230d9c1 100644 --- a/test/unit/org/apache/cassandra/utils/AccordGenerators.java +++ b/test/unit/org/apache/cassandra/utils/AccordGenerators.java @@ -18,23 +18,28 @@ package org.apache.cassandra.utils; +import java.lang.reflect.Array; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.NavigableMap; import java.util.Set; +import java.util.TreeSet; import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Sets; import accord.local.Command; import accord.local.Command.Truncated; import accord.local.ICommand; import accord.local.DurableBefore; +import accord.local.Node; import accord.local.RedundantBefore; import accord.local.RedundantBefore.Bounds; import accord.local.StoreParticipants; @@ -55,12 +60,17 @@ import accord.primitives.Timestamp; import accord.primitives.Txn; import accord.primitives.TxnId; import accord.primitives.Writes; +import accord.topology.Shard; +import accord.topology.Topology; import accord.utils.AccordGens; import accord.utils.Gen; import accord.utils.Gens; import accord.utils.RandomSource; import accord.utils.ReducingRangeMap; +import accord.utils.SortedArrays.SortedArrayList; +import accord.utils.TinyEnumSet; import accord.utils.TriFunction; +import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.dht.AccordSplitter; import org.apache.cassandra.dht.IPartitioner; @@ -95,6 +105,18 @@ public class AccordGenerators { } + public static boolean maybeUpdatePartitioner(Ranges ranges) + { + if (ranges.isEmpty()) return false; + for (Range range : ranges) + { + TokenRange tr = (TokenRange) range; + DatabaseDescriptor.setPartitionerUnsafe(tr.start().token().getPartitioner()); + return true; + } + return false; + } + public static Gen partitioner() { return PARTITIONER_GEN.filter(IPartitioner::accordSupported); @@ -298,7 +320,7 @@ public class AccordGenerators else return Truncated.truncated(command, saveStatus, executeAt, null, null, null, null); case TruncatedApplyWithOutcome: - if (txnId.kind().awaitsOnlyDeps()) return Truncated.truncated(command, saveStatus, executeAt, command.partialDeps(), txnId.is(Write) ? new Writes(txnId, executeAt, keysOrRanges,new TxnWrite(Collections.emptyList(), true)) : null, new TxnData(), txnId); + if (txnId.kind().awaitsOnlyDeps()) return Truncated.truncated(command, saveStatus, executeAt, command.partialDeps(), txnId.is(Write) ? new Writes(txnId, executeAt, keysOrRanges, new TxnWrite(Collections.emptyList(), true)) : null, new TxnData(), txnId); else return Truncated.truncated(command, saveStatus, executeAt, command.partialDeps(), txnId.is(Write) ? new Writes(txnId, executeAt, keysOrRanges, new TxnWrite(Collections.emptyList(), true)) : null, new TxnData(), null); case Erased: @@ -326,7 +348,7 @@ public class AccordGenerators return rs -> new PartitionKey(tableIdGen.next(rs), key.next(rs)); } - public static Gen routingKeys(IPartitioner partitioner) + public static Gen routingKeysGen(IPartitioner partitioner) { return routingKeyGen(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(CassandraGenerators.token(partitioner)), @@ -335,20 +357,23 @@ public class AccordGenerators public static Gen routingKeyGen(Gen tableIdGen, Gen tokenGen, IPartitioner partitioner) { - return routingKeyGen(tableIdGen, Gens.enums().all(TokenKey.RoutingKeyKind.class), tokenGen, partitioner); + return routingKeyGen(tableIdGen, Gens.enums().all(RoutingKeyKind.class), tokenGen, partitioner); } - public static Gen routingKeyGen(Gen tableIdGen, Gen kindGen, Gen tokenGen, IPartitioner partitioner) + public enum RoutingKeyKind + { + TOKEN, SENTINEL + } + + public static Gen routingKeyGen(Gen tableIdGen, Gen kindGen, Gen tokenGen, IPartitioner partitioner) { return rs -> { TableId tableId = tableIdGen.next(rs); - TokenKey.RoutingKeyKind kind = kindGen.next(rs); + RoutingKeyKind kind = kindGen.next(rs); switch (kind) { case TOKEN: return new TokenKey(tableId, tokenGen.next(rs)); - case MIN_TOKEN: - return TokenKey.before(tableId, tokenGen.next(rs)); case SENTINEL: return rs.nextBoolean() ? TokenKey.min(tableId, partitioner) : TokenKey.max(tableId, partitioner); default: @@ -357,9 +382,23 @@ public class AccordGenerators }; } + public static Gen allowBeforeAndAfter(Gen gen) + { + return gen.map((rs, key) -> { + if (key.isTokenSentinel()) return key; + switch (rs.nextInt(0, 3)) + { + case 0: return key; + case 1: return key.before(); + case 2: return key.after(); + default: throw new AssertionError(); + } + }); + } + public static Gen range() { - return PARTITIONER_GEN.flatMap(partitioner -> range(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(CassandraGenerators.token(partitioner)), partitioner)); + return partitioner().flatMap(partitioner -> range(fromQT(CassandraGenerators.TABLE_ID_GEN), fromQT(CassandraGenerators.token(partitioner)), partitioner)); } public static Gen range(IPartitioner partitioner) @@ -370,20 +409,28 @@ public class AccordGenerators public static Gen range(Gen tables, Gen tokenGen, IPartitioner partitioner) { return rs -> { - Gen gen = routingKeyGen(Gens.constant(tables.next(rs)), tokenGen, partitioner); + Gen gen = allowBeforeAndAfter(routingKeyGen(Gens.constant(tables.next(rs)), tokenGen, partitioner)); TokenKey a = gen.next(rs); TokenKey b = gen.next(rs); - while (a.equals(b)) + while (same(a, b)) b = gen.next(rs); - if (a.compareTo(b) < 0) return TokenRange.create(a, b); - else return TokenRange.create(b, a); + return a.compareTo(b) < 0 ? TokenRange.create(a, b) : TokenRange.create(b, a); }; } + private static boolean same(TokenKey a, TokenKey b) + { + if (a.equals(b)) return true; + // define +Inf == before(+Inf) as these are not actionable ranges + return a.isTableSentinel() && b.isTableSentinel() + && a.isMin() == b.isMin() + && a.isMax() == b.isMax(); + } + public static Gen ranges() { // javac couldn't pick the right constructor with HashSet::new, so had to create new lambda... - return ranges(Gens.lists(fromQT(CassandraGenerators.TABLE_ID_GEN)).unique().ofSizeBetween(1, 10).map(l -> new HashSet<>(l)), PARTITIONER_GEN); + return ranges(Gens.lists(fromQT(CassandraGenerators.TABLE_ID_GEN)).unique().ofSizeBetween(1, 10).map(l -> new HashSet<>(l)), partitioner()); } public static Gen ranges(Gen> tableIdGen, Gen partitionerGen) @@ -417,6 +464,12 @@ public class AccordGenerators return ranges(Gens.lists(fromQT(CassandraGenerators.TABLE_ID_GEN)).unique().ofSizeBetween(1, 10).map(l -> new HashSet<>(l)), ignore -> partitioner); } + public static Gen ranges(TableId tableId, IPartitioner partitioner) + { + Set tables = Collections.singleton(tableId); + return ranges(i -> tables, i -> partitioner); + } + public static Gen rangesArbitrary(IPartitioner partitioner) { Gen rangeGen = range(partitioner); @@ -430,14 +483,21 @@ public class AccordGenerators }; } + public static Gen rangesSplitOrArbitrary(IPartitioner partitioner) + { + Gen split = ranges(partitioner); + Gen arbitrary = rangesArbitrary(partitioner); + return rs -> rs.nextBoolean() ? split.next(rs) : arbitrary.next(rs); + } + public static Gen keyDepsGen(IPartitioner partitioner) { - return AccordGens.keyDeps(AccordGenerators.routingKeys(partitioner)); + return AccordGens.keyDeps(AccordGenerators.routingKeysGen(partitioner)); } public static Gen directKeyDepsGen(IPartitioner partitioner) { - return AccordGens.directKeyDeps(AccordGenerators.routingKeys(partitioner)); + return AccordGens.directKeyDeps(AccordGenerators.routingKeysGen(partitioner)); } public static Gen rangeDepsGen(IPartitioner partitioner) @@ -561,6 +621,94 @@ public class AccordGenerators }; } + public static Gen> shardFlagsGen() + { + return rs -> { + if (rs.nextBoolean()) return Shard.NO_FLAGS; + EnumSet flags = EnumSet.noneOf(Shard.Flag.class); + for (Shard.Flag v : Shard.Flag.values()) + { + if (rs.nextBoolean()) + flags.add(v); + } + return new TinyEnumSet<>(flags.toArray(Shard.Flag[]::new)); + }; + } + + public static > Gen> sortedArrayList(Class klass, Gen.IntGen sizeGen, Gen valueGen) + { + return rs -> { + int size = sizeGen.nextInt(rs); + if (size == 0) return SortedArrayList.ofSorted(); + return SortedArrayList.copyUnsorted(Gens.lists(valueGen).unique().ofSize(size).next(rs), s -> (T[]) Array.newInstance(klass, s)); + }; + } + + private static Gen> select(List list, int size) + { + // This is better in Gens, but didn't want to alter Accord in this patch... + if (size < 0 || size > list.size()) + throw new IllegalArgumentException("Unexpected size: " + size + ", list size is " + list.size()); + if (size == 0) return i -> List.of(); + if (size == list.size()) return i -> list; + return rs -> { + List toSelect = new ArrayList<>(list); + List selected = new ArrayList<>(size); + for (int i = 0; i < size; i++) + { + int idx = rs.nextInt(0, toSelect.size()); + selected.add(toSelect.remove(idx)); + } + return selected; + }; + } + + private static Gen shardGen(Range range) + { + Gen> nodesGen = sortedArrayList(Node.Id.class, Gens.ints().between(1, 10), AccordGens.nodes()); + Gen> shardFlagsGen = shardFlagsGen(); + return rs -> { + SortedArrayList nodes = nodesGen.next(rs); + int maxFailures = Shard.maxToleratedFailures(nodes.size()); + int slowQuorumSize = Shard.slowQuorumSize(nodes.size()); + Set fastPathElectorate = new TreeSet<>(select(nodes, nodes.size() == slowQuorumSize ? slowQuorumSize : rs.nextInt(slowQuorumSize, nodes.size())).next(rs)); + List nonFastPath = new ArrayList<>(Sets.difference(new HashSet<>(nodes), fastPathElectorate)); + nonFastPath.sort(Comparator.naturalOrder()); + Set joining = new TreeSet<>(select(nonFastPath, nonFastPath.size() == 0 ? 0 : rs.nextInt(0, nonFastPath.size())).next(rs)); + return Shard.create(range, nodes, fastPathElectorate, joining, shardFlagsGen.next(rs)); + }; + } + + public static Gen topologyGen(IPartitioner partitioner) + { + return topologyGen(AccordGens.epochs(), partitioner); + } + + public static Gen topologyGen(Gen.LongGen epochGen, IPartitioner partitioner) + { + return topologyGen(epochGen, ranges(partitioner)); + } + + public static Gen topologyGen(Gen rangesGen) + { + return topologyGen(AccordGens.epochs(), rangesGen); + } + + public static Gen topologyGen(Gen.LongGen epochGen, Gen rangesGen) + { + return rs -> { + long epoch = epochGen.nextLong(rs); + Ranges ranges = rangesGen.next(rs); + if (ranges.isEmpty()) return new Topology(epoch, new Shard[0]); + + List shards = new ArrayList<>(ranges.size()); + for (Range range : ranges) + shards.add(shardGen(range).next(rs)); + //TODO (coverage): staleNodes + return new Topology(epoch, shards.toArray(Shard[]::new)); + }; + } + public static Gen fromQT(org.quicktheories.core.Gen qt) { return rs -> { diff --git a/test/unit/org/apache/cassandra/utils/CassandraGenerators.java b/test/unit/org/apache/cassandra/utils/CassandraGenerators.java index b8cab9a39e..ea34b72cb0 100644 --- a/test/unit/org/apache/cassandra/utils/CassandraGenerators.java +++ b/test/unit/org/apache/cassandra/utils/CassandraGenerators.java @@ -68,6 +68,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.cql3.Duration; import org.apache.cassandra.cql3.FieldIdentifier; +import org.apache.cassandra.db.Clustering; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.db.ReadCommand; import org.apache.cassandra.db.SchemaCQLHelper; @@ -138,6 +139,7 @@ import static org.apache.cassandra.utils.Generators.IDENTIFIER_GEN; import static org.apache.cassandra.utils.Generators.SMALL_TIME_SPAN_NANOS; import static org.apache.cassandra.utils.Generators.TIMESTAMP_NANOS; import static org.apache.cassandra.utils.Generators.TINY_TIME_SPAN_NANOS; +import static org.apache.cassandra.utils.Generators.directAndHeapBytes; public final class CassandraGenerators { @@ -206,6 +208,17 @@ public final class CassandraGenerators cast(READ_REPAIR_RSP_GEN)) .describedAs(CassandraGenerators::toStringRecursive); + private static final Constraint CLUSTERING_OPTIONS = Constraint.between(0, 2); + public static final Gen> CLUSTERING_GEN = rnd -> { + switch ((int) rnd.next(CLUSTERING_OPTIONS)) + { + case 0: return Clustering.EMPTY; + case 1: return Clustering.STATIC_CLUSTERING; + case 2: return Clustering.make(Generators.array(ByteBuffer.class, directAndHeapBytes(0, 10), SourceDSL.integers().between(1, 3)).generate(rnd)); + default: throw new AssertionError(); + } + }; + private CassandraGenerators() { diff --git a/test/unit/org/apache/cassandra/utils/CollectionSerializersTest.java b/test/unit/org/apache/cassandra/utils/CollectionSerializersTest.java new file mode 100644 index 0000000000..c0c42c5c9e --- /dev/null +++ b/test/unit/org/apache/cassandra/utils/CollectionSerializersTest.java @@ -0,0 +1,123 @@ +/* + * 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.utils; + +import java.io.IOException; + +import org.junit.Test; + +import accord.utils.Gens; +import org.apache.cassandra.db.TypeSizes; +import org.apache.cassandra.io.IVersionedSerializer; +import org.apache.cassandra.io.UnversionedSerializer; +import org.apache.cassandra.io.VersionedSerializer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.io.util.DataOutputPlus; + +import static accord.utils.Property.qt; +import static org.apache.cassandra.io.Serializers.testSerde; +import static org.apache.cassandra.utils.CollectionSerializers.newListSerializer; + +public class CollectionSerializersTest +{ + @Test + public void serde() + { + // This test is testing the collection serializer and not the serializer it uses for the element. There are + // special things that must be accounted for in the test + // 1) number of elements can hit the different byte counts (vint can be 1-4 bytes) + // 2) element serializer needs to be fast. So this test avoids random values for the element + DataOutputBuffer output = new DataOutputBuffer(); + Integer cached = 42; + // 0 takes 1 bytes + // 128 takes 2 bytes + // 16384 takes 3 bytes + // 2097152 takes 4 bytes + qt().forAll(Gens.lists(i -> cached).ofSizeBetween(0, 2_097_152)).check(list -> { + testSerde(output, newListSerializer((UnversionedSerializer) IntSerializer.instance), list); + testSerde(output, newListSerializer((IVersionedSerializer) IntSerializer.instance), list, 0); + testSerde(output, newListSerializer((VersionedSerializer) IntSerializer.instance), list, Version.V1); + }); + } + + public enum Version + { + V1 + } + + public enum IntSerializer implements UnversionedSerializer, IVersionedSerializer, VersionedSerializer + { + instance; + + @Override + public void serialize(Integer t, DataOutputPlus out) throws IOException + { + out.writeInt(t); + } + + @Override + public void serialize(Integer t, DataOutputPlus out, Version version) throws IOException + { + serialize(t, out); + } + + @Override + public void serialize(Integer t, DataOutputPlus out, int version) throws IOException + { + serialize(t, out); + } + + @Override + public Integer deserialize(DataInputPlus in) throws IOException + { + return in.readInt(); + } + + @Override + public Integer deserialize(DataInputPlus in, Version version) throws IOException + { + return deserialize(in); + } + + @Override + public Integer deserialize(DataInputPlus in, int version) throws IOException + { + return deserialize(in); + } + + @Override + public long serializedSize(Integer t) + { + return TypeSizes.INT_SIZE; + } + + @Override + public long serializedSize(Integer t, Version version) + { + return serializedSize(t); + } + + @Override + public long serializedSize(Integer t, int version) + { + return serializedSize(t); + } + } +} \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/utils/Generators.java b/test/unit/org/apache/cassandra/utils/Generators.java index 6bb7f56a8d..b8013ffee7 100644 --- a/test/unit/org/apache/cassandra/utils/Generators.java +++ b/test/unit/org/apache/cassandra/utils/Generators.java @@ -17,6 +17,7 @@ */ package org.apache.cassandra.utils; +import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; @@ -375,6 +376,11 @@ public final class Generators return bytes(min, max, SourceDSL.arbitrary().pick(BBCases.DIRECT, BBCases.READ_ONLY_DIRECT)); } + public static Gen directAndHeapBytes(int min, int max) + { + return bytes(min, max, SourceDSL.arbitrary().pick(BBCases.DIRECT, BBCases.HEAP)); + } + public static Gen bytesAnyType(int min, int max) { return bytes(min, max, SourceDSL.arbitrary().enumValues(BBCases.class)); @@ -494,6 +500,17 @@ public final class Generators }; } + public static Gen> list(Gen gen, Gen sizeGen) + { + return rnd -> { + int size = sizeGen.generate(rnd); + List list = new ArrayList<>(size); + for (int i = 0; i < size; i++) + list.add(gen.generate(rnd)); + return list; + }; + } + public static Gen> uniqueList(Gen gen, Gen sizeGen) { return rnd -> { @@ -510,6 +527,17 @@ public final class Generators }; } + public static Gen array(Class type, Gen gen, Gen sizeGen) + { + return rnd -> { + int size = sizeGen.generate(rnd); + T[] array = (T[]) Array.newInstance(type, size); + for (int i = 0; i < size; i++) + array[i] = gen.generate(rnd); + return array; + }; + } + public static Gen cached(Gen gen) { Object cacheMissed = new Object(); diff --git a/test/unit/org/apache/cassandra/utils/SerializerTestUtils.java b/test/unit/org/apache/cassandra/utils/SerializerTestUtils.java deleted file mode 100644 index 37435a42a6..0000000000 --- a/test/unit/org/apache/cassandra/utils/SerializerTestUtils.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.utils; - -import java.io.IOException; - -import org.junit.Assert; - -import org.apache.cassandra.io.IVersionedSerializer; -import org.apache.cassandra.io.util.DataInputBuffer; -import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService; - -public class SerializerTestUtils -{ - private static int MS_VERSION = MessagingService.current_version; - - public static T serdes(IVersionedSerializer serializer, T message) - { - int expectedSize = (int) serializer.serializedSize(message, MS_VERSION); - try (DataOutputBuffer out = new DataOutputBuffer(expectedSize)) - { - serializer.serialize(message, out, MS_VERSION); - Assert.assertEquals(expectedSize, out.buffer().limit()); - try (DataInputBuffer in = new DataInputBuffer(out.buffer(), false)) - { - return serializer.deserialize(in, MS_VERSION); - } - } - catch (IOException e) - { - throw new AssertionError(e); - } - } - - public static void assertSerializerIOEquality(T expected, IVersionedSerializer serializer, int version) - { - int expectedSize = (int) serializer.serializedSize(expected, version); - try (DataOutputBuffer out = new DataOutputBuffer(expectedSize)) - { - serializer.serialize(expected, out, version); - Assert.assertEquals(expectedSize, out.buffer().limit()); - try (DataInputBuffer in = new DataInputBuffer(out.buffer(), false)) - { - Assert.assertEquals(expected, serializer.deserialize(in, version)); - } - } - catch (IOException e) - { - throw new AssertionError(e); - } - } - - public static void assertSerializerIOEquality(T expected, IVersionedSerializer serializer) - { - assertSerializerIOEquality(expected, serializer, MS_VERSION); - } -}