diff --git a/pom.xml b/pom.xml index a41be63a8..e376bf28b 100755 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ net.openhft chronicle-bom pom - 1.10.10-SNAPSHOT + 1.10.12-SNAPSHOT import diff --git a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java index d05b78210..5660c9aa6 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java @@ -89,8 +89,8 @@ public abstract class CompactOffHeapLinearHashTable { } CompactOffHeapLinearHashTable(VanillaChronicleHash h) { - this(h.segmentHashLookupCapacity, h.segmentHashLookupEntrySize, h.segmentHashLookupKeyBits, - h.segmentHashLookupValueBits); + this(h.tierHashLookupCapacity, h.tierHashLookupEntrySize, h.tierHashLookupKeyBits, + h.tierHashLookupValueBits); } abstract long indexToPos(long index); diff --git a/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java b/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java index 66488934e..436540d8b 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java @@ -16,11 +16,18 @@ package net.openhft.chronicle.hash.impl; +import net.openhft.chronicle.bytes.IORuntimeException; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; +import net.openhft.chronicle.wire.Marshallable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; + import java.io.Serializable; import static net.openhft.chronicle.core.Maths.isPowerOf2; -public interface HashSplitting extends Serializable { +public interface HashSplitting extends Serializable, Marshallable { int segmentIndex(long hash); long segmentHash(long hash); @@ -36,7 +43,7 @@ public interface HashSplitting extends Serializable { } } - enum ForSingleSegment implements HashSplitting { + enum ForSingleSegment implements HashSplitting, EnumMarshallable { INSTANCE; @Override @@ -48,13 +55,18 @@ public interface HashSplitting extends Serializable { public long segmentHash(long hash) { return hash; } + + @Override + public ForSingleSegment readResolve() { + return INSTANCE; + } } class ForPowerOf2Segments implements HashSplitting { private static final long serialVersionUID = 0L; - private final int mask; - private final int bits; + private int mask; + private int bits; ForPowerOf2Segments(int segments) { mask = segments - 1; @@ -70,6 +82,18 @@ public interface HashSplitting extends Serializable { public long segmentHash(long hash) { return hash >>> bits; } + + @Override + public void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { + mask = wire.read(() -> "mask").int32(); + bits = wire.read(() -> "bits").int32(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wire) { + wire.write(() -> "mask").int32(mask); + wire.write(() -> "bits").int32(bits); + } } //TODO optimize? @@ -79,7 +103,7 @@ public interface HashSplitting extends Serializable { private static final int MASK = Integer.MAX_VALUE; private static final int BITS = 31; - private final int segments; + private int segments; public ForNonPowerOf2Segments(int segments) { this.segments = segments; @@ -94,5 +118,15 @@ public interface HashSplitting extends Serializable { public long segmentHash(long hash) { return hash >>> BITS; } + + @Override + public void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { + segments = wire.read(() -> "segments").int32(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wire) { + wire.write(() -> "segments").int32(segments); + } } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 2f5e2f02a..35696bbd2 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -19,6 +19,7 @@ package net.openhft.chronicle.hash.impl; import net.openhft.chronicle.algo.bytes.Access; import net.openhft.chronicle.algo.locks.*; import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.MappedBytesStoreFactory; import net.openhft.chronicle.bytes.NativeBytesStore; import net.openhft.chronicle.core.Maths; @@ -31,6 +32,10 @@ import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.values.Values; +import net.openhft.chronicle.wire.Marshallable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,7 +59,7 @@ import static net.openhft.chronicle.hash.impl.DummyReferenceCounted.DUMMY_REFERE public abstract class VanillaChronicleHash, SC extends HashSegmentContext, ECQ extends ExternalHashQueryContext> - implements ChronicleHash, Serializable { + implements ChronicleHash, Serializable, Marshallable { private static final Logger LOG = LoggerFactory.getLogger(VanillaChronicleHash.class); @@ -65,7 +70,7 @@ public abstract class VanillaChronicleHash kClass; - public final SizeMarshaller keySizeMarshaller; - public final SizedReader originalKeyReader; - public final DataAccess originalKeyDataAccess; + public Class keyClass; + public SizeMarshaller keySizeMarshaller; + public SizedReader keyReader; + public DataAccess keyDataAccess; ///////////////////////////////////////////////// // Checksum entries - public final boolean checksumEntries; + public boolean checksumEntries; ///////////////////////////////////////////////// // Concurrency (number of segments), memory management and dependent fields - public final int actualSegments; - public final HashSplitting hashSplitting; + public int actualSegments; + public HashSplitting hashSplitting; - public final long entriesPerSegment; + public long entriesPerSegment; - public final long chunkSize; - public final int maxChunksPerEntry; - public final long actualChunksPerSegment; + public long chunkSize; + public int maxChunksPerEntry; + public long actualChunksPerSegment; ///////////////////////////////////////////////// // Precomputed offsets and sizes for fast Context init - final int segmentHeaderSize; + int segmentHeaderSize; - public final int segmentHashLookupValueBits; - public final int segmentHashLookupKeyBits; - public final int segmentHashLookupEntrySize; - public final long segmentHashLookupCapacity; - final long segmentHashLookupInnerSize; - public final long segmentHashLookupOuterSize; + public int tierHashLookupValueBits; + public int tierHashLookupKeyBits; + public int tierHashLookupEntrySize; + public long tierHashLookupCapacity; + long tierHashLookupInnerSize; + public long tierHashLookupOuterSize; - public final long segmentFreeListInnerSize; - public final long segmentFreeListOuterSize; + public long tierFreeListInnerSize; + public long tierFreeListOuterSize; - final long segmentEntrySpaceInnerSize; - public final int segmentEntrySpaceInnerOffset; - final long segmentEntrySpaceOuterSize; + long tierEntrySpaceInnerSize; + public int tierEntrySpaceInnerOffset; + long tierEntrySpaceOuterSize; - public final long segmentSize; + public long tierSize; - final long maxExtraTiers; - final long tierBulkSizeInBytes; - final long tierBulkInnerOffsetToTiers; - protected final long tiersInBulk; - protected final int log2TiersInBulk; + long maxExtraTiers; + long tierBulkSizeInBytes; + long tierBulkInnerOffsetToTiers; + protected long tiersInBulk; + protected int log2TiersInBulk; ///////////////////////////////////////////////// // Bytes Store (essentially, the base address) and serialization-dependent offsets @@ -164,10 +169,10 @@ public abstract class VanillaChronicleHash keyBuilder = privateAPI.keyBuilder(); - kClass = keyBuilder.tClass; + keyClass = keyBuilder.tClass; keySizeMarshaller = keyBuilder.sizeMarshaller(); - originalKeyReader = keyBuilder.reader(); - originalKeyDataAccess = keyBuilder.dataAccess(); + keyReader = keyBuilder.reader(); + keyDataAccess = keyBuilder.dataAccess(); actualSegments = privateAPI.actualSegments(); hashSplitting = HashSplitting.Splitting.forSegments(actualSegments); @@ -181,28 +186,28 @@ public abstract class VanillaChronicleHash 4) { + tierHashLookupValueBits = valueBits(actualChunksPerSegment); + tierHashLookupKeyBits = keyBits(entriesPerSegment, tierHashLookupValueBits); + tierHashLookupEntrySize = + entrySize(tierHashLookupKeyBits, tierHashLookupValueBits); + if (!privateAPI.aligned64BitMemoryOperationsAtomic() && tierHashLookupEntrySize > 4) { throw new IllegalStateException("aligned64BitMemoryOperationsAtomic() == false, " + - "but hash lookup slot is " + segmentHashLookupEntrySize); + "but hash lookup slot is " + tierHashLookupEntrySize); } - segmentHashLookupCapacity = CompactOffHeapLinearHashTable.capacityFor(entriesPerSegment); - segmentHashLookupInnerSize = segmentHashLookupCapacity * segmentHashLookupEntrySize; - segmentHashLookupOuterSize = CACHE_LINES.align(segmentHashLookupInnerSize, BYTES); + tierHashLookupCapacity = CompactOffHeapLinearHashTable.capacityFor(entriesPerSegment); + tierHashLookupInnerSize = tierHashLookupCapacity * tierHashLookupEntrySize; + tierHashLookupOuterSize = CACHE_LINES.align(tierHashLookupInnerSize, BYTES); - segmentFreeListInnerSize = LONGS.align( + tierFreeListInnerSize = LONGS.align( BYTES.alignAndConvert(actualChunksPerSegment, BITS), BYTES); - segmentFreeListOuterSize = CACHE_LINES.align(segmentFreeListInnerSize, BYTES); + tierFreeListOuterSize = CACHE_LINES.align(tierFreeListInnerSize, BYTES); - segmentEntrySpaceInnerSize = chunkSize * actualChunksPerSegment; - segmentEntrySpaceInnerOffset = privateAPI.segmentEntrySpaceInnerOffset(); - segmentEntrySpaceOuterSize = CACHE_LINES.align( - segmentEntrySpaceInnerOffset + segmentEntrySpaceInnerSize, BYTES); + tierEntrySpaceInnerSize = chunkSize * actualChunksPerSegment; + tierEntrySpaceInnerOffset = privateAPI.segmentEntrySpaceInnerOffset(); + tierEntrySpaceOuterSize = CACHE_LINES.align( + tierEntrySpaceInnerOffset + tierEntrySpaceInnerSize, BYTES); - segmentSize = segmentSize(); + tierSize = segmentSize(); maxExtraTiers = privateAPI.maxExtraTiers(); tiersInBulk = computeNumberOfTiersInBulk(); @@ -213,6 +218,101 @@ public abstract class VanillaChronicleHash "dataFileVersion").text(); + + keyClass = wireIn.read(() -> "keyClass").typeLiteral(); + keySizeMarshaller = wireIn.read(() -> "keySizeMarshaller").typedMarshallable(); + keyReader = wireIn.read(() -> "keyReader").typedMarshallable(); + keyDataAccess = wireIn.read(() -> "keyDataAccess").typedMarshallable(); + + checksumEntries = wireIn.read(() -> "checksumEntries").bool(); + + actualSegments = wireIn.read(() -> "actualSegments").int32(); + hashSplitting = wireIn.read(() -> "hashSplitting").typedMarshallable(); + + entriesPerSegment = wireIn.read(() -> "entriesPerSegment").int64(); + + chunkSize = wireIn.read(() -> "chunkSize").int64(); + maxChunksPerEntry = wireIn.read(() -> "maxChunksPerEntry").int32(); + actualChunksPerSegment = wireIn.read(() -> "actualChunksPerSegment").int64(); + + segmentHeaderSize = wireIn.read(() -> "segmentHeaderSize").int32(); + + tierHashLookupValueBits = wireIn.read(() -> "tierHashLookupValueBits").int32(); + tierHashLookupKeyBits = wireIn.read(() -> "tierHashLookupKeyBits").int32(); + tierHashLookupEntrySize = wireIn.read(() -> "tierHashLookupEntrySize").int32(); + tierHashLookupCapacity = wireIn.read(() -> "tierHashLookupCapacity").int64(); + tierHashLookupInnerSize = wireIn.read(() -> "tierHashLookupInnerSize").int64(); + tierHashLookupOuterSize = wireIn.read(() -> "tierHashLookupOuterSize").int64(); + + tierFreeListInnerSize = wireIn.read(() -> "tierFreeListInnerSize").int64(); + tierFreeListOuterSize = wireIn.read(() -> "tierFreeListOuterSize").int64(); + + tierEntrySpaceInnerSize = wireIn.read(() -> "tierEntrySpaceInnerSize").int64(); + tierEntrySpaceInnerOffset = wireIn.read(() -> "tierEntrySpaceInnerOffset").int32(); + tierEntrySpaceOuterSize = wireIn.read(() -> "tierEntrySpaceOuterSize").int64(); + + tierSize = wireIn.read(() -> "tierSize").int64(); + + maxExtraTiers = wireIn.read(() -> "maxExtraTiers").int64(); + tierBulkSizeInBytes = wireIn.read(() -> "tierBulkSizeInBytes").int64(); + tierBulkInnerOffsetToTiers = wireIn.read(() -> "tierBulkInnerOffsetToTiers").int64(); + tiersInBulk = wireIn.read(() -> "tiersInBulk").int64(); + log2TiersInBulk = wireIn.read(() -> "log2TiersInBulk").int32(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "dataFileVersion").text(dataFileVersion); + + wireOut.write(() -> "keyClass").typeLiteral(keyClass); + wireOut.write(() -> "keySizeMarshaller").typedMarshallable(keySizeMarshaller); + wireOut.write(() -> "keyReader").typedMarshallable(keyReader); + wireOut.write(() -> "keyDataAccess").typedMarshallable(keyDataAccess); + + wireOut.write(() -> "checksumEntries").bool(checksumEntries); + + wireOut.write(() -> "actualSegments").int32(actualSegments); + wireOut.write(() -> "hashSplitting").typedMarshallable(hashSplitting); + + wireOut.write(() -> "entriesPerSegment").int64(entriesPerSegment); + + wireOut.write(() -> "chunkSize").int64(chunkSize); + wireOut.write(() -> "maxChunksPerEntry").int32(maxChunksPerEntry); + wireOut.write(() -> "actualChunksPerSegment").int64(actualChunksPerSegment); + + wireOut.write(() -> "segmentHeaderSize").int32(segmentHeaderSize); + + wireOut.write(() -> "tierHashLookupValueBits").int32(tierHashLookupValueBits); + wireOut.write(() -> "tierHashLookupKeyBits").int32(tierHashLookupKeyBits); + wireOut.write(() -> "tierHashLookupEntrySize").int32(tierHashLookupEntrySize); + wireOut.write(() -> "tierHashLookupCapacity").int64(tierHashLookupCapacity); + wireOut.write(() -> "tierHashLookupInnerSize").int64(tierHashLookupInnerSize); + wireOut.write(() -> "tierHashLookupOuterSize").int64(tierHashLookupOuterSize); + + wireOut.write(() -> "tierFreeListInnerSize").int64(tierFreeListInnerSize); + wireOut.write(() -> "tierFreeListOuterSize").int64(tierFreeListOuterSize); + + wireOut.write(() -> "tierEntrySpaceInnerSize").int64(tierEntrySpaceInnerSize); + wireOut.write(() -> "tierEntrySpaceInnerOffset").int32(tierEntrySpaceInnerOffset); + wireOut.write(() -> "tierEntrySpaceOuterSize").int64(tierEntrySpaceOuterSize); + + wireOut.write(() -> "tierSize").int64(tierSize); + + wireOut.write(() -> "maxExtraTiers").int64(maxExtraTiers); + wireOut.write(() -> "tierBulkSizeInBytes").int64(tierBulkSizeInBytes); + wireOut.write(() -> "tierBulkInnerOffsetToTiers").int64(tierBulkInnerOffsetToTiers); + wireOut.write(() -> "tiersInBulk").int64(tiersInBulk); + wireOut.write(() -> "log2TiersInBulk").int32(log2TiersInBulk); + } + protected VanillaGlobalMutableState createGlobalMutableState() { return Values.newNativeReference(VanillaGlobalMutableState.class); } @@ -222,8 +322,8 @@ public abstract class VanillaChronicleHash(); - if (segmentHashLookupEntrySize == 4) { + if (tierHashLookupEntrySize == 4) { hashLookup = new IntCompactOffHeapLinearHashTable(this); - } else if (segmentHashLookupEntrySize == 8) { + } else if (tierHashLookupEntrySize == 8) { hashLookup = new LongCompactOffHeapLinearHashTable(this); } else { throw new AssertionError("hash lookup slot size could be 4 or 8, " + - segmentHashLookupEntrySize + " observed"); + tierHashLookupEntrySize + " observed"); } } @@ -326,15 +426,14 @@ public abstract class VanillaChronicleHash= tierBulkOffsets.size()) mapTierBulks(bulkIndex); return tierBulkOffsets.get(bulkIndex).offset + tierBulkInnerOffsetToTiers + - (extraTierIndex & (tiersInBulk - 1)) * segmentSize; + (extraTierIndex & (tiersInBulk - 1)) * tierSize; } private TierBulkData tierBulkData(long tierIndexMinusOne) { @@ -655,7 +754,7 @@ public abstract class VanillaChronicleHash h = hh.h(); long segmentBaseAddr = this.segmentBaseAddr; - segmentBS.set(segmentBaseAddr, h.segmentSize); + segmentBS.set(segmentBaseAddr, h.tierSize); segmentBytes.clear(); - long freeListOffset = h.segmentHashLookupOuterSize + TIER_COUNTERS_AREA_SIZE; + long freeListOffset = h.tierHashLookupOuterSize + TIER_COUNTERS_AREA_SIZE; freeList.setOffset(segmentBaseAddr + freeListOffset); - entrySpaceOffset = freeListOffset + h.segmentFreeListOuterSize + - h.segmentEntrySpaceInnerOffset; + entrySpaceOffset = freeListOffset + h.tierFreeListOuterSize + + h.tierEntrySpaceInnerOffset; } @Stage("Segment") diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java index aa76dbf39..1a4f52855 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java @@ -28,5 +28,5 @@ public class KeyBytesInterop { @StageRef VanillaChronicleHashHolder hh; - public final SizedReader keyReader = copyIfNeeded(hh.h().originalKeyReader); + public final SizedReader keyReader = copyIfNeeded(hh.h().keyReader); } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java index 896c3af18..6d0b21e62 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java @@ -43,7 +43,7 @@ public abstract class HashQuery implements HashEntry { @StageRef public HashLookupPos hlp; @StageRef public KeySearch ks; - final DataAccess innerInputKeyDataAccess = hh.h().originalKeyDataAccess.copy(); + final DataAccess innerInputKeyDataAccess = hh.h().keyDataAccess.copy(); /** * This stage exists for hooking {@link #innerInputKeyDataAccess} usage, to trigger {@link diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java index eff258b3f..0e14e80bc 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.ReadBytesMarshallable; +import net.openhft.chronicle.wire.Marshallable; import org.jetbrains.annotations.NotNull; import java.io.Serializable; @@ -28,8 +29,7 @@ import java.io.Serializable; * @param type of objects deserialized * @see BytesWriter */ -@FunctionalInterface -public interface BytesReader extends Serializable { +public interface BytesReader extends Serializable, Marshallable { /** * Reads and returns the object from {@link Bytes#readPosition()} (i. e. the current position) diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java index e7642a9d5..0c488d335 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.WriteBytesMarshallable; +import net.openhft.chronicle.wire.Marshallable; import org.jetbrains.annotations.NotNull; import java.io.Serializable; @@ -28,8 +29,7 @@ import java.io.Serializable; * @param the type of objects serialized * @see BytesReader */ -@FunctionalInterface -public interface BytesWriter extends Serializable { +public interface BytesWriter extends Serializable, Marshallable { /** * Serializes the given object to the given {@code out}. diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java index c6a7dbf81..80f6f855f 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java @@ -17,11 +17,12 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.wire.Marshallable; import org.jetbrains.annotations.NotNull; import java.io.Serializable; -public interface DataAccess extends StatefulCopyable>, Serializable { +public interface DataAccess extends StatefulCopyable>, Serializable, Marshallable { Data getData(@NotNull T instance); diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java index 81afc233c..f13e393a9 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java @@ -17,6 +17,9 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,8 +61,8 @@ public class ListMarshaller implements BytesReader>, BytesWriter>, StatefulCopyable> { // Config fields - private final BytesReader elementReader; - private final BytesWriter elementWriter; + private BytesReader elementReader; + private BytesWriter elementWriter; public ListMarshaller(BytesReader elementReader, BytesWriter elementWriter) { this.elementReader = elementReader; @@ -104,4 +107,16 @@ public class ListMarshaller return this; } } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + elementReader = wireIn.read(() -> "elementReader").typedMarshallable(); + elementWriter = wireIn.read(() -> "elementWriter").typedMarshallable(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "elementReader").typedMarshallable(elementReader); + wireOut.write(() -> "elementWriter").typedMarshallable(elementWriter); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java index 6dc698128..31be76714 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java @@ -17,6 +17,9 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,10 +55,10 @@ public class MapMarshaller StatefulCopyable> { // Config fields - private final BytesReader keyReader; - private final BytesWriter keyWriter; - private final BytesReader valueReader; - private final BytesWriter valueWriter; + private BytesReader keyReader; + private BytesWriter keyWriter; + private BytesReader valueReader; + private BytesWriter valueWriter; // Cache fields private transient Deque orderedKeys; @@ -120,4 +123,21 @@ public class MapMarshaller return new MapMarshaller<>(copyIfNeeded(keyReader), copyIfNeeded(keyWriter), copyIfNeeded(valueReader), copyIfNeeded(valueWriter)); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + keyReader = wireIn.read(() -> "keyReader").typedMarshallable(); + keyWriter = wireIn.read(() -> "keyWriter").typedMarshallable(); + valueReader = wireIn.read(() -> "valueReader").typedMarshallable(); + valueWriter = wireIn.read(() -> "valueWriter").typedMarshallable(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "keyReader").typedMarshallable(keyReader); + wireOut.write(() -> "keyWriter").typedMarshallable(keyWriter); + wireOut.write(() -> "valueReader").typedMarshallable(valueReader); + wireOut.write(() -> "valueWriter").typedMarshallable(valueWriter); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java index b452b7a20..1dd6fa265 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java @@ -17,6 +17,9 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,8 +62,8 @@ public class SetMarshaller implements BytesReader>, BytesWriter>, StatefulCopyable> { // Config fields - private final BytesReader elementReader; - private final BytesWriter elementWriter; + private BytesReader elementReader; + private BytesWriter elementWriter; /** Cache field */ private transient Deque orderedElements; @@ -110,4 +113,17 @@ public class SetMarshaller public SetMarshaller copy() { return new SetMarshaller<>(copyIfNeeded(elementReader), copyIfNeeded(elementWriter)); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + elementReader = wireIn.read(() -> "elementReader").typedMarshallable(); + elementWriter = wireIn.read(() -> "elementWriter").typedMarshallable(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "elementReader").typedMarshallable(elementReader); + wireOut.write(() -> "elementWriter").typedMarshallable(elementWriter); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java index 97a42f382..d486c03d7 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java @@ -19,6 +19,7 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.serialization.impl.ConstantSizeMarshaller; import net.openhft.chronicle.hash.serialization.impl.StopBitSizeMarshaller; +import net.openhft.chronicle.wire.Marshallable; import java.io.Serializable; @@ -36,7 +37,7 @@ import java.io.Serializable; * value (it's constant size). If the marshaller is fed with the size it is not able store, it could * throw an {@code IllegalArgumentException}. */ -public interface SizeMarshaller extends Serializable { +public interface SizeMarshaller extends Serializable, Marshallable { static SizeMarshaller stopBit() { return StopBitSizeMarshaller.INSTANCE; diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java index 763b6938d..991facc89 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.ChronicleHash; +import net.openhft.chronicle.wire.Marshallable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +32,8 @@ import java.io.Serializable; *

Implementation example:


  * class LongPair { long first, second; }
  * 
- * enum LongPairArrayReader implements{@code SizedReader} {
+ * enum LongPairArrayReader
+ *         implements{@code SizedReader, EnumMarshallable} {
  *     INSTANCE;
  *
  *    {@literal @}Override
@@ -60,13 +62,17 @@ import java.io.Serializable;
  *         }
  *         return res;
  *     }
+ *
+ *    {@literal @}Override
+ *     public LongPairArrayReader readResolve() {
+ *         return INSTANCE;
+ *     }
  * }
* * @param the type of the object deserialized * @see SizedWriter */ -@FunctionalInterface -public interface SizedReader extends Serializable { +public interface SizedReader extends Serializable, Marshallable { /** * Reads and returns the object from {@link Bytes#readPosition()} (i. e. the current position) diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java index ece461192..a25edd86b 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.hash.serialization; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.ChronicleHash; +import net.openhft.chronicle.wire.Marshallable; import org.jetbrains.annotations.NotNull; import java.io.Serializable; @@ -31,7 +32,8 @@ import java.io.Serializable; *

Implementation example:


  * class LongPair { long first, second; }
  *
- * enum LongPairArrayWriter implements{@code SizedWriter} {
+ * enum LongPairArrayWriter
+ *         implements{@code SizedWriter, EnumMarshallable} {
  *     INSTANCE;
  *
  *    {@literal @}Override
@@ -47,12 +49,17 @@ import java.io.Serializable;
  *             out.writeLong(pair.second);
  *         }
  *     }
+ *
+ *    {@literal @}Override
+ *     public LongPairArrayWriter readResolve() {
+ *         return INSTANCE;
+ *     }
  * }
* * @param the type of the object marshalled * @see SizedReader */ -public interface SizedWriter extends Serializable { +public interface SizedWriter extends Serializable, Marshallable { /** * Returns the length (in bytes) of the serialized form of the given object. Serialization form diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java index 1fb1afcef..f87ec3441 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; public enum BooleanMarshaller implements SizedReader, BytesReader, - SizedWriter, BytesWriter { + SizedWriter, BytesWriter, EnumMarshallable { INSTANCE; @Override @@ -55,4 +55,9 @@ public enum BooleanMarshaller public void write(Bytes out, @NotNull Boolean toWrite) { out.writeByte((byte) (toWrite ? 'Y' : 0)); } + + @Override + public BooleanMarshaller readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java index fe7f0096a..0e8f113da 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java @@ -17,10 +17,13 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.HeapBytesStore; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -93,4 +96,15 @@ public class ByteArrayDataAccess extends AbstractData implements DataAcc public DataAccess copy() { return new ByteArrayDataAccess(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java index 538cfb3d7..9a71cfd98 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java @@ -21,7 +21,8 @@ import net.openhft.chronicle.hash.serialization.SizedReader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public enum ByteArraySizedReader implements SizedReader { +public enum ByteArraySizedReader + implements SizedReader, EnumMarshallable { INSTANCE; @NotNull @@ -40,4 +41,9 @@ public enum ByteArraySizedReader implements SizedReader { size + " given. Memory corruption?"); return (int) size; } + + @Override + public ByteArraySizedReader readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java index f9bb72485..0f532e07e 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java @@ -20,6 +20,8 @@ import net.openhft.chronicle.bytes.*; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import sun.nio.ch.DirectBuffer; @@ -116,4 +118,15 @@ public class ByteBufferDataAccess extends AbstractData public DataAccess copy() { return new ByteBufferDataAccess(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java index 7bd8f6a69..fcf329fef 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java @@ -23,7 +23,8 @@ import org.jetbrains.annotations.Nullable; import java.nio.ByteBuffer; -public enum ByteBufferSizedReader implements SizedReader { +public enum ByteBufferSizedReader + implements SizedReader, EnumMarshallable { INSTANCE; @NotNull @@ -43,4 +44,9 @@ public enum ByteBufferSizedReader implements SizedReader { using.flip(); return using; } + + @Override + public ByteBufferSizedReader readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java index 4d5ab0a94..24a39323b 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java @@ -17,9 +17,12 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -89,6 +92,6 @@ public class ByteableDataAccess extends InstanceCreatingMars @Override public DataAccess copy() { - return new ByteableDataAccess<>(tClass); + return new ByteableDataAccess<>(tClass()); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java index 29510cc8a..316d34bb4 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java @@ -17,9 +17,12 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,7 +30,7 @@ public class BytesAsSizedReader implements SizedReader, StatefulCopyable> { /** Config field */ - private final BytesReader reader; + private BytesReader reader; public BytesAsSizedReader(BytesReader reader) { this.reader = reader; @@ -47,4 +50,14 @@ public class BytesAsSizedReader return this; } } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + reader = wireIn.read(() -> "reader").typedMarshallable(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "reader").typedMarshallable(reader); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java index 5512d2191..723e387ae 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java @@ -18,9 +18,11 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,6 +43,12 @@ public class BytesMarshallableDataAccess initTransients(); } + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + super.readMarshallable(wireIn); + initTransients(); + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); initTransients(); @@ -109,6 +117,6 @@ public class BytesMarshallableDataAccess @Override public DataAccess copy() { - return new BytesMarshallableDataAccess<>(tClass); + return new BytesMarshallableDataAccess<>(tClass()); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java index c1019eca6..1891ec2c2 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java @@ -30,11 +30,17 @@ import org.jetbrains.annotations.NotNull; * * @see CharSequenceBytesWriter */ -public enum CharSequenceBytesWriter implements BytesWriter { +public enum CharSequenceBytesWriter + implements BytesWriter, EnumMarshallable { INSTANCE; @Override public void write(Bytes out, @NotNull CharSequence toWrite) { out.writeUtf8(toWrite); } + + @Override + public CharSequenceBytesWriter readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java index 9727e2c03..f772e3ea7 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java @@ -18,8 +18,11 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -70,4 +73,15 @@ public class CharSequenceSizedReader public CharSequenceSizedReader copy() { return new CharSequenceSizedReader(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java index 578d3c1c8..d72ca9742 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java @@ -21,7 +21,8 @@ import net.openhft.chronicle.bytes.BytesUtil; import net.openhft.chronicle.hash.serialization.SizedWriter; import org.jetbrains.annotations.NotNull; -public enum CharSequenceSizedWriter implements SizedWriter { +public enum CharSequenceSizedWriter + implements SizedWriter, EnumMarshallable { INSTANCE; @Override @@ -33,4 +34,9 @@ public enum CharSequenceSizedWriter implements SizedWriter { public void write(@NotNull Bytes out, long size, @NotNull CharSequence toWrite) { BytesUtil.appendUtf8(out, toWrite); } + + @Override + public CharSequenceSizedWriter readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java index 544e0eea6..b03991b3a 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java @@ -17,12 +17,16 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.SizeMarshaller; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; public final class ConstantSizeMarshaller implements SizeMarshaller { /** Config field */ - private final long constantSize; + private long constantSize; public ConstantSizeMarshaller(long constantSize) { this.constantSize = constantSize; @@ -62,4 +66,14 @@ public final class ConstantSizeMarshaller implements SizeMarshaller { public long readSize(Bytes in) { return constantSize; } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + constantSize = wireIn.read(() -> "constantSize").int64(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "constantSize").int64(constantSize); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java index 0b2ae48ed..b1896b38b 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; public enum DoubleMarshaller implements SizedReader, BytesReader, - SizedWriter, BytesWriter { + SizedWriter, BytesWriter, EnumMarshallable { INSTANCE; @NotNull @@ -55,4 +55,9 @@ public enum DoubleMarshaller public void write(Bytes out, @NotNull Double toWrite) { out.writeDouble(toWrite); } + + @Override + public DoubleMarshaller readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java index 438b7a5b5..f1dd3d277 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java @@ -17,11 +17,14 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.BytesWriter; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,8 +37,8 @@ public class ExternalBytesMarshallableDataAccess extends InstanceCreatingMars implements DataAccess, Data { // Config fields - private final SizedReader reader; - private final BytesWriter writer; + private SizedReader reader; + private BytesWriter writer; /** Cache field */ private transient Bytes bytes; @@ -120,6 +123,21 @@ public class ExternalBytesMarshallableDataAccess extends InstanceCreatingMars @Override public DataAccess copy() { return new ExternalBytesMarshallableDataAccess<>( - tClass, copyIfNeeded(reader), copyIfNeeded(writer)); + tClass(), copyIfNeeded(reader), copyIfNeeded(writer)); + } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + super.readMarshallable(wireIn); + reader = wireIn.read(() -> "reader").typedMarshallable(); + writer = wireIn.read(() -> "writer").typedMarshallable(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + super.writeMarshallable(wireOut); + wireOut.write(() -> "reader").typedMarshallable(reader); + wireOut.write(() -> "writer").typedMarshallable(writer); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java index d7a928694..d09017c49 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java @@ -16,8 +16,11 @@ package net.openhft.chronicle.hash.serialization.impl; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,12 +32,16 @@ import java.io.ObjectOutputStream; public class ExternalizableDataAccess extends SerializableDataAccess { /** Config field */ - protected final Class tClass; + private Class tClass; public ExternalizableDataAccess(Class tClass) { this.tClass = tClass; } + protected Class tClass() { + return tClass; + } + protected T createInstance() { try { return tClass.newInstance(); @@ -74,4 +81,15 @@ public class ExternalizableDataAccess extends Serializ public DataAccess copy() { return new ExternalizableDataAccess<>(tClass); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + tClass = wireIn.read(() -> "tClass").typeLiteral(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "tClass").typeLiteral(tClass); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java index 9ab79e0ed..979dcd6a6 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java @@ -16,13 +16,17 @@ package net.openhft.chronicle.hash.serialization.impl; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.map.ChronicleMapBuilder; +import net.openhft.chronicle.wire.Marshallable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; import java.io.Serializable; -import java.lang.reflect.Constructor; /** * Holds new instance creation logic, common for many {@link DataAccess} and {@link SizedReader} @@ -30,12 +34,9 @@ import java.lang.reflect.Constructor; * * @param the type of objects deserialized */ -public abstract class InstanceCreatingMarshaller implements Serializable { +public abstract class InstanceCreatingMarshaller implements Serializable, Marshallable { - /** - * The class of objects deserialized. - */ - protected final Class tClass; + private Class tClass; /** * Constructor for use in subclasses. @@ -46,6 +47,13 @@ public abstract class InstanceCreatingMarshaller implements Serializable { this.tClass = tClass; } + /** + * Returns the class of objects deserialized. + */ + protected Class tClass() { + return tClass; + } + /** * Creates a new {@code T} instance by calling {@link Class#newInstance()}. If you need * different logic, i. e. calling a constructor with parameter, override this method in a @@ -70,4 +78,15 @@ public abstract class InstanceCreatingMarshaller implements Serializable { "Chronicle Map via keyMarshaller[s]() or valueMarshaller[s]() methods", e); } } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + //noinspection unchecked + tClass = wireIn.read(() -> "tClass").typeLiteral(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "tClass").typeLiteral(tClass); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java index c9d015f96..5f16081a8 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; public enum IntegerMarshaller implements SizedReader, BytesReader, - SizedWriter, BytesWriter { + SizedWriter, BytesWriter, EnumMarshallable { INSTANCE; @NotNull @@ -55,4 +55,9 @@ public enum IntegerMarshaller public void write(Bytes out, @NotNull Integer toWrite) { out.writeInt(toWrite); } + + @Override + public IntegerMarshaller readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java index b331142d5..d38af87b7 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; public enum LongMarshaller implements SizedReader, BytesReader, - SizedWriter, BytesWriter { + SizedWriter, BytesWriter, EnumMarshallable { INSTANCE; @Override @@ -55,4 +55,9 @@ public enum LongMarshaller public void write(Bytes out, @NotNull Long toWrite) { out.writeLong(toWrite); } + + @Override + public LongMarshaller readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java index 0553c6b05..3ca2c0436 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java @@ -37,6 +37,6 @@ public class NotReusingSizedMarshallableDataAccess extends SizedMarshallableD @Override public DataAccess copy() { return new NotReusingSizedMarshallableDataAccess<>( - tClass, copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter)); + tClass(), copyIfNeeded(sizedReader()), copyIfNeeded(sizedWriter())); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java index 4796be64e..8ba64d27d 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java @@ -17,10 +17,13 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,7 +49,7 @@ public class SerializableDataAccess extends AbstractData initTransients(); } - private void initTransients() { + void initTransients() { bytes = Bytes.allocateElasticDirect(1); out = bytes.outputStream(); in = bytes.inputStream(); @@ -107,4 +110,15 @@ public class SerializableDataAccess extends AbstractData public DataAccess copy() { return new SerializableDataAccess<>(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java index f07f0c2cd..9741899c2 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java @@ -17,8 +17,11 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,4 +47,14 @@ public class SerializableReader throw new RuntimeException(e); } } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java index 18a604b41..f123b5682 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java @@ -17,11 +17,14 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,8 +37,8 @@ public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller, Data { // Config fields - final SizedReader sizedReader; - final SizedWriter sizedWriter; + private SizedReader sizedReader; + private SizedWriter sizedWriter; /** Cache field */ private transient Bytes bytes; @@ -51,6 +54,14 @@ public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller sizedReader() { + return sizedReader; + } + + SizedWriter sizedWriter() { + return sizedWriter; + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); initTransients(); @@ -120,6 +131,21 @@ public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller copy() { return new SizedMarshallableDataAccess<>( - tClass, copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter)); + tClass(), copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter)); + } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + super.readMarshallable(wireIn); + sizedReader = wireIn.read(() -> "sizedReader").typedMarshallable(); + sizedWriter = wireIn.read(() -> "sizedWriter").typedMarshallable(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + super.writeMarshallable(wireOut); + wireOut.write(() -> "sizedReader").typedMarshallable(sizedReader); + wireOut.write(() -> "sizedWriter").typedMarshallable(sizedWriter); } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java index d76dadfcc..97292cf3f 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java @@ -23,7 +23,8 @@ import net.openhft.chronicle.hash.serialization.SizeMarshaller; import static java.lang.Math.max; import static java.lang.Math.min; -public enum StopBitSizeMarshaller implements SizeMarshaller { +public enum StopBitSizeMarshaller + implements SizeMarshaller, EnumMarshallable { INSTANCE; private static final long MIN_ENCODABLE_SIZE = Long.MIN_VALUE; @@ -75,4 +76,9 @@ public enum StopBitSizeMarshaller implements SizeMarshaller { public long readSize(Bytes in) { return BytesUtil.readStopBit(in); } + + @Override + public StopBitSizeMarshaller readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java index d2c5756a3..61bb401fd 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java @@ -22,7 +22,8 @@ import net.openhft.chronicle.hash.serialization.SizedReader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public enum StringBuilderSizedReader implements SizedReader { +public enum StringBuilderSizedReader + implements SizedReader, EnumMarshallable { INSTANCE; @NotNull @@ -40,4 +41,9 @@ public enum StringBuilderSizedReader implements SizedReader { BytesUtil.parseUtf8(in, using, csLen); return using; } + + @Override + public StringBuilderSizedReader readResolve() { + return INSTANCE; + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java index ec9608993..fb7f148e2 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java @@ -17,10 +17,13 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.ListMarshaller; import net.openhft.chronicle.hash.serialization.SetMarshaller; import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,4 +69,15 @@ public class StringBytesReader public StringBytesReader copy() { return new StringBytesReader(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java index c6f3e0c65..7a7ec6379 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java @@ -18,8 +18,11 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,4 +61,15 @@ public class StringSizedReader implements SizedReader, StatefulCopyable< public StringSizedReader copy() { return new StringSizedReader(); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + // no fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no fields to write + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java index 79e269099..6fa03d318 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java @@ -17,12 +17,15 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.values.Copyable; import net.openhft.chronicle.values.Values; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,12 +36,12 @@ import static net.openhft.chronicle.bytes.NativeBytesStore.nativeStoreWithFixedC public class ValueDataAccess extends AbstractData implements DataAccess { - /** The interface of values serialized. */ - protected final Class valueType; + /** Config field */ + private Class valueType; // Cache fields - protected transient Class nativeClass; - protected transient Class heapClass; + private transient Class nativeClass; + private transient Class heapClass; private transient Byteable nativeInstance; private transient Copyable nativeInstanceAsCopyable; @@ -50,6 +53,19 @@ public class ValueDataAccess extends AbstractData implements DataAccess initTransients(); } + /** Returns the interface of values serialized. */ + protected Class valueType() { + return valueType; + } + + protected Class nativeClass() { + return nativeClass; + } + + protected Class heapClass() { + return heapClass; + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); initTransients(); @@ -120,4 +136,15 @@ public class ValueDataAccess extends AbstractData implements DataAccess public DataAccess copy() { return new ValueDataAccess<>(valueType); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + valueType = wireIn.read(() -> "valueType").typeLiteral(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "valueType").typeLiteral(valueType); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java index 9cf36e3ee..fe4ff38fd 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java @@ -18,11 +18,14 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Byteable; import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.StatefulCopyable; import net.openhft.chronicle.values.Copyable; import net.openhft.chronicle.values.Values; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,12 +35,12 @@ import java.io.ObjectInputStream; public class ValueReader implements SizedReader, BytesReader, StatefulCopyable> { - /** The interface of values deserialized. */ - protected final Class valueType; + /** Config field */ + private Class valueType; // Cache fields - protected transient Class heapClass; - protected transient Class nativeClass; + private transient Class nativeClass; + private transient Class heapClass; private transient Byteable nativeReference; public ValueReader(Class valueType) { @@ -45,14 +48,27 @@ public class ValueReader initTransients(); } + /** Returns the interface of values deserialized. */ + protected Class valueType() { + return valueType; + } + + protected Class nativeClass() { + return nativeClass; + } + + protected Class heapClass() { + return heapClass; + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); initTransients(); } private void initTransients() { - heapClass = Values.heapClassFor(valueType); nativeClass = Values.nativeClassFor(valueType); + heapClass = Values.heapClassFor(valueType); nativeReference = (Byteable) Values.newNativeReference(valueType); } @@ -92,4 +108,15 @@ public class ValueReader public ValueReader copy() { return new ValueReader<>(valueType); } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) throws IORuntimeException { + valueType = wireIn.read(() -> "valueType").typeLiteral(); + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + wireOut.write(() -> "valueType").typeLiteral(valueType); + } } diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index 70f78cfea..e80b06249 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -16,7 +16,9 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.algo.MemoryUnit; import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.core.OS; import net.openhft.chronicle.hash.ChronicleHashBuilder; @@ -31,11 +33,15 @@ import net.openhft.chronicle.map.replication.MapRemoteOperations; import net.openhft.chronicle.set.ChronicleSetBuilder; import net.openhft.chronicle.threads.NamedThreadFactory; import net.openhft.chronicle.values.ValueModel; +import net.openhft.chronicle.wire.TextWire; +import net.openhft.chronicle.wire.Wire; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -120,6 +126,8 @@ public final class ChronicleMapBuilder implements return !isNaN(config); } + private static int MAX_BOOTSTRAPPING_HEADER_SIZE = (int) MemoryUnit.KILOBYTES.toBytes(16); + // not final because of cloning private ChronicleMapBuilderPrivateAPI privateAPI = new ChronicleMapBuilderPrivateAPI<>(this); @@ -515,7 +523,7 @@ public final class ChronicleMapBuilder implements if (worstAlignmentComputationRequiresValueSize(alignment)) { long constantSizeBeforeAlignment = round(size); if (constantlySizedValues()) { - // see segmentEntrySpaceInnerOffset() + // see tierEntrySpaceInnerOffset() long totalDataSize = constantSizeBeforeAlignment + constantValueSize(); worstAlignment = (int) (alignAddr(totalDataSize, alignment) - totalDataSize); } else { @@ -1364,28 +1372,29 @@ public final class ChronicleMapBuilder implements for (int i = 0; i < 10; i++) { long fileLength = file.length(); if (fileLength > 0) { - try (FileInputStream fis = new FileInputStream(file); - ObjectInputStream ois = new ObjectInputStream(fis)) { - Object m; - try { - m = ois.readObject(); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); - } - @SuppressWarnings("unchecked") - VanillaChronicleMap map = (VanillaChronicleMap) m; + try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { + FileChannel fileChannel = raf.getChannel(); + ByteBuffer headerBuffer = ByteBuffer.allocate(MAX_BOOTSTRAPPING_HEADER_SIZE); + fileChannel.read(headerBuffer); + headerBuffer.flip(); + Bytes headerBytes = Bytes.wrapForRead(headerBuffer); + headerBytes.readLimit(headerBuffer.limit()); + Wire wire = new TextWire(headerBytes); + VanillaChronicleMap map = wire.getValueIn().typedMarshallable(); map.initTransientsFromBuilder(this); initTransientsFromReplication(map, singleHashReplication, channel); - map.initBeforeMapping(fis.getChannel()); + + fileChannel.position(headerBytes.readPosition()); + map.initBeforeMapping(fileChannel); long expectedFileLength = map.expectedFileSize(); if (expectedFileLength != fileLength) { throw new IOException("The file " + file + " the map is serialized from " + "has unexpected length " + fileLength + ", probably corrupted. " + "Expected length is " + expectedFileLength); } - map.createMappedStoreAndSegments(file); + map.createMappedStoreAndSegments(file, raf); establishReplication(map, singleHashReplication, channel); - fis.getChannel().force(true); + fileChannel.force(true); // TODO according to Self Boostrapping Data spec, should write "init complete" // byte *after* the above force instruction, see HCOLL-396 return map; @@ -1406,12 +1415,17 @@ public final class ChronicleMapBuilder implements VanillaChronicleMap map = newMap(singleHashReplication, channel); - try (FileOutputStream fos = new FileOutputStream(file); - ObjectOutputStream oos = new ObjectOutputStream(fos)) { - oos.writeObject(map); - oos.flush(); - map.initBeforeMapping(fos.getChannel()); - map.createMappedStoreAndSegments(file); + try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { + FileChannel fileChannel = raf.getChannel(); + ByteBuffer headerBuffer = ByteBuffer.allocate(MAX_BOOTSTRAPPING_HEADER_SIZE); + Bytes headerBytes = Bytes.wrapForWrite(headerBuffer); + Wire wire = new TextWire(headerBytes); + wire.getValueOut().typedMarshallable(map); + + headerBuffer.limit((int) headerBytes.writePosition()); + fileChannel.write(headerBuffer); + map.initBeforeMapping(fileChannel); + map.createMappedStoreAndSegments(file, raf); } return establishReplication(map, singleHashReplication, channel); diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index 71716d7e0..b0de43174 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -759,7 +759,7 @@ public class ReplicatedChronicleMap extends VanillaChronicleMap ///////////////////////////////////////////////// // Value Data model - final Class vClass; - public final SizeMarshaller valueSizeMarshaller; - public final SizedReader originalValueReader; - public final DataAccess originalValueDataAccess; + Class valueClass; + public SizeMarshaller valueSizeMarshaller; + public SizedReader valueReader; + public DataAccess valueDataAccess; - public final boolean constantlySizedEntry; + public boolean constantlySizedEntry; ///////////////////////////////////////////////// // Memory management and dependent fields - public final int alignment; - public final int worstAlignment; - public final boolean couldNotDetermineAlignmentBeforeAllocation; + public int alignment; + public int worstAlignment; + + public transient boolean couldNotDetermineAlignmentBeforeAllocation; ///////////////////////////////////////////////// // Behavior @@ -78,23 +82,51 @@ public class VanillaChronicleMap public VanillaChronicleMap(ChronicleMapBuilder builder) throws IOException { super(builder); SerializationBuilder valueBuilder = builder.valueBuilder; - vClass = valueBuilder.tClass; + valueClass = valueBuilder.tClass; valueSizeMarshaller = valueBuilder.sizeMarshaller(); - originalValueReader = valueBuilder.reader(); - originalValueDataAccess = valueBuilder.dataAccess(); + valueReader = valueBuilder.reader(); + valueDataAccess = valueBuilder.dataAccess(); constantlySizedEntry = builder.constantlySizedEntries(); // Concurrency (number of segments), memory management and dependent fields alignment = builder.valueAlignment(); worstAlignment = builder.worstAlignment(); - couldNotDetermineAlignmentBeforeAllocation = - greatestCommonDivisor((int) chunkSize, alignment) != alignment; initTransientsFromBuilder(builder); initTransients(); } - + + @Override + protected void readMarshallableFields(@NotNull WireIn wireIn) throws IORuntimeException { + super.readMarshallableFields(wireIn); + + valueClass = wireIn.read(() -> "valueClass").typeLiteral(); + valueSizeMarshaller = wireIn.read(() -> "valueSizeMarshaller").typedMarshallable(); + valueReader = wireIn.read(() -> "valueReader").typedMarshallable(); + valueDataAccess = wireIn.read(() -> "valueDataAccess").typedMarshallable(); + + constantlySizedEntry = wireIn.read(() -> "constantlySizedEntry").bool(); + + alignment = wireIn.read(() -> "alignment").int32(); + worstAlignment = wireIn.read(() -> "worstAlignment").int32(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + super.writeMarshallable(wireOut); + + wireOut.write(() -> "valueClass").typeLiteral(valueClass); + wireOut.write(() -> "valueSizeMarshaller").typedMarshallable(valueSizeMarshaller); + wireOut.write(() -> "valueReader").typedMarshallable(valueReader); + wireOut.write(() -> "valueDataAccess").typedMarshallable(valueDataAccess); + + wireOut.write(() -> "constantlySizedEntry").bool(constantlySizedEntry); + + wireOut.write(() -> "alignment").int32(alignment); + wireOut.write(() -> "worstAlignment").int32(worstAlignment); + } + void initTransientsFromBuilder(ChronicleMapBuilder builder) { putReturnsNull = builder.putReturnsNull(); removeReturnsNull = builder.removeReturnsNull(); @@ -111,6 +143,8 @@ public class VanillaChronicleMap } private void initOwnTransients() { + couldNotDetermineAlignmentBeforeAllocation = + greatestCommonDivisor((int) chunkSize, alignment) != alignment; cxt = new ThreadLocal<>(); } @@ -120,8 +154,8 @@ public class VanillaChronicleMap } public final V checkValue(Object value) { - if (!vClass.isInstance(value)) { - throw new ClassCastException("Value must be a " + vClass.getName() + + if (!valueClass.isInstance(value)) { + throw new ClassCastException("Value must be a " + valueClass.getName() + " but was a " + value.getClass()); } return (V) value; @@ -129,12 +163,12 @@ public class VanillaChronicleMap @Override public Class keyClass() { - return kClass; + return keyClass; } @Override public Class valueClass() { - return vClass; + return valueClass; } static T newInstance(Class aClass, boolean isKey) { diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java index f6eea0a65..6d11a133d 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java @@ -28,7 +28,7 @@ public class WrappedValueInstanceDataHolder { @StageRef VanillaChronicleMapHolder mh; - private final DataAccess wrappedValueDataAccess = mh.m().originalValueDataAccess.copy(); + private final DataAccess wrappedValueDataAccess = mh.m().valueDataAccess.copy(); private WrappedValueInstanceDataHolder next; diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java index 352ef6eca..1a082b6db 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java @@ -28,6 +28,6 @@ public class ValueBytesInterop { @StageRef VanillaChronicleMapHolder mh; - public final SizedReader valueReader = copyIfNeeded(mh.m().originalValueReader); + public final SizedReader valueReader = copyIfNeeded(mh.m().valueReader); } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java index df3f3fef0..33e2eab70 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java @@ -55,7 +55,7 @@ public abstract class MapQuery extends HashQuery @StageRef public MapAbsentEntryHolder absent; - final DataAccess innerInputValueDataAccess = mh.m().originalValueDataAccess.copy(); + final DataAccess innerInputValueDataAccess = mh.m().valueDataAccess.copy(); /** Same as {@link #inputKeyDataAccessInitialized} */ @Stage("InputValueDataAccess") private boolean inputValueDataAccessInitialized = false; diff --git a/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java b/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java index 0abed5364..4ef3f9294 100644 --- a/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java +++ b/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java @@ -20,10 +20,12 @@ import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -enum DummyValueMarshaller implements DataAccess, SizedReader { +enum DummyValueMarshaller implements DataAccess, SizedReader, + EnumMarshallable { INSTANCE; @Override @@ -46,5 +48,10 @@ enum DummyValueMarshaller implements DataAccess, SizedReader, BytesWriter { +public enum DeflatorStringMarshaller implements BytesReader, + BytesWriter, EnumMarshallable { INSTANCE; private static final StringFactory STRING_FACTORY = getStringFactory(); @@ -54,7 +56,7 @@ public enum DeflatorStringMarshaller } @Override - public void write(Bytes out, CharSequence s) { + public void write(Bytes out, @NotNull CharSequence s) { if (s == null) { out.writeStopBit(NULL_LENGTH); return; @@ -114,6 +116,11 @@ public enum DeflatorStringMarshaller } } + @Override + public DeflatorStringMarshaller readResolve() { + return INSTANCE; + } + private static abstract class StringFactory { abstract String fromChars(char[] chars) throws Exception; } diff --git a/src/test/java/net/openhft/chronicle/map/Issue43Test.java b/src/test/java/net/openhft/chronicle/map/Issue43Test.java index 18f1d5e83..d102259a8 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue43Test.java +++ b/src/test/java/net/openhft/chronicle/map/Issue43Test.java @@ -19,7 +19,9 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import net.openhft.chronicle.set.Builder; +import org.jetbrains.annotations.NotNull; import org.junit.Test; public class Issue43Test { @@ -34,7 +36,7 @@ public class Issue43Test { ChronicleMap map = ChronicleMapBuilder .of(Long.class, ValueWrapper.class) .entries(512) - .valueMarshaller(new ArrayMarshaller()) + .valueMarshaller(ArrayMarshaller.INSTANCE) .constantValueSizeBySample(new ValueWrapper(new double[128])) .createPersistedTo(Builder.getPersistenceFile()); System.out.println("Created the monkey map ValueWrapper 128"); @@ -52,11 +54,12 @@ public class Issue43Test { } } - private static class ArrayMarshaller - implements BytesReader, BytesWriter { + private enum ArrayMarshaller implements BytesReader, BytesWriter, + EnumMarshallable { + INSTANCE; @Override - public void write(Bytes bytes, ValueWrapper vw) { + public void write(Bytes bytes, @NotNull ValueWrapper vw) { bytes.writeInt(vw.values.length); for (int i = 0; i < vw.values.length; i ++) { @@ -68,5 +71,10 @@ public class Issue43Test { public ValueWrapper read(Bytes in, ValueWrapper using) { throw new UnsupportedOperationException("Not supported yet."); } + + @Override + public ArrayMarshaller readResolve() { + return INSTANCE; + } } } diff --git a/src/test/java/net/openhft/chronicle/map/Issue58.java b/src/test/java/net/openhft/chronicle/map/Issue58.java index 60c6dcc33..d9d1883e3 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue58.java +++ b/src/test/java/net/openhft/chronicle/map/Issue58.java @@ -19,6 +19,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -128,7 +129,8 @@ public class Issue58 { } - enum UuidMarshaller implements BytesReader, BytesWriter { + enum UuidMarshaller + implements BytesReader, BytesWriter, EnumMarshallable { INSTANCE; @Override @@ -137,9 +139,15 @@ public class Issue58 { bytes.writeLong(uuid.getLeastSignificantBits()); } + @NotNull @Override public UUID read(Bytes bytes, @Nullable UUID using) { return new UUID(bytes.readLong(), bytes.readLong()); } + + @Override + public UuidMarshaller readResolve() { + return INSTANCE; + } } } diff --git a/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java b/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java index b55e66300..e4a0de87d 100644 --- a/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java +++ b/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java @@ -20,9 +20,9 @@ import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesMarshallable; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.chronicle.map.Issue43Test; import org.jetbrains.annotations.NotNull; import org.junit.Test; @@ -36,7 +36,7 @@ public class ComplexSerializationTest { List list_; } - enum AMarshaller implements BytesReader, BytesWriter { + enum AMarshaller implements BytesReader, BytesWriter, EnumMarshallable { INSTANCE; @Override @@ -79,6 +79,11 @@ public class ComplexSerializationTest { } return using; } + + @Override + public AMarshaller readResolve() { + return INSTANCE; + } } static class B implements BytesMarshallable { diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java index 5981b8748..aa9db288a 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java @@ -18,11 +18,12 @@ package net.openhft.chronicle.map.fromdocs; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -enum LongPairArrayReader implements SizedReader { +enum LongPairArrayReader implements SizedReader, EnumMarshallable { INSTANCE; @NotNull @@ -50,4 +51,9 @@ enum LongPairArrayReader implements SizedReader { } return res; } + + @Override + public LongPairArrayReader readResolve() { + return INSTANCE; + } } diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java index 591e6539a..7685c9e3e 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java @@ -18,9 +18,10 @@ package net.openhft.chronicle.map.fromdocs; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.hash.serialization.impl.EnumMarshallable; import org.jetbrains.annotations.NotNull; -enum LongPairArrayWriter implements SizedWriter { +enum LongPairArrayWriter implements SizedWriter, EnumMarshallable { INSTANCE; @Override @@ -35,4 +36,9 @@ enum LongPairArrayWriter implements SizedWriter { out.writeLong(pair.second); } } + + @Override + public LongPairArrayWriter readResolve() { + return INSTANCE; + } }