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 7ca8fc7c4..8443f3046 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 @@ -16,9 +16,7 @@ package net.openhft.chronicle.hash.serialization.impl; -import net.openhft.chronicle.bytes.Bytes; -import net.openhft.chronicle.bytes.BytesMarshallable; -import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.bytes.*; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.wire.WireIn; @@ -28,8 +26,10 @@ import org.jetbrains.annotations.Nullable; public class BytesMarshallableDataAccess extends InstanceCreatingMarshaller implements DataAccess, Data { - /** Cache field */ + // Cache fields + private transient boolean bytesInit; private transient Bytes bytes; + private transient VanillaBytes targetBytes; /** State field */ private transient T instance; @@ -47,13 +47,23 @@ public class BytesMarshallableDataAccess private void initTransients() { bytes = Bytes.allocateElasticDirect(1); + targetBytes = VanillaBytes.vanillaBytes(); } @Override public RandomDataInput bytes() { + initBytes(); return bytes.bytesStore(); } + private void initBytes() { + if (!bytesInit) { + bytes.clear(); + instance.writeMarshallable(bytes); + bytesInit = true; + } + } + @Override public long offset() { return 0; @@ -61,9 +71,23 @@ public class BytesMarshallableDataAccess @Override public long size() { + initBytes(); return bytes.readRemaining(); } + @Override + public void writeTo(RandomDataOutput target, long targetOffset) { + if (bytesInit) { + target.write(targetOffset, bytes(), offset(), size()); + } else { + targetBytes.bytesStore((BytesStore) target, targetOffset, + target.capacity() - targetOffset); + targetBytes.writePosition(targetOffset); + instance.writeMarshallable(targetBytes); + targetBytes.bytesStore(NoBytesStore.NO_BYTES_STORE, 0, 0); + } + } + @Override public T get() { return instance; @@ -73,6 +97,7 @@ public class BytesMarshallableDataAccess public T getUsing(@Nullable T using) { if (using == null) using = createInstance(); + initBytes(); using.readMarshallable(bytes); bytes.readPosition(0); return using; @@ -96,8 +121,7 @@ public class BytesMarshallableDataAccess @Override public Data getData(@NotNull T instance) { this.instance = instance; - bytes.clear(); - instance.writeMarshallable(bytes); + bytesInit = false; return this; } diff --git a/src/test/java/net/openhft/chronicle/map/BytesMarshallableValueTest.java b/src/test/java/net/openhft/chronicle/map/BytesMarshallableValueTest.java new file mode 100644 index 000000000..48da84689 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/BytesMarshallableValueTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.map; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; +import org.junit.Assert; +import org.junit.Test; + +public class BytesMarshallableValueTest { + + @Test + public void bytesMarshallableValueTest() { + try (ChronicleMap map = ChronicleMap + .of(Integer.class, Value.class) + .averageValue(new Value(1, "foo")) + .entries(10) + .create()) { + map.put(1, new Value(1, "bar")); + Assert.assertEquals("bar", map.replace(1, new Value(2, "baz")).foo); + map.remove(1); + } + } + + public static class Value implements BytesMarshallable { + + int x; + String foo; + + public Value(int x, String foo) { + this.x = x; + this.foo = foo; + } + + public Value() { + } + + @Override + public void readMarshallable(Bytes bytes) { + x = bytes.readInt(); + foo = bytes.readUtf8(); + } + + @Override + public void writeMarshallable(Bytes bytes) { + bytes.writeInt(x); + bytes.writeUtf8(foo); + } + } +}