Remove buggy optimization in DirectBytesBuffer #58

This commit is contained in:
leventov
2015-11-17 15:00:01 +03:00
parent fdc3720e29
commit 6b7eb99144
2 changed files with 176 additions and 32 deletions
@@ -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;
}
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
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<String, UUID> 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<String, UUID> data) throws IOException {
if (mapFile.exists())
mapFile.delete();
if (reverseMapFile.exists())
reverseMapFile.delete();
try (
ChronicleMap<String, UUID> map = ChronicleMap.of(String.class, UUID.class)
.averageKeySize(2)
.valueMarshaller(UuidMarshaller.INSTANCE)
.constantValueSizeBySample(UUID.randomUUID())
.entries(data.size())
.createPersistedTo(mapFile);
ChronicleMap<UUID, String> reverseMap = ChronicleMap.of(UUID.class, String.class)
.keyMarshaller(UuidMarshaller.INSTANCE)
.averageValueSize(2)
.constantKeySizeBySample(UUID.randomUUID())
.entries(data.size())
.createPersistedTo(reverseMapFile);
) {
map.putAll(data);
Map<UUID, String> reverse = data.keySet().stream()
.collect(toMap(k -> data.get(k), k -> k));
reverseMap.putAll(reverse);
}
}
public void test1(Map<String, UUID> data) throws IOException {
try (
ChronicleMap<String, UUID> map = ChronicleMap.of(String.class, UUID.class)
.averageKeySize(2)
.valueMarshaller(UuidMarshaller.INSTANCE)
.constantValueSizeBySample(UUID.randomUUID())
.entries(data.size())
.createPersistedTo(mapFile);
ChronicleMap<UUID, String> 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<String, UUID> data) throws IOException {
try (
ChronicleMap<String, UUID> map = ChronicleMap.of(String.class, UUID.class)
.averageKeySize(2)
.valueMarshaller(UuidMarshaller.INSTANCE)
.constantValueSizeBySample(UUID.randomUUID())
.entries(data.size())
.createPersistedTo(mapFile);
ChronicleMap<UUID, String> 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<UUID> {
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);
}
}
}