Update to newer Core, Bytes & Wire dependency versions; make all enum marshallers ordinary classes with static INSTANCE fields, because of difficulties with Wire serialization of enums

This commit is contained in:
leventov
2016-06-24 17:49:34 +07:00
parent fc6e2af7e4
commit 4cffff652f
23 changed files with 138 additions and 55 deletions
+24 -14
View File
@@ -519,11 +519,13 @@ For example, here is the implementation of `BytesWriter` and `BytesReader` for `
value type (array of CharSequences):
```java
public enum CharSequenceArrayBytesMarshaller
public final class CharSequenceArrayBytesMarshaller
implements BytesWriter<CharSequence[]>, BytesReader<CharSequence[]>,
ReadResolvable<CharSequenceArrayBytesMarshaller> {
INSTANCE;
static final CharSequenceArrayBytesMarshaller INSTANCE = new CharSequenceArrayBytesMarshaller();
private CharSequenceArrayBytesMarshaller() {}
@Override
public void write(Bytes out, @NotNull CharSequence[] toWrite) {
@@ -603,12 +605,15 @@ Some additional notes:
- If the reader or writer interface implementation is not configurable and doesn't have
per-instance cache or state fields, i. e. it doesn't have instance fields at all, there is
a convention to make such implementations `enum`s with a single `INSTANCE` constant.
- For `enum` serialization interface implementations, don't forget to implement `ReadResolvable`
a convention to make such implementation classes `final`, give them a `private` constructor and
expose a single `INSTANCE` constant - a sole instance of this implementation in the JVM.
- *Don't* make marshaller class `enum`, because there are some issues with `enum` serialization/
deserialization.
- For such no-state implementations, don't forget to implement `ReadResolvable`
interface and return `INSTANCE`, otherwise you have no guarantee that `INSTANCE` constant is the
only alive instance of this implementation in the JVM.
- If *both* writer and reader interface implementations have no fields, it might be a good idea
to merge them into a single `enum` type, in order to keep writing and reading logic together.
to merge them into a single type, in order to keep writing and reading logic together.
###### Custom `CharSequence` encoding
@@ -875,7 +880,7 @@ Some notes on this case of custom serialization:
- Both `CharSequenceCustomEncodingBytesWriter` and `CharSequenceCustomEncodingBytesReader` have
configurations (charset and input buffer size), hence they are implemented as normal classes rather
than enums with a single `INSTANCE` constant.
than classes with `private` constructors and a single `INSTANCE`.
- Both writer and reader classes have some "cache" fields, their contents are mutated during
writing and reading. That is why they have to implement `StatefulCopyable` interface. See
[Understanding `StatefulCopyable`](#understanding-statefulcopyable) section for more infromation on
@@ -936,11 +941,13 @@ public final class Point {
Serializer implementation:
```java
public enum PointListSizedMarshaller
public final class PointListSizedMarshaller
implements SizedReader<List<Point>>, SizedWriter<List<Point>>,
ReadResolvable<PointListSizedMarshaller> {
INSTANCE;
static final PointListSizedMarshaller INSTANCE = new PointListSizedMarshaller();
private PointListSizedMarshaller() {}
/** A point takes 16 bytes in serialized form: 8 bytes for both x and y value */
private static final long ELEMENT_SIZE = 16;
@@ -1153,10 +1160,12 @@ right in `Data` interface.
Corresponding `SizedReader` for `byte[]`:
```java
public enum ByteArraySizedReader
public final class ByteArraySizedReader
implements SizedReader<byte[]>, Marshallable, ReadResolvable<ByteArraySizedReader> {
INSTANCE;
public static final ByteArraySizedReader INSTANCE = new ByteArraySizedReader();
private ByteArraySizedReader() {}
@NotNull
@Override
@@ -1274,11 +1283,12 @@ class.
`SizedReader`](#sizedwriter-and-sizedreader) or [`DataAccess` and
`SizedReader`](#dataaccess-and-sizedreader). Recommendations on which pair to choose are given in
the linked sections, describing each pair.
2. If implementation of the writer or reader part is configuration-less, make it a `enum` with
a single `INSTANCE` constant. Implement `ReadResolvable` and return `INSTANCE` from `readResolve()`
method.
2. If implementation of the writer or reader part is configuration-less, give it a `private`
constructor and define a single `INSTANCE` constant -- a sole instance of this marshaller class in
the JVM. Implement `ReadResolvable` and return `INSTANCE` from `readResolve()` method. *But, don't
make implementation a Java `enum`.*
3. If both the writer and reader are configuration-less, merge them into a single `-Marshaller`
`enum` implementation.
implementation class.
4. Make best effort in reusing `using` objects on the reader side (`BytesReader` or `SizedReader`),
including nesting objects.
5. Make best effort in caching intermediate serialization results on writer side while working with
+2 -2
View File
@@ -39,7 +39,7 @@
<groupId>net.openhft</groupId>
<artifactId>third-party-bom</artifactId>
<type>pom</type>
<version>3.5.0</version>
<version>3.5.1</version>
<scope>import</scope>
</dependency>
@@ -47,7 +47,7 @@
<groupId>net.openhft</groupId>
<artifactId>chronicle-bom</artifactId>
<type>pom</type>
<version>1.12.14-SNAPSHOT</version>
<version>1.12.26</version>
<scope>import</scope>
</dependency>
@@ -39,8 +39,10 @@ public interface HashSplitting extends Marshallable {
int segmentIndex(long hash);
long segmentHash(long hash);
enum ForSingleSegment implements HashSplitting, EnumMarshallable<ForSingleSegment> {
INSTANCE;
final class ForSingleSegment implements HashSplitting, EnumMarshallable<ForSingleSegment> {
public static final ForSingleSegment INSTANCE = new ForSingleSegment();
private ForSingleSegment() {}
@Override
public int segmentIndex(long hash) {
@@ -24,10 +24,12 @@ import net.openhft.chronicle.hash.serialization.SizedWriter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum BooleanMarshaller
public final class BooleanMarshaller
implements SizedReader<Boolean>, BytesReader<Boolean>,
SizedWriter<Boolean>, BytesWriter<Boolean>, EnumMarshallable<BooleanMarshaller> {
INSTANCE;
public static final BooleanMarshaller INSTANCE = new BooleanMarshaller();
private BooleanMarshaller() {}
@Override
public long size(@NotNull Boolean e) {
@@ -22,10 +22,12 @@ import net.openhft.chronicle.hash.serialization.SizedReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum ByteArraySizedReader
public final class ByteArraySizedReader
implements SizedReader<byte[]>, EnumMarshallable<ByteArraySizedReader> {
INSTANCE;
public static final ByteArraySizedReader INSTANCE = new ByteArraySizedReader();
private ByteArraySizedReader() {}
@NotNull
@Override
@@ -23,9 +23,11 @@ import org.jetbrains.annotations.Nullable;
import java.nio.ByteBuffer;
public enum ByteBufferSizedReader
public final class ByteBufferSizedReader
implements SizedReader<ByteBuffer>, EnumMarshallable<ByteBufferSizedReader> {
INSTANCE;
public static final ByteBufferSizedReader INSTANCE = new ByteBufferSizedReader();
private ByteBufferSizedReader() {}
@NotNull
@Override
@@ -37,9 +37,11 @@ import java.io.ObjectInputStream;
*
* @see CharSequenceBytesWriter
*/
public enum CharSequenceBytesReader implements BytesReader<CharSequence>,
public final class CharSequenceBytesReader implements BytesReader<CharSequence>,
StatefulCopyable<CharSequenceBytesReader>, EnumMarshallable<CharSequenceBytesReader> {
INSTANCE;
public static final CharSequenceBytesReader INSTANCE = new CharSequenceBytesReader();
private CharSequenceBytesReader() {}
@NotNull
@Override
@@ -30,9 +30,11 @@ import org.jetbrains.annotations.NotNull;
*
* @see StringBytesReader
*/
public enum CharSequenceBytesWriter
public final class CharSequenceBytesWriter
implements BytesWriter<CharSequence>, EnumMarshallable<CharSequenceBytesWriter> {
INSTANCE;
public static final CharSequenceBytesWriter INSTANCE = new CharSequenceBytesWriter();
private CharSequenceBytesWriter() {}
@Override
public void write(Bytes out, @NotNull CharSequence toWrite) {
@@ -25,9 +25,12 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use one of {@link AbstractCharSequenceUtf8DataAccess} subclasses instead
*/
@Deprecated
public enum CharSequenceSizedWriter
@SuppressWarnings("deprecation")
public final class CharSequenceSizedWriter
implements SizedWriter<CharSequence>, EnumMarshallable<CharSequenceSizedWriter> {
INSTANCE;
public static final CharSequenceSizedWriter INSTANCE = new CharSequenceSizedWriter();
private CharSequenceSizedWriter() {}
@Override
public long size(@NotNull CharSequence toWrite) {
@@ -26,10 +26,12 @@ import org.jetbrains.annotations.Nullable;
* deprecated in favor of {@link DoubleDataAccess}. As reader and element writer for {@link
* ListMarshaller} and similar composite marshallers, {@code DoubleMarshaller} is not deprecated.
*/
public enum DoubleMarshaller
public final class DoubleMarshaller
implements SizedReader<Double>, BytesReader<Double>,
SizedWriter<Double>, BytesWriter<Double>, EnumMarshallable<DoubleMarshaller> {
INSTANCE;
public static final DoubleMarshaller INSTANCE = new DoubleMarshaller();
private DoubleMarshaller() {}
@NotNull
@Override
@@ -22,7 +22,19 @@ import net.openhft.chronicle.wire.WireIn;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
public interface EnumMarshallable<E extends Enum<E>> extends Marshallable, ReadResolvable<E> {
/**
* This interface safes many single-constant enum-like subclasses in the
* {@link net.openhft.chronicle.hash.serialization.impl} package from implementing empty
* {@link #readMarshallable} and {@link #writeMarshallable} methods, and forces them to implement
* {@link ReadResolvable}. The name references "Enum" because formerly it allowed only {@code enum}
* subclasses, to enforce a good practice of making enum-like classes actually Java {@code enum}s.
* But changes in Chronicle-Wire, used to serialize/deserialize marshallers in Chronicle Map
* headers, turned {@code enum}s from recommended form of marshaller implementations to impossible
* one. So now there are no subclasses of this interface which are actually {@code enum}s.
*
* @param <E> the subclassing marshaller type
*/
public interface EnumMarshallable<E> extends Marshallable, ReadResolvable<E> {
@Override
default void readMarshallable(@NotNull WireIn wireIn) {
@@ -26,10 +26,12 @@ import org.jetbrains.annotations.Nullable;
* is deprecated in favor of {@link IntegerDataAccess}. As reader and element writer for {@link
* ListMarshaller} and similar composite marshallers, {@code IntegerMarshaller} is not deprecated.
*/
public enum IntegerMarshaller
public final class IntegerMarshaller
implements SizedReader<Integer>, BytesReader<Integer>,
SizedWriter<Integer>, BytesWriter<Integer>, EnumMarshallable<IntegerMarshaller> {
INSTANCE;
public static final IntegerMarshaller INSTANCE = new IntegerMarshaller();
private IntegerMarshaller() {}
@NotNull
@Override
@@ -26,10 +26,12 @@ import org.jetbrains.annotations.Nullable;
* deprecated in favor of {@link LongDataAccess}. As reader and element writer for {@link
* ListMarshaller} and similar composite marshallers, {@code LongMarshaller} is not deprecated.
*/
public enum LongMarshaller
public final class LongMarshaller
implements SizedReader<Long>, BytesReader<Long>,
SizedWriter<Long>, BytesWriter<Long>, EnumMarshallable<LongMarshaller> {
INSTANCE;
public static final LongMarshaller INSTANCE = new LongMarshaller();
private LongMarshaller() {}
@Override
public long size(@NotNull Long toWrite) {
@@ -19,9 +19,11 @@ package net.openhft.chronicle.hash.serialization.impl;
import net.openhft.chronicle.bytes.Byteable;
import net.openhft.chronicle.bytes.BytesMarshallable;
import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.core.util.ReadResolvable;
import net.openhft.chronicle.hash.serialization.*;
import net.openhft.chronicle.values.ValueModel;
import net.openhft.chronicle.values.Values;
import net.openhft.chronicle.wire.Marshallable;
import java.io.*;
import java.lang.reflect.Modifier;
@@ -36,6 +38,17 @@ public final class SerializationBuilder<T> implements Cloneable {
return !c.isInterface() && !Modifier.isAbstract(c.getModifiers());
}
private static void checkNonMarshallableEnum(Class c) {
if (Enum.class.isAssignableFrom(c) && (Marshallable.class.isAssignableFrom(c) ||
ReadResolvable.class.isAssignableFrom(c))) {
throw new IllegalArgumentException(c + ": since Chronicle Map 3.9.0, enum marshaller " +
"shouldn't be a Java enum and implement " + Marshallable.class.getName() +
" or " + ReadResolvable.class.getName() + ". There are problems with " +
"serializing/deserializing them in Chronicle Map header. Emulate enums by " +
"static final fields");
}
}
public final Class<T> tClass;
private SizeMarshaller sizeMarshaller = stopBit();
private SizedReader<T> reader;
@@ -129,10 +142,12 @@ public final class SerializationBuilder<T> implements Cloneable {
}
public void reader(SizedReader<T> reader) {
checkNonMarshallableEnum(reader.getClass());
this.reader = reader;
}
public void reader(BytesReader<T> reader) {
checkNonMarshallableEnum(reader.getClass());
this.reader = new BytesAsSizedReader<>(reader);
}
@@ -141,6 +156,7 @@ public final class SerializationBuilder<T> implements Cloneable {
}
public void dataAccess(DataAccess<T> dataAccess) {
checkNonMarshallableEnum(dataAccess.getClass());
this.dataAccess = dataAccess;
}
@@ -149,14 +165,17 @@ public final class SerializationBuilder<T> implements Cloneable {
}
public void writer(SizedWriter<? super T> writer) {
checkNonMarshallableEnum(writer.getClass());
dataAccess(new SizedMarshallableDataAccess<>(tClass, reader, writer));
}
private void notReusingWriter(SizedWriter<? super T> writer) {
checkNonMarshallableEnum(writer.getClass());
dataAccess(new NotReusingSizedMarshallableDataAccess<>(tClass, reader, writer));
}
public void writer(BytesWriter<? super T> writer) {
checkNonMarshallableEnum(writer.getClass());
dataAccess(new ExternalBytesMarshallableDataAccess<>(tClass, reader, writer));
}
@@ -212,6 +231,7 @@ public final class SerializationBuilder<T> implements Cloneable {
}
public SerializationBuilder<T> sizeMarshaller(SizeMarshaller sizeMarshaller) {
checkNonMarshallableEnum(sizeMarshaller.getClass());
this.sizeMarshaller = sizeMarshaller;
return this;
}
@@ -23,9 +23,11 @@ import net.openhft.chronicle.hash.serialization.SizeMarshaller;
import static java.lang.Math.max;
import static java.lang.Math.min;
public enum StopBitSizeMarshaller
public final class StopBitSizeMarshaller
implements SizeMarshaller, EnumMarshallable<StopBitSizeMarshaller> {
INSTANCE;
public static final StopBitSizeMarshaller INSTANCE = new StopBitSizeMarshaller();
private StopBitSizeMarshaller() {}
private static final long MIN_ENCODABLE_SIZE = Long.MIN_VALUE;
private static final long MAX_ENCODABLE_SIZE = Long.MAX_VALUE;
@@ -22,9 +22,11 @@ import net.openhft.chronicle.hash.serialization.SizedReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum StringBuilderSizedReader
public final class StringBuilderSizedReader
implements SizedReader<StringBuilder>, EnumMarshallable<StringBuilderSizedReader> {
INSTANCE;
public static final StringBuilderSizedReader INSTANCE = new StringBuilderSizedReader();
private StringBuilderSizedReader() {}
@NotNull
@Override
@@ -24,9 +24,11 @@ import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
enum DummyValueMarshaller implements DataAccess<DummyValue>, SizedReader<DummyValue>,
final class DummyValueMarshaller implements DataAccess<DummyValue>, SizedReader<DummyValue>,
EnumMarshallable<DummyValueMarshaller> {
INSTANCE;
public static final DummyValueMarshaller INSTANCE = new DummyValueMarshaller();
private DummyValueMarshaller() {}
@Override
public Data<DummyValue> getData(@NotNull DummyValue instance) {
@@ -32,9 +32,11 @@ import java.util.zip.InflaterInputStream;
/**
* Created by peter on 24/10/14.
*/
public enum DeflatorStringMarshaller implements BytesReader<CharSequence>,
public final class DeflatorStringMarshaller implements BytesReader<CharSequence>,
BytesWriter<CharSequence>, EnumMarshallable<DeflatorStringMarshaller> {
INSTANCE;
public static final DeflatorStringMarshaller INSTANCE = new DeflatorStringMarshaller();
private DeflatorStringMarshaller() {}
private static final StringFactory STRING_FACTORY = getStringFactory();
@@ -54,9 +54,12 @@ public class Issue43Test {
}
}
private enum ArrayMarshaller implements BytesReader<ValueWrapper>, BytesWriter<ValueWrapper>,
private static final class ArrayMarshaller
implements BytesReader<ValueWrapper>, BytesWriter<ValueWrapper>,
EnumMarshallable<ArrayMarshaller> {
INSTANCE;
public static final ArrayMarshaller INSTANCE = new ArrayMarshaller();
private ArrayMarshaller() {}
@Override
public void write(Bytes bytes, @NotNull ValueWrapper vw) {
@@ -129,9 +129,11 @@ public class Issue58 {
}
enum UuidMarshaller
static final class UuidMarshaller
implements BytesReader<UUID>, BytesWriter<UUID>, EnumMarshallable<UuidMarshaller> {
INSTANCE;
public static final UuidMarshaller INSTANCE = new UuidMarshaller();
private UuidMarshaller() {}
@Override
public void write(Bytes bytes, @NotNull UUID uuid) {
@@ -53,8 +53,11 @@ public class PointListSerializationTest {
}
}
enum AMarshaller implements BytesReader<A>, BytesWriter<A>, EnumMarshallable<AMarshaller> {
INSTANCE;
static final class AMarshaller implements BytesReader<A>, BytesWriter<A>,
EnumMarshallable<AMarshaller> {
public static final AMarshaller INSTANCE = new AMarshaller();
private AMarshaller() {}
@Override
public void write(Bytes out, @NotNull A toWrite) {
@@ -28,11 +28,13 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
public enum CharSequenceArrayBytesMarshaller
public final class CharSequenceArrayBytesMarshaller
implements BytesWriter<CharSequence[]>, BytesReader<CharSequence[]>,
ReadResolvable<CharSequenceArrayBytesMarshaller> {
INSTANCE;
static final CharSequenceArrayBytesMarshaller INSTANCE = new CharSequenceArrayBytesMarshaller();
private CharSequenceArrayBytesMarshaller() {}
@Override
public void write(Bytes out, @NotNull CharSequence[] toWrite) {
@@ -28,11 +28,13 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public enum PointListSizedMarshaller
public final class PointListSizedMarshaller
implements SizedReader<List<Point>>, SizedWriter<List<Point>>,
ReadResolvable<PointListSizedMarshaller> {
INSTANCE;
static final PointListSizedMarshaller INSTANCE = new PointListSizedMarshaller();
private PointListSizedMarshaller() {}
/** A point takes 16 bytes in serialized form: 8 bytes for both x and y value */
private static final long ELEMENT_SIZE = 16;