From a7ebbf6a7537925cfb8fe5b2763a55ab04d0a487 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 20 Sep 2019 14:19:45 +0100 Subject: [PATCH] Simplified support for Marshallable and BytesMarshallable, https://github.com/OpenHFT/Chronicle-Map/issues/196 --- .../hash/serialization/SizedWriter.java | 1 + .../impl/BytesMarshallableReaderWriter.java | 55 ++++++++++++ .../impl/MarshallableReaderWriter.java | 46 ++++++++++ .../chronicle/map/CHMUseCasesTest.java | 23 +++++ ...qmentTest.java => ForEachSegmentTest.java} | 41 ++------- .../openhft/chronicle/map/SampleValues.java | 84 ------------------- 6 files changed, 130 insertions(+), 120 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java rename src/test/java/net/openhft/chronicle/map/{ForEachSeqmentTest.java => ForEachSegmentTest.java} (75%) delete mode 100755 src/test/java/net/openhft/chronicle/map/SampleValues.java 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 7e26f1bfb..e55ed471f 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java @@ -50,6 +50,7 @@ public interface SizedWriter extends Marshallable { * @param toWrite the object which serialized form length should be returned * @return the length (in bytes) of the serialized form of the given object */ + // TODO lift the requirement to give a size first which can involve double serialization. long size(@NotNull T toWrite); /** diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java new file mode 100644 index 000000000..e45b38fe9 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReaderWriter.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016-2019 Chronicle Software Ltd + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.VanillaBytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.wire.BinaryWire; +import net.openhft.chronicle.wire.Marshallable; +import net.openhft.chronicle.wire.Wire; +import net.openhft.chronicle.wire.Wires; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BytesMarshallableReaderWriter + extends InstanceCreatingMarshaller + implements SizedReader, SizedWriter { + public BytesMarshallableReaderWriter(Class vClass) { + super(vClass); + } + + private static final ThreadLocal VANILLA_BYTES_TL = ThreadLocal.withInitial(() -> new VanillaBytes<>(BytesStore.empty())); + + @NotNull + @Override + public V read(Bytes in, long size, @Nullable V using) { + if (using == null) + using = createInstance(); + + VanillaBytes vanillaBytes = VANILLA_BYTES_TL.get(); + vanillaBytes.bytesStore(in, in.readPosition(), size); + using.readMarshallable(vanillaBytes); + return using; + } + + @Override + public long size(@NotNull V toWrite) { + Bytes bytes = Wires.acquireBytes(); + toWrite.writeMarshallable(bytes); + return bytes.readRemaining(); + } + + @Override + public void write(Bytes out, long size, @NotNull V toWrite) { + VanillaBytes vanillaBytes = VANILLA_BYTES_TL.get(); + vanillaBytes.bytesStore(out, out.readPosition(), out.readRemaining()); + vanillaBytes.writeLimit(out.writePosition() + size); + toWrite.writeMarshallable(vanillaBytes); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java new file mode 100644 index 000000000..77f063228 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/MarshallableReaderWriter.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016-2019 Chronicle Software Ltd + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.wire.BinaryWire; +import net.openhft.chronicle.wire.Marshallable; +import net.openhft.chronicle.wire.Wire; +import net.openhft.chronicle.wire.Wires; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MarshallableReaderWriter + extends InstanceCreatingMarshaller + implements SizedReader, SizedWriter { + public MarshallableReaderWriter(Class vClass) { + super(vClass); + } + + @NotNull + @Override + public V read(Bytes in, long size, @Nullable V using) { + if (using == null) + using = createInstance(); + + using.readMarshallable(Wires.binaryWireForRead(in, in.readPosition(), size)); + return using; + } + + @Override + public long size(@NotNull V toWrite) { + Wire wire = Wires.acquireBinaryWire(); + toWrite.writeMarshallable(wire); + return wire.bytes().readRemaining(); + } + + @Override + public void write(Bytes out, long size, @NotNull V toWrite) { + BinaryWire wire = Wires.binaryWireForWrite(out, out.writePosition(), size); + toWrite.writeMarshallable(wire); + } +} diff --git a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java index 26b456356..d440dc394 100644 --- a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java @@ -2557,6 +2557,29 @@ public class CHMUseCasesTest { } } } + @Test + public void testBytesMarshallable3() throws IOException { + BytesMarshallableReaderWriter bmwr = new BytesMarshallableReaderWriter<>(IData.Data.class); + ChronicleMapBuilder builder = ChronicleMapBuilder + .of(IData.Data.class, IData.Data.class) + .keyMarshaller(bmwr) + .valueMarshaller(bmwr) + .actualChunkSize(64) + .entries(1000); + try (ChronicleMap map = newInstance(builder)) { + for (int i = 0; i < 100; i++) { + IData.Data key = new IData.Data(); + IData.Data value = new IData.Data(); + key.setText("key-" + i); + key.setNumber(i); + value.setNumber(i); + value.setText("value-" + i); + map.put(key, value); + // check the map is still valid. + map.entrySet().toString(); + } + } + } enum TypeOfMap {SIMPLE, SIMPLE_PERSISTED} diff --git a/src/test/java/net/openhft/chronicle/map/ForEachSeqmentTest.java b/src/test/java/net/openhft/chronicle/map/ForEachSegmentTest.java similarity index 75% rename from src/test/java/net/openhft/chronicle/map/ForEachSeqmentTest.java rename to src/test/java/net/openhft/chronicle/map/ForEachSegmentTest.java index 4a334f3d7..f4603d090 100644 --- a/src/test/java/net/openhft/chronicle/map/ForEachSeqmentTest.java +++ b/src/test/java/net/openhft/chronicle/map/ForEachSegmentTest.java @@ -6,6 +6,8 @@ import net.openhft.chronicle.core.OS; import net.openhft.chronicle.core.pool.ClassAliasPool; import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.hash.serialization.impl.BytesMarshallableReader; +import net.openhft.chronicle.hash.serialization.impl.BytesMarshallableReaderWriter; import net.openhft.chronicle.wire.AbstractBytesMarshallable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,7 +16,7 @@ import org.junit.Test; import java.io.File; import java.io.IOException; -public class ForEachSeqmentTest { +public class ForEachSegmentTest { static { ClassAliasPool.CLASS_ALIASES.addAlias(MyDto.class); } @@ -25,7 +27,7 @@ public class ForEachSeqmentTest { .entries(256) .averageValueSize(128) .actualSegments(1) - .valueMarshaller(new MyDtoMarshaller()); + .valueMarshaller(new BytesMarshallableReaderWriter<>(MyDto.class)); File tmp = new File(OS.TMP, "stressTest-" + System.nanoTime()); tmp.deleteOnExit(); try (ChronicleMap map = builder.createOrRecoverPersistedTo(tmp)) { @@ -46,7 +48,7 @@ public class ForEachSeqmentTest { .entries(256) .averageValueSize(128) .actualSegments(1) - .valueMarshaller(new MyDtoMarshaller()); + .valueMarshaller(new BytesMarshallableReaderWriter<>(MyDto.class)); File tmp = new File(OS.TMP, "stressTest-" + System.nanoTime()); Thread t = null; try (ChronicleMap map = builder.createOrRecoverPersistedTo(tmp)) { @@ -88,38 +90,5 @@ public class ForEachSeqmentTest { static class MyDto extends AbstractBytesMarshallable { String s1; String s2; - - public MyDto() { - } - - public MyDto(final String s1, final String s2) { - this.s1 = s1; - this.s2 = s2; - } } - - static class MyDtoMarshaller implements SizedReader, SizedWriter { - transient Bytes bytes = Bytes.elasticByteBuffer(); - - @NotNull - @Override - public MyDto read(final Bytes in, final long size, @Nullable final MyDto using) { - MyDto u = using == null ? new MyDto() : using; - u.readMarshallable(in); - return u; - } - - @Override - public long size(@NotNull final MyDto toWrite) { - bytes.clear(); - write(bytes, 0, toWrite); - return bytes.readRemaining(); - } - - @Override - public void write(final Bytes out, final long size, @NotNull final MyDto toWrite) { - toWrite.writeMarshallable(out); - } - } - } diff --git a/src/test/java/net/openhft/chronicle/map/SampleValues.java b/src/test/java/net/openhft/chronicle/map/SampleValues.java deleted file mode 100755 index 055a89bf5..000000000 --- a/src/test/java/net/openhft/chronicle/map/SampleValues.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2018 Chronicle Map Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map;/* - * Copyright 2013 peter.lawrey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import net.openhft.chronicle.bytes.BytesIn; -import net.openhft.chronicle.bytes.BytesMarshallable; -import net.openhft.chronicle.bytes.BytesOut; -import org.jetbrains.annotations.NotNull; - -enum BuySell { - Buy, Sell -} - -/** - * Sample entry of 10 fields with two String, Enum, int, double, long - */ -public class SampleValues implements BytesMarshallable { - String aa = "aaaaaaaaaa"; - String bb = "bbbbbbbbbb"; - BuySell cc = BuySell.Buy; - BuySell dd = BuySell.Sell; - int ee = 123456; - int ff = 654321; - double gg = 1.23456789; - double hh = 9.87654321; - long ii = 987654321; - long jj = 123456789; - - @Override - public void readMarshallable(@NotNull BytesIn in) throws IllegalStateException { - aa = in.readUtf8(); - bb = in.readUtf8(); - cc = (BuySell) in.readEnum(BuySell.class); - dd = (BuySell) in.readEnum(BuySell.class); - ee = in.readInt(); - ff = in.readInt(); - gg = in.readDouble(); - hh = in.readDouble(); - ii = in.readLong(); - jj = in.readLong(); - } - - @Override - public void writeMarshallable(@NotNull BytesOut out) { - out.writeUtf8(aa); - out.writeUtf8(bb); - out.writeEnum(cc); - out.writeEnum(dd); - out.writeInt(ee); - out.writeInt(ff); - out.writeDouble(gg); - out.writeDouble(hh); - out.writeLong(ii); - out.writeLong(jj); - } -}