Simplified support for Marshallable and BytesMarshallable, https://github.com/OpenHFT/Chronicle-Map/issues/196

This commit is contained in:
Peter Lawrey
2019-09-20 14:19:45 +01:00
parent edb7df2336
commit a7ebbf6a75
6 changed files with 130 additions and 120 deletions
@@ -50,6 +50,7 @@ public interface SizedWriter<T> 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);
/**
@@ -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<V extends BytesMarshallable>
extends InstanceCreatingMarshaller<V>
implements SizedReader<V>, SizedWriter<V> {
public BytesMarshallableReaderWriter(Class<V> vClass) {
super(vClass);
}
private static final ThreadLocal<VanillaBytes> 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);
}
}
@@ -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<V extends Marshallable>
extends InstanceCreatingMarshaller<V>
implements SizedReader<V>, SizedWriter<V> {
public MarshallableReaderWriter(Class<V> 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);
}
}
@@ -2557,6 +2557,29 @@ public class CHMUseCasesTest {
}
}
}
@Test
public void testBytesMarshallable3() throws IOException {
BytesMarshallableReaderWriter<IData.Data> bmwr = new BytesMarshallableReaderWriter<>(IData.Data.class);
ChronicleMapBuilder<IData.Data, IData.Data> builder = ChronicleMapBuilder
.of(IData.Data.class, IData.Data.class)
.keyMarshaller(bmwr)
.valueMarshaller(bmwr)
.actualChunkSize(64)
.entries(1000);
try (ChronicleMap<IData.Data, IData.Data> 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}
@@ -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<Integer, MyDto> 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<Integer, MyDto> 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<MyDto>, SizedWriter<MyDto> {
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);
}
}
}
@@ -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);
}
}