Make key/value size discovery more defensive, inspired by #43

This commit is contained in:
leventov
2015-09-21 19:08:45 +03:00
parent 97ae2fc2a2
commit d9c771bedc
11 changed files with 37 additions and 23 deletions
@@ -34,6 +34,6 @@ public class KeyBytesInterop<K, KI, MKI extends MetaBytesInterop<K, ? super KI>>
public MKI keyMetaInterop(K key) {
return hh.h().metaKeyInteropProvider.get(
ch.copies, hh.h().originalMetaKeyInterop, keyInterop, key);
ch.copies, hh.h().originalMetaKeyInterop, keyInterop, key, false);
}
}
@@ -92,10 +92,10 @@ public abstract class CopyingMetaBytesInterop<E, W> extends BasicCopyingMetaByte
@Override
public CopyingMetaBytesInterop<E, M> get(
ThreadLocalCopies copies,
CopyingMetaBytesInterop<E, M> originalMetaWriter, M writer, E e) {
CopyingMetaBytesInterop<E, M> originalMetaWriter, M writer, E e, boolean checked) {
DirectBytesBuffer.ForBytesMarshaller forBytesMarshaller =
provider.get(copies, originalMetaWriter.buffer()).forBytesMarshaller;
forBytesMarshaller.init(writer, e, mutable, maxSize);
forBytesMarshaller.init(writer, e, mutable, maxSize, checked);
return forBytesMarshaller;
}
}
@@ -115,11 +115,12 @@ public abstract class CopyingMetaBytesInterop<E, W> extends BasicCopyingMetaByte
}
@Override
public CopyingMetaBytesInterop<E, W> get(ThreadLocalCopies copies,
CopyingMetaBytesInterop<E, W> originalMetaWriter, W writer, E e) {
public CopyingMetaBytesInterop<E, W> get(
ThreadLocalCopies copies, CopyingMetaBytesInterop<E, W> originalMetaWriter,
W writer, E e, boolean checked) {
DirectBytesBuffer.ForBytesWriter forBytesWriter =
provider.get(copies, originalMetaWriter.buffer()).forBytesWriter;
forBytesWriter.init(writer, e, mutable);
forBytesWriter.init(writer, e, mutable, checked);
return forBytesWriter;
}
}
@@ -17,6 +17,7 @@
package net.openhft.chronicle.hash.serialization.internal;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.lang.io.BoundsCheckingDirectBytes;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.model.*;
import net.openhft.lang.threadlocal.ThreadLocalCopies;
@@ -40,8 +41,10 @@ public abstract class DataValueMetaBytesInterop<E>
return e.equals(other);
}
void init(BytesWriter<E> writer, E e, long size) {
void init(BytesWriter<E> writer, E e, long size, boolean checked) {
Bytes buffer = this.buffer.obtain(size, true);
if (checked)
buffer = new BoundsCheckingDirectBytes(buffer, null);
writer.write(buffer, e);
buffer.flip();
assert buffer.remaining() == size;
@@ -87,13 +90,13 @@ public abstract class DataValueMetaBytesInterop<E>
@Override
public MetaBytesInterop<E, BytesWriter<E>> get(
ThreadLocalCopies copies, MetaBytesInterop<E, BytesWriter<E>> originalMetaWriter,
BytesWriter<E> writer, E e) {
BytesWriter<E> writer, E e, boolean checked) {
if (e instanceof Byteable)
return metaByteableInterop;
DirectBytesBuffer.ForDataValueWriter forDataValueWriter =
provider.get(copies, ((DataValueMetaBytesInterop)originalMetaWriter).buffer)
.forDataValueWriter;
forDataValueWriter.init(writer, e, size);
forDataValueWriter.init(writer, e, size, checked);
return forDataValueWriter;
}
}
@@ -35,8 +35,9 @@ public final class DelegatingMetaBytesInteropProvider<E, I extends BytesInterop<
private DelegatingMetaBytesInteropProvider() {}
@Override
public MetaBytesInterop<E, I> get(ThreadLocalCopies copies,
MetaBytesInterop<E, I> originalMetaWriter, I writer, E e) {
public MetaBytesInterop<E, I> get(
ThreadLocalCopies copies, MetaBytesInterop<E, I> originalMetaWriter, I writer, E e,
boolean checked) {
return originalMetaWriter;
}
@@ -17,9 +17,7 @@
package net.openhft.chronicle.hash.serialization.internal;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.DirectBytes;
import net.openhft.lang.io.DirectStore;
import net.openhft.lang.io.*;
import net.openhft.lang.io.serialization.BytesMarshallableSerializer;
import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.io.serialization.ObjectSerializer;
@@ -91,13 +89,15 @@ class DirectBytesBuffer
super(DirectBytesBuffer.this);
}
void init(M writer, E e, boolean mutable, long maxSize) {
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();
@@ -122,12 +122,14 @@ class DirectBytesBuffer
super(DirectBytesBuffer.this);
}
void init(W writer, E e, boolean mutable) {
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;
@@ -22,7 +22,7 @@ import java.io.Serializable;
public interface MetaProvider<E, W, MW extends MetaBytesWriter<E, ? super W>> extends Serializable {
MW get(ThreadLocalCopies copies, MW originalMetaWriter, W writer, E e);
MW get(ThreadLocalCopies copies, MW originalMetaWriter, W writer, E e, boolean checked);
ThreadLocalCopies getCopies(ThreadLocalCopies copies);
}
@@ -278,7 +278,7 @@ public final class SerializationBuilder<E> implements Cloneable, Serializable {
MetaProvider metaInteropProvider = this.metaInteropProvider;
try {
metaInterop = metaInteropProvider.get(
copies, this.metaInterop, interop, sampleObject);
copies, this.metaInterop, interop, sampleObject, true);
break findSufficientSerializationSize;
} catch (Exception e) {
CopyingMetaBytesInterop.checkMaxSizeStillReasonable(maxSize, e);
@@ -287,7 +287,8 @@ public final class SerializationBuilder<E> implements Cloneable, Serializable {
}
} else {
MetaProvider metaInteropProvider = this.metaInteropProvider;
metaInterop = metaInteropProvider.get(copies, this.metaInterop, interop, sampleObject);
metaInterop = metaInteropProvider.get(
copies, this.metaInterop, interop, sampleObject, true);
}
return metaInterop.size(interop, sampleObject);
}
@@ -1329,7 +1329,7 @@ public final class ChronicleMapBuilder<K, V> implements
MetaProvider metaWriterProvider = valueBuilder.metaInteropProvider();
copies = metaWriterProvider.getCopies(copies);
MetaBytesWriter metaValueWriter = metaWriterProvider.get(copies,
valueBuilder.metaInterop(), valueWriter, defaultValue);
valueBuilder.metaInterop(), valueWriter, defaultValue, true);
return new ConstantValueProvider<>(defaultValue, metaValueWriter, valueWriter);
}
@@ -55,7 +55,8 @@ final class WriterWithSize<T> {
copies = writerProvider.getCopies(copies);
Object writer = writerProvider.get(copies, originalWriter);
copies = metaWriterProvider.getCopies(copies);
MetaBytesWriter metaWriter = metaWriterProvider.get(copies, originalMetaWriter, writer, t);
MetaBytesWriter metaWriter = metaWriterProvider.get(
copies, originalMetaWriter, writer, t, false);
long size = metaWriter.size(writer, t);
if (bufferResizer != null)
out = resizeIfRequired(out, size);
@@ -90,7 +91,8 @@ final class WriterWithSize<T> {
public ThreadLocalCopies writeInLoop(Bytes out, T t, Object writer,
@Nullable ThreadLocalCopies copies) {
copies = metaWriterProvider.getCopies(copies);
MetaBytesWriter metaWriter = metaWriterProvider.get(copies, originalMetaWriter, writer, t);
MetaBytesWriter metaWriter = metaWriterProvider.get(
copies, originalMetaWriter, writer, t, false);
long size = metaWriter.size(writer, t);
if (bufferResizer != null)
out = resizeIfRequired(out, size);
@@ -35,6 +35,6 @@ public class ValueBytesInterop<V, VI, MVI extends MetaBytesInterop<V, ? super VI
public MVI valueMetaInterop(V value) {
return mh.m().metaValueInteropProvider.get(
ch.copies, mh.m().originalMetaValueInterop, valueInterop, value);
ch.copies, mh.m().originalMetaValueInterop, valueInterop, value, false);
}
}