diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DirectBytesBuffer.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DirectBytesBuffer.java index cfc930514..cb5aa4f73 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DirectBytesBuffer.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DirectBytesBuffer.java @@ -90,25 +90,23 @@ class DirectBytesBuffer } void init(M writer, E e, boolean mutable, long maxSize, boolean checked) { - if (mutable || writer != this.writer || e != cur) { - this.writer = writer; - cur = e; - while (true) { - try { - Bytes buffer = this.buffer.obtain(maxSize, true); - if (checked) - buffer = new BoundsCheckingDirectBytes(buffer, null); - writer.write(buffer, e); - buffer.flip(); - long size = this.size = buffer.remaining(); - this.buffer.buffer.position(0L); - this.buffer.buffer.limit(size); - hash = 0L; - return; - } catch (Exception ex) { - checkMaxSizeStillReasonable(maxSize, ex); - maxSize *= 2L; - } + this.writer = writer; + cur = e; + while (true) { + try { + Bytes buffer = this.buffer.obtain(maxSize, true); + if (checked) + buffer = new BoundsCheckingDirectBytes(buffer, null); + writer.write(buffer, e); + buffer.flip(); + long size = this.size = buffer.remaining(); + this.buffer.buffer.position(0L); + this.buffer.buffer.limit(size); + hash = 0L; + return; + } catch (Exception ex) { + checkMaxSizeStillReasonable(maxSize, ex); + maxSize *= 2L; } } } @@ -123,19 +121,17 @@ class DirectBytesBuffer } void init(W writer, E e, boolean mutable, boolean checked) { - if (mutable || writer != this.writer || e != cur) { - this.writer = writer; - cur = e; - long size = writer.size(e); - Bytes buffer = this.buffer.obtain(size, true); - if (checked) - buffer = new BoundsCheckingDirectBytes(buffer, null); - writer.write(buffer, e); - buffer.flip(); - this.size = size; - assert size == buffer.remaining(); - hash = 0L; - } + this.writer = writer; + cur = e; + long size = writer.size(e); + Bytes buffer = this.buffer.obtain(size, true); + if (checked) + buffer = new BoundsCheckingDirectBytes(buffer, null); + writer.write(buffer, e); + buffer.flip(); + this.size = size; + assert size == buffer.remaining(); + hash = 0L; } } diff --git a/src/test/java/net/openhft/chronicle/map/Issue58.java b/src/test/java/net/openhft/chronicle/map/Issue58.java new file mode 100644 index 000000000..80999d0b1 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/Issue58.java @@ -0,0 +1,148 @@ +/* + * 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.lang.io.Bytes; +import net.openhft.lang.io.serialization.BytesMarshaller; +import net.openhft.lang.model.constraints.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static java.util.stream.Collectors.toMap; + +public class Issue58 { + File mapFile = new File("string-to-uuid.dat"); + File reverseMapFile = new File("uuid-to-string.dat"); + + public static void main(String... args) { + Map map = new HashMap<>(); + map.put("AA", UUID.randomUUID()); + map.put("AB", UUID.randomUUID()); + map.put("BA", UUID.randomUUID()); + map.put("BB", UUID.randomUUID()); + try { + Issue58 test = new Issue58(); + test.writeMapAndReverseMap(map); + test.test1(map); + test.test2(map); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void writeMapAndReverseMap(Map data) throws IOException { + if (mapFile.exists()) + mapFile.delete(); + if (reverseMapFile.exists()) + reverseMapFile.delete(); + + try ( + ChronicleMap map = ChronicleMap.of(String.class, UUID.class) + .averageKeySize(2) + .valueMarshaller(UuidMarshaller.INSTANCE) + .constantValueSizeBySample(UUID.randomUUID()) + .entries(data.size()) + .createPersistedTo(mapFile); + ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) + .keyMarshaller(UuidMarshaller.INSTANCE) + .averageValueSize(2) + .constantKeySizeBySample(UUID.randomUUID()) + .entries(data.size()) + .createPersistedTo(reverseMapFile); + ) { + + map.putAll(data); + Map reverse = data.keySet().stream() + .collect(toMap(k -> data.get(k), k -> k)); + reverseMap.putAll(reverse); + } + + } + + public void test1(Map data) throws IOException { + try ( + ChronicleMap map = ChronicleMap.of(String.class, UUID.class) + .averageKeySize(2) + .valueMarshaller(UuidMarshaller.INSTANCE) + .constantValueSizeBySample(UUID.randomUUID()) + .entries(data.size()) + .createPersistedTo(mapFile); + ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) + .keyMarshaller(UuidMarshaller.INSTANCE) + .constantKeySizeBySample(UUID.randomUUID()) + .averageValueSize(2) + .entries(data.size()) + .createPersistedTo(reverseMapFile) + ) { + System.out.println("first test passes:"); + UUID uuid = data.get("BB"); + System.out.println("BB" + " == " + reverseMap.get(uuid)); + System.out.println(uuid + " == " + map.get("BB")); + } + } + + public void test2(Map data) throws IOException { + try ( + ChronicleMap map = ChronicleMap.of(String.class, UUID.class) + .averageKeySize(2) + .valueMarshaller(UuidMarshaller.INSTANCE) + .constantValueSizeBySample(UUID.randomUUID()) + .entries(data.size()) + .createPersistedTo(mapFile); + ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) + .keyMarshaller(UuidMarshaller.INSTANCE) + .constantKeySizeBySample(UUID.randomUUID()) + .averageValueSize(2) + .entries(data.size()) + .createPersistedTo(reverseMapFile) + ) { + System.out.println("second identical test also passes:"); + UUID uuid = data.get("BB"); + System.out.println("BB" + " == " + reverseMap.get(uuid)); + System.out.println(uuid + " == " + map.get("BB")); //returns null + System.out.println("despite all data being present:"); + map.entrySet().forEach(e -> System.out.println(e.getKey() + "->" + e.getValue())); + reverseMap.forEach((k, v) -> System.out.println(k + " -> " + v)); + } + + } + + + enum UuidMarshaller implements BytesMarshaller { + INSTANCE; + + @Override + public void write(Bytes bytes, UUID uuid) { + bytes.writeLong(uuid.getMostSignificantBits()); + bytes.writeLong(uuid.getLeastSignificantBits()); + } + + @Override + public UUID read(Bytes bytes) { + return new UUID(bytes.readLong(), bytes.readLong()); + } + + @Override + public UUID read(Bytes bytes, @Nullable UUID uuid) { + return read(bytes); + } + } +}