HCOLL-164 added a void marshaller and Map replication test using VOID value

This commit is contained in:
Rob Austin
2014-10-10 13:10:29 +01:00
parent 11fb016e97
commit 3630cfe555
12 changed files with 272 additions and 49 deletions
@@ -34,18 +34,16 @@ import static net.openhft.chronicle.map.Objects.builderEquals;
public class ChronicleSetBuilder<E> implements Cloneable {
private ChronicleMapBuilder<E, Boolean> chronicleMapBuilder;
private ChronicleMapBuilder<E, Void> chronicleMapBuilder;
ChronicleSetBuilder(Class<E> keyClass) {
chronicleMapBuilder = new ChronicleMapBuilder<E, Boolean>(keyClass, Boolean.class);
chronicleMapBuilder.constantValueSizeBySample(Boolean.TRUE);
chronicleMapBuilder = new ChronicleMapBuilder<E, Void>(keyClass, Void.class);
}
public static <K> ChronicleSetBuilder<K> of(Class<K> keyClass) {
return new ChronicleSetBuilder<K>(keyClass);
}
@Override
public ChronicleSetBuilder<E> clone() {
try {
@@ -58,7 +56,6 @@ public class ChronicleSetBuilder<E> implements Cloneable {
}
}
public ChronicleSetBuilder<E> actualSegments(int actualSegments) {
chronicleMapBuilder.actualSegments(actualSegments);
return this;
@@ -83,7 +80,6 @@ public class ChronicleSetBuilder<E> implements Cloneable {
return chronicleMapBuilder.minSegments();
}
public ChronicleSetBuilder<E> actualElementsPerSegment(int actualEntriesPerSegment) {
chronicleMapBuilder.actualEntriesPerSegment(actualEntriesPerSegment);
return this;
@@ -338,22 +334,22 @@ public class ChronicleSetBuilder<E> implements Cloneable {
public ChronicleSet<E> create(File file) throws IOException {
final ChronicleMap<E, Boolean> map = chronicleMapBuilder.create(file);
final ChronicleMap<E, Void> map = chronicleMapBuilder.create(file);
return new SetFromMap<E>(map);
}
public ChronicleSet<E> create() throws IOException {
final ChronicleMap<E, Boolean> map = chronicleMapBuilder.create();
final ChronicleMap<E, Void> map = chronicleMapBuilder.create();
return new SetFromMap<E>(map);
}
private static class SetFromMap<E> extends AbstractSet<E>
implements ChronicleSet<E>, Serializable {
private final ChronicleMap<E, Boolean> m; // The backing map
private final ChronicleMap<E, Void> m; // The backing map
private transient Set<E> s; // Its keySet
SetFromMap(ChronicleMap<E, Boolean> map) {
SetFromMap(ChronicleMap<E, Void> map) {
if (!map.isEmpty())
throw new IllegalArgumentException("Map is non-empty");
m = map;
@@ -381,7 +377,7 @@ public class ChronicleSetBuilder<E> implements Cloneable {
}
public boolean add(E e) {
return m.put(e, Boolean.TRUE) == null;
return m.put(e, (Void)null) == null;
}
public Iterator<E> iterator() {
@@ -381,7 +381,6 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
long valueSize;
if (!isDeleted) {
valueSize = valueSizeMarshaller.readSize(entry);
assert valueSize > 0;
} else {
valueSize = 0;
}
@@ -21,7 +21,10 @@ import net.openhft.chronicle.map.serialization.impl.*;
import net.openhft.chronicle.map.threadlocal.Provider;
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.*;
import net.openhft.lang.io.serialization.BytesMarshallable;
import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.io.serialization.ObjectFactory;
import net.openhft.lang.io.serialization.ObjectSerializer;
import net.openhft.lang.io.serialization.impl.*;
import net.openhft.lang.model.Byteable;
import org.jetbrains.annotations.NotNull;
@@ -40,7 +43,7 @@ final class SerializationBuilder<E> implements Cloneable {
private static boolean concreteClass(Class c) {
return !c.isInterface() && !Modifier.isAbstract(c.getModifiers());
}
private static boolean marshallerUseFactory(Class c) {
return Byteable.class.isAssignableFrom(c) ||
BytesMarshallable.class.isAssignableFrom(c) ||
@@ -52,6 +55,7 @@ final class SerializationBuilder<E> implements Cloneable {
}
enum Role {KEY, VALUE}
private enum CopyingInterop {FROM_MARSHALLER, FROM_WRITER}
private final Serializable bufferIdentity;
@@ -84,6 +88,8 @@ final class SerializationBuilder<E> implements Cloneable {
} else if (eClass == CharSequence.class || eClass == String.class) {
reader((BytesReader<E>) CharSequenceReader.of(), factory);
writer((BytesWriter<E>) CharSequenceWriter.instance());
} else if (eClass == Void.class) {
agileMarshaller((AgileBytesMarshaller<E>) VoidMarshaller.INSTANCE, factory);
} else if (eClass == Long.class) {
agileMarshaller((AgileBytesMarshaller<E>) LongMarshaller.INSTANCE, factory);
} else if (eClass == byte[].class) {
@@ -17,15 +17,16 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.map.serialization.*;
import net.openhft.chronicle.map.threadlocal.Provider;
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
import net.openhft.lang.Maths;
import net.openhft.lang.collection.DirectBitSet;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.*;
import net.openhft.lang.io.serialization.*;
import net.openhft.lang.io.serialization.JDKObjectSerializer;
import net.openhft.lang.io.serialization.ObjectFactory;
import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory;
import net.openhft.lang.model.Byteable;
import net.openhft.chronicle.map.threadlocal.Provider;
import net.openhft.chronicle.map.threadlocal.ThreadLocalCopies;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -312,7 +313,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
void checkValue(Object value) {
if (!vClass.isInstance(value)) {
if (vClass != Void.class && !vClass.isInstance(value)) {
throw new ClassCastException("Value must be a " + vClass.getName() +
" but was a " + value.getClass());
}
@@ -692,7 +693,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
* true}, {@code usingValue} or a newly created instance of value class, if {@code usingValue ==
* null}, is put into this Segment for the key.</li></ol>
*
* @param hash2 a hash code related to the {@code keyBytes}
* @param hash2 a hash code related to the {@code keyBytes}
* @return the value which is finally associated with the given key in this Segment after execution of
* this method, or {@code null}.
*/
@@ -827,13 +828,12 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
/**
* Puts entry. If {@code value} implements {@link Byteable} interface and
* {@code usingValue} is {@code true}, the value is backed with the bytes of this entry.
* Puts entry. If {@code value} implements {@link Byteable} interface and {@code usingValue} is {@code
* true}, the value is backed with the bytes of this entry.
*
* @param value the value to put
* @param usingValue {@code true} if the value should be backed with the bytes of the entry,
* if it implements {@link Byteable} interface, {@code false} if it
* should put itself
* @param usingValue {@code true} if the value should be backed with the bytes of the entry, if it
* implements {@link Byteable} interface, {@code false} if it should put itself
* @return offset of the written entry in the Segment bytes
*/
private long putEntry(ThreadLocalCopies copies, MKI metaKeyInterop, KI keyInterop, K key,
@@ -958,7 +958,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
* Removes a key (or key-value pair) from the Segment. <p/> The entry will only be removed if {@code
* expectedValue} equals to {@code null} or the value previously corresponding to the specified key.
*
* @param hash2 a hash code related to the {@code keyBytes}
* @param hash2 a hash code related to the {@code keyBytes}
* @return the value of the entry that was removed if the entry corresponding to the {@code keyBytes}
* exists and {@link #removeReturnsNull} is {@code false}, {@code null} otherwise
*/
@@ -1095,12 +1095,12 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
* Replaces value in existing entry. May cause entry relocation, because there may be not enough space
* for new value in location already allocated for this entry.
*
* @param pos index of the first block occupied by the entry
* @param offset relative offset of the entry in Segment bytes (before, i. e. including
* metaData)
* @param entry relative pointer in Segment bytes
* @param valueSizePos relative position of value size in entry
* @param entryEndAddr absolute address of the entry end
* @param pos index of the first block occupied by the entry
* @param offset relative offset of the entry in Segment bytes (before, i. e. including
* metaData)
* @param entry relative pointer in Segment bytes
* @param valueSizePos relative position of value size in entry
* @param entryEndAddr absolute address of the entry end
* @return relative offset of the entry in Segment bytes after putting value (that may cause entry
* relocation)
*/
@@ -0,0 +1,71 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* 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.serialization.impl;
import net.openhft.chronicle.map.serialization.AgileBytesMarshaller;
import net.openhft.lang.io.Bytes;
public enum VoidMarshaller implements AgileBytesMarshaller<Void> {
INSTANCE;
@Override
public long size(Void e) {
return 0L;
}
@Override
public int sizeEncodingSize(long size) {
return 0;
}
@Override
public void writeSize(Bytes bytes, long size) {
// do nothing
}
@Override
public boolean startsWith(Bytes bytes, Void e) {
return false;
}
@Override
public long hash(Void e) {
return 0;
}
@Override
public void write(Bytes bytes, Void e) {
// do nothing;
}
@Override
public long readSize(Bytes bytes) {
return 0L;
}
@Override
public Void read(Bytes bytes, long size) {
// Void nothing;
return null;
}
@Override
public Void read(Bytes bytes, long size, Void aVoid) {
return null;
}
}