diff --git a/pom.xml b/pom.xml index abff2e6c4..6c0156f15 100755 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ net.openhft chronicle-bom pom - 1.9.7 + 1.10.3-SNAPSHOT import @@ -67,7 +67,12 @@ net.openhft - lang + chronicle-values + + + + net.openhft + chronicle-threads @@ -147,7 +152,7 @@ net.openhft stage-compiler - 1.4 + 1.5 provided diff --git a/src/main/java/net/openhft/chronicle/hash/AbstractData.java b/src/main/java/net/openhft/chronicle/hash/AbstractData.java index 8f8deb3af..fd399a330 100644 --- a/src/main/java/net/openhft/chronicle/hash/AbstractData.java +++ b/src/main/java/net/openhft/chronicle/hash/AbstractData.java @@ -16,8 +16,6 @@ package net.openhft.chronicle.hash; -import net.openhft.chronicle.algo.hashing.LongHashFunction; - /** * Defines reasonable defaults for {@code Data}'s {@code equals()}, {@code hashCode()} and * {@code toString()}. They should be default implementations in the {@code Data} interface itself, @@ -37,7 +35,7 @@ public abstract class AbstractData implements Data { */ @Override public int hashCode() { - return (int) hash(LongHashFunction.city_1_1()); + return dataHashCode(); } /** @@ -45,9 +43,7 @@ public abstract class AbstractData implements Data { */ @Override public boolean equals(Object obj) { - return obj != null && - obj instanceof Data && - Data.bytesEquivalent(this, (Data) obj); + return dataEquals(obj); } /** diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java index a7081aec9..0b8a7e01a 100755 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.hash; +import net.openhft.chronicle.bytes.Byteable; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; @@ -25,21 +26,12 @@ import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.set.ChronicleSet; import net.openhft.chronicle.set.ChronicleSetBuilder; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.*; -import net.openhft.lang.io.serialization.impl.AllocateInstanceObjectFactory; -import net.openhft.lang.io.serialization.impl.NewInstanceObjectFactory; -import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory; -import net.openhft.lang.model.Byteable; import org.jetbrains.annotations.NotNull; -import java.io.Externalizable; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; -import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -98,8 +90,9 @@ public interface ChronicleHashBuilder, * should manually configure the actual chunk size in addition to this average key size * configuration, which is anyway needed. * - *

If key is a boxed primitive type or {@link Byteable} subclass, i. e. if key size is known - * statically, it is automatically accounted and shouldn't be specified by user. + *

If key is a boxed primitive type, a value interface or {@link Byteable} subclass, i. e. if + * key size is known statically, it is automatically accounted and shouldn't be specified by + * user. * *

Calling this method clears any previous {@link #constantKeySizeBySample(Object)} and * {@link #averageKey(Object)} configurations. @@ -118,7 +111,7 @@ public interface ChronicleHashBuilder, /** * Configures the average number of bytes, taken by serialized form of keys, put into hash * containers, created by this builder, by serializing the given {@code averageKey} using - * the configured {@link #keyMarshallers(BytesWriter, BytesReader) keys marshallers}. + * the configured {@link #keyMarshallers(SizedReader, SizedWriter) keys marshallers}. * In some cases, {@link #averageKeySize(double)} might be easier to use, than constructing the * "average key". If key size is always the same, call {@link #constantKeySizeBySample( * Object)} method instead of this one. @@ -438,73 +431,50 @@ public interface ChronicleHashBuilder, B cleanupRemovedEntries(boolean cleanupRemovedEntries); /** - * Configures a {@link BytesMarshallerFactory} to be used with {@link - * BytesMarshallableSerializer}, which is a default {@link #objectSerializer ObjectSerializer}, - * to serialize/deserialize data to/from off-heap memory in hash containers, created by this - * builder. + * Configures the {@code DataAccess} and {@code SizedReader} used to serialize and deserialize + * keys to and from off-heap memory in hash containers, created by this builder. * - *

Default {@code BytesMarshallerFactory} is an instance of {@link - * VanillaBytesMarshallerFactory}. This is a convenience configuration method, it has no effect - * on the resulting hash containers, if {@linkplain #keyMarshaller(BytesMarshaller) custom data - * marshallers} are configured, data types extends one of specific serialization interfaces, - * recognized by this builder (e. g. {@code Externalizable} or {@code BytesMarshallable}), or - * {@code ObjectSerializer} is configured. - * - * @param bytesMarshallerFactory the marshaller factory to be used with the default {@code - * ObjectSerializer}, i. e. {@code BytesMarshallableSerializer} + * @param keyReader the new bytes → key object reader strategy + * @param keyDataAccess the new strategy of accessing the keys' bytes for writing * @return this builder back - * @see #objectSerializer(ObjectSerializer) + * @see #keyMarshallers(SizedReader, SizedWriter) */ - B bytesMarshallerFactory(BytesMarshallerFactory bytesMarshallerFactory); - - /** - * Configures the serializer used to serialize/deserialize data to/from off-heap memory, when - * specified class doesn't implement a specific serialization interface like {@link - * Externalizable} or {@link BytesMarshallable} (for example, if data is loosely typed and just - * {@code Object} is specified as the data class), or nullable data, and if custom marshaller is - * not {@linkplain #keyMarshaller(BytesMarshaller) configured}, in hash containers, created by - * this builder. Please read {@link ObjectSerializer} docs for more info and available options. - * - *

Default serializer is {@link BytesMarshallableSerializer}, configured with the specified - * or default {@link #bytesMarshallerFactory(BytesMarshallerFactory) BytesMarshallerFactory}. - * - * @param objectSerializer the serializer used to serialize loosely typed or nullable data if - * custom marshaller is not configured - * @return this builder back - * @see #bytesMarshallerFactory(BytesMarshallerFactory) - * @see #keyMarshaller(BytesMarshaller) - */ - B objectSerializer(ObjectSerializer objectSerializer); - - /** - * Configures the {@code BytesMarshaller} used to serialize/deserialize keys to/from off-heap - * memory in hash containers, created by this builder. See the - * section about serialization in ChronicleMap manual for more information. - * - * @param keyMarshaller the marshaller used to serialize keys - * @return this builder back - * @see #keyMarshallers(BytesWriter, BytesReader) - * @see #objectSerializer(ObjectSerializer) - */ - B keyMarshaller(@NotNull BytesMarshaller keyMarshaller); + B keyReaderAndDataAccess(SizedReader keyReader, @NotNull DataAccess keyDataAccess); /** * Configures the marshallers, used to serialize/deserialize keys to/from off-heap memory in - * hash containers, created by this builder. See the - * section about serialization in ChronicleMap manual for more information. + * hash containers, created by this builder. * - *

Configuring marshalling this way results to a little bit more compact in-memory layout of - * the map, comparing to a single interface configuration: {@link #keyMarshaller(BytesMarshaller)}. - * - *

Passing {@link BytesInterop} (which is a subinterface of {@link BytesWriter}) as the first - * argument is supported, and even more advantageous from performance perspective. - * - * @param keyWriter the new key object → {@link Bytes} writer (interop) strategy - * @param keyReader the new {@link Bytes} → key object reader strategy + * @param keyReader the new bytes → key object reader strategy + * @param keyWriter the new key object → bytes writer strategy * @return this builder back - * @see #keyMarshaller(BytesMarshaller) + * @see #keyReaderAndDataAccess(SizedReader, DataAccess) */ - B keyMarshallers(@NotNull BytesWriter keyWriter, @NotNull BytesReader keyReader); + B keyMarshallers(@NotNull BytesReader keyReader, @NotNull BytesWriter keyWriter); + + /** + * Shortcut for {@link #keyMarshallers(BytesReader, BytesWriter) + * keyMarshallers(marshaller, marshaller)}. + */ + & BytesWriter> B keyMarshaller(@NotNull M marshaller); + + /** + * Configures the marshallers, used to serialize/deserialize keys to/from off-heap memory in + * hash containers, created by this builder. + * + * @param keyReader the new bytes → key object reader strategy + * @param keyWriter the new key object → bytes writer strategy + * @return this builder back + * @see #keyReaderAndDataAccess(SizedReader, DataAccess) + */ + B keyMarshallers(@NotNull SizedReader keyReader, @NotNull SizedWriter keyWriter); + + /** + * Shortcut for {@link #keyMarshallers(SizedReader, SizedWriter) + * keyMarshallers(sizedMarshaller, sizedMarshaller)}. + * @param sizedMarshaller + */ + & SizedWriter> B keyMarshaller(@NotNull M sizedMarshaller); /** * Configures the marshaller used to serialize actual key sizes to off-heap memory in hash @@ -515,8 +485,8 @@ public interface ChronicleHashBuilder, * type is always constant and {@code ChronicleHashBuilder} implementation knows about it, this * configuration takes no effect, because a special {@link SizeMarshaller} implementation, which * doesn't actually do any marshalling, and just returns the known constant size on {@link - * SizeMarshaller#readSize(Bytes)} calls, is used instead of any {@code SizeMarshaller} - * configured using this method. + * SizeMarshaller#readSize(net.openhft.chronicle.bytes.Bytes)} calls, is used instead of any {@code + * SizeMarshaller} configured using this method. * * @param keySizeMarshaller the new marshaller, used to serialize actual key sizes to off-heap * memory @@ -524,43 +494,6 @@ public interface ChronicleHashBuilder, */ B keySizeMarshaller(@NotNull SizeMarshaller keySizeMarshaller); - /** - * Configures factory which is used to create a new key instance, if key class is either {@link - * Byteable}, {@link BytesMarshallable} or {@link Externalizable} subclass, or key type is - * eligible for data value generation, or {@linkplain #keyMarshallers(BytesWriter, BytesReader) - * configured custom key reader} implements {@link DeserializationFactoryConfigurableBytesReader - * }, in maps, created by this builder. - * - *

Default key deserialization factory is {@link NewInstanceObjectFactory}, which creates a - * new key instance using {@link Class#newInstance()} default constructor. You could provide an - * {@link AllocateInstanceObjectFactory}, which uses {@code Unsafe.allocateInstance(Class)} (you - * might want to do this for better performance or if you don't want to initialize fields), or a - * factory which calls a key class constructor with some arguments, or a factory which - * internally delegates to instance pool or {@link ThreadLocal}, to reduce allocations. - * - * @param keyDeserializationFactory the key factory used to produce instances to deserialize - * data in - * @return this builder back - * @throws IllegalStateException if it is not possible to apply deserialization factory to - * key deserializers, currently configured for this builder - */ - B keyDeserializationFactory(@NotNull ObjectFactory keyDeserializationFactory); - - /** - * Specifies that key objects, queried with the hash containers, created by this builder, are - * inherently immutable. Keys in {@link ChronicleMap} or {@link ChronicleSet} are not required - * to be immutable, as in ordinary {@link Map} or {@link Set} implementations, because they are - * serialized off-heap. However, {@code ChronicleMap} and {@code ChronicleSet} implementations - * can benefit from the knowledge that keys are not mutated between queries. - * - *

By default, {@code ChronicleHashBuilder}s detects immutability automatically only for very - * few standard JDK types (for example, for {@link String}), it is not recommended to rely on - * {@code ChronicleHashBuilder} to be smart enough about this. - * - * @return this builder back - */ - B immutableKeys(); - /** * Specifies whether on the current combination of platform, OS and Jvm aligned 8-byte reads * and writes are atomic or not. By default, Chronicle tries to determine this itself, but diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java index 1e0ee4410..a0dc481cf 100644 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilderPrivateAPI.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.hash; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; public interface ChronicleHashBuilderPrivateAPI { diff --git a/src/main/java/net/openhft/chronicle/hash/Data.java b/src/main/java/net/openhft/chronicle/hash/Data.java index d3982f328..56b031e62 100644 --- a/src/main/java/net/openhft/chronicle/hash/Data.java +++ b/src/main/java/net/openhft/chronicle/hash/Data.java @@ -75,11 +75,30 @@ public interface Data { * Reads the object from the value's bytes, trying to reuse the given object * (might be {@code null}). */ - V getUsing(@Nullable V usingInstance); + V getUsing(@Nullable V using); static boolean bytesEquivalent(Data d1, Data d2) { if (d1.size() != d2.size()) return false; return BytesUtil.bytesEqual(d1.bytes(), d1.offset(), d2.bytes(), d2.offset(), d1.size()); } + + /** + * {@code Data} implementations should override {@link Object#hashCode()} with delegation to + * this method. Computes value's hash code by applying a hash function to {@code Data}'s + * bytes representation. + */ + default int dataHashCode() { + return (int) hash(LongHashFunction.city_1_1()); + } + + /** + * {@code Data} implementations should override {@link Object#equals(Object)} with delegation to + * this method. Compares {@code Data}s' bytes representations. + */ + default boolean dataEquals(Object obj) { + return obj != null && + obj instanceof Data && + Data.bytesEquivalent(this, (Data) obj); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/VanillaGlobalMutableState.java b/src/main/java/net/openhft/chronicle/hash/VanillaGlobalMutableState.java index 0434b24ff..24678eb02 100644 --- a/src/main/java/net/openhft/chronicle/hash/VanillaGlobalMutableState.java +++ b/src/main/java/net/openhft/chronicle/hash/VanillaGlobalMutableState.java @@ -16,7 +16,8 @@ package net.openhft.chronicle.hash; -import net.openhft.lang.model.Byteable; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.values.Group; /** *

This interface is a private API, don't use in client code

@@ -25,15 +26,19 @@ import net.openhft.lang.model.Byteable; */ public interface VanillaGlobalMutableState extends Byteable { + @Group(1) int getAllocatedExtraTierBulks(); void setAllocatedExtraTierBulks(int allocatedExtraTierBulks); + @Group(2) long getFirstFreeTierIndex(); void setFirstFreeTierIndex(long firstFreeTierIndex); + @Group(3) long getExtraTiersInUse(); void setExtraTiersInUse(long extraTiersInUse); + @Group(4) long getSegmentHeadersOffset(); void setSegmentHeadersOffset(long segmentHeadersOffset); } diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/Access.java b/src/main/java/net/openhft/chronicle/hash/hashing/Access.java deleted file mode 100644 index 1bc0d02c8..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/Access.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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.hash.hashing; - -import net.openhft.lang.io.Bytes; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -/** - * Strategy of reading bytes, defines the abstraction of {@code T} class instances as ordered byte - * sequence. All {@code getXXX(input, offset)} should be consistent to each other in terms of - * ordered byte sequence each {@code T} instance represents. For example, if some {@code - * Access} implementation returns {@link ByteOrder#LITTLE_ENDIAN} on {@link #byteOrder(Object) - * byteOrder(input)} call, the following expressions should always have the same value: - *
    - *
  • {@code getLong(input, 0)}
  • - *
  • {@code getUnsignedInt(input, 0) | (getUnsignedInt(input, 4) << 32)}
  • - *
  • {@code getUnsignedInt(input, 0) |
    - *    ((long) getUnsignedShort(input, 4) << 32) |
    - *    ((long) getUnsignedByte(input, 6) << 48) |
    - *    ((long) getUnsignedByte(input, 7) << 56)}
  • - *
  • And so on
  • - *
- * - *

{@code getXXX(input, offset)} methods could throw unchecked exceptions when requested bytes - * range is outside of the bounds of the byte sequence, represented by the given {@code input}. - * However, they could omit checks for better performance. - * - *

Only {@link #getByte(Object, long)} and {@link #byteOrder(Object)} methods are abstract in - * this class, so implementing them is sufficient for valid {@code Access} instance, but for - * efficiency your should override methods used by target {@link LongHashFunction} implementation. - * - *

{@code Access} API is designed for inputs, that actually represent byte sequences that lay - * continuously in memory. Theoretically {@code Access} strategy could be implemented for - * non-continuous byte sequences, or abstractions which aren't actually present in memory as they - * are accessed, but this should be awkward, and hashing using such {@code Access} is expected to - * be slow. - * - * @param the type of the object to access - * @see LongHashFunction#hash(Object, Access, long, long) - * @deprecated moved to Chronicle-Bytes: {@link net.openhft.chronicle.bytes.Access} - */ -@Deprecated -public abstract class Access { - - /** - * Returns the {@code Access} to any {@link Bytes}. This {@code Access} isn't useful in - * the user code, because methods {@link LongHashFunction#hashBytes(Bytes)} and - * {@link LongHashFunction#hashBytes(Bytes, long, long)} exist. This {@code Access} could be - * used in new {@link LongHashFunction} implementations. - * - * @return the {@code Access} to {@link Bytes} instances - */ - public static Access toBytes() { - return BytesAccess.INSTANCE; - } - - /** - * Returns the {@code Access} delegating {@code getXXX(input, offset)} methods to {@code - * sun.misc.Unsafe.getXXX(input, offset)}. - * - *

Usage example:

{@code
-     * class Pair {
-     *     long first, second;
-     *
-     *     static final long pairDataOffset =
-     *         theUnsafe.objectFieldOffset(Pair.class.getDeclaredField("first"));
-     *
-     *     static long hashPair(Pair pair, LongHashFunction hashFunction) {
-     *         return hashFunction.hash(pair, Access.unsafe(), pairDataOffset, 16L);
-     *     }
-     * }}
- * - *

{@code null} is a valid input, on accepting {@code null} {@code Unsafe} just interprets - * the given offset as a wild memory address. Note that for hashing memory by address there is - * a shortcut {@link LongHashFunction#hashMemory(long, long) hashMemory(address, len)} method. - * - * @param the type of objects to access - * @return the unsafe memory {@code Access} - */ - public static Access unsafe() { - return (Access) UnsafeAccess.INSTANCE; - } - - /** - * Returns the {@code Access} to any {@link ByteBuffer}. This {@code Access} isn't useful in - * the user code, because methods {@link LongHashFunction#hashBytes(ByteBuffer)} and - * {@link LongHashFunction#hashBytes(ByteBuffer, int, int)} exist. This {@code Access} could be - * used in new {@link LongHashFunction} implementations. - * - * @return the {@code Access} to {@link ByteBuffer}s - */ - public static Access toByteBuffer() { - return ByteBufferAccess.INSTANCE; - } - - /** - * Returns the {@code Access} to {@link CharSequence}s backed by {@linkplain - * ByteOrder#nativeOrder() native} {@code char} reads, typically from {@code char[]} array. - * - *

Usage example:

{@code
-     * static long hashStringBuffer(StringBuffer buffer, LongHashFunction hashFunction) {
-     *     return hashFunction.hash(buffer, Access.toNativeCharSequence(),
-     *         // * 2L because length is passed in bytes, not chars
-     *         0L, buffer.length() * 2L);
-     * }}
- * - *

This method is a shortcut for {@code Access.toCharSequence(ByteOrder.nativeOrder())}. - * - * @param the {@code CharSequence} subtype (backed by native {@code char reads}) to access - * @return the {@code Access} to {@link CharSequence}s backed by native {@code char} reads - * @see #toCharSequence(ByteOrder) - */ - public static Access toNativeCharSequence() { - return (Access) CharSequenceAccess.nativeCharSequenceAccess(); - } - - /** - * Returns the {@code Access} to {@link CharSequence}s backed by {@code char} reads made in - * the specified byte order. - * - *

Usage example:

{@code
-     * static long hashCharBuffer(CharBuffer buffer, LongHashFunction hashFunction) {
-     *     return hashFunction.hash(buffer, Access.toCharSequence(buffer.order()),
-     *         // * 2L because length is passed in bytes, not chars
-     *         0L, buffer.length() * 2L);
-     * }}
- * - * @param backingOrder the byte order of {@code char} reads backing - * {@code CharSequences} to access - * @return the {@code Access} to {@link CharSequence}s backed by {@code char} reads made in - * the specified byte order - * @param the {@code CharSequence} subtype to access - * @see #toNativeCharSequence() - */ - public static Access toCharSequence(ByteOrder backingOrder) { - return (Access) CharSequenceAccess.charSequenceAccess(backingOrder); - } - - /** - * Constructor for use in subclasses. - */ - protected Access() {} - - /** - * Reads {@code [offset, offset + 7]} bytes of the byte sequence represented by the given - * {@code input} as a single {@code long} value. - * - * @param input the object to access - * @param offset offset to the first byte to read within the byte sequence represented - * by the given object - * @return eight bytes as a {@code long} value, in {@linkplain #byteOrder(Object) the expected - * order} - */ - public long getLong(T input, long offset) { - if (byteOrder(input) == LITTLE_ENDIAN) { - return getUnsignedInt(input, offset) | (getUnsignedInt(input, offset + 4L) << 32); - } else { - return getUnsignedInt(input, offset + 4L) | (getUnsignedInt(input, offset) << 32); - } - } - - /** - * Shortcut for {@code getInt(input, offset) & 0xFFFFFFFFL}. Could be implemented more - * efficiently. - * - * @param input the object to access - * @param offset offset to the first byte to read within the byte sequence represented - * by the given object - * @return four bytes as an unsigned int value, in {@linkplain #byteOrder(Object) the expected - * order} - */ - public long getUnsignedInt(T input, long offset) { - return ((long) getInt(input, offset)) & 0xFFFFFFFFL; - } - - /** - * Reads {@code [offset, offset + 3]} bytes of the byte sequence represented by the given - * {@code input} as a single {@code int} value. - * - * @param input the object to access - * @param offset offset to the first byte to read within the byte sequence represented - * by the given object - * @return four bytes as an {@code int} value, in {@linkplain #byteOrder(Object) the expected - * order} - */ - public int getInt(T input, long offset) { - if (byteOrder(input) == LITTLE_ENDIAN) { - return getUnsignedShort(input, offset) | (getUnsignedShort(input, offset + 2L) << 16); - } else { - return getUnsignedShort(input, offset + 2L) | (getUnsignedShort(input, offset) << 16); - } - } - - /** - * Shortcut for {@code getShort(input, offset) & 0xFFFF}. Could be implemented more - * efficiently. - * - * @param input the object to access - * @param offset offset to the first byte to read within the byte sequence represented - * by the given object - * @return two bytes as an unsigned short value, in {@linkplain #byteOrder(Object) the expected - * order} - */ - public int getUnsignedShort(T input, long offset) { - if (byteOrder(input) == LITTLE_ENDIAN) { - return getUnsignedByte(input, offset) | (getUnsignedByte(input, offset + 1L) << 8); - } else { - return getUnsignedByte(input, offset + 1L) | (getUnsignedByte(input, offset) << 8); - } - } - - /** - * Reads {@code [offset, offset + 1]} bytes of the byte sequence represented by the given - * {@code input} as a single {@code short} value, returned widened to {@code int}. - * - * @param input the object to access - * @param offset offset to the first byte to read within the byte sequence represented - * by the given object - * @return two bytes as a {@code short} value, in {@linkplain #byteOrder(Object) the expected - * order}, widened to {@code int} - */ - public int getShort(T input, long offset) { - return (int) (short) getUnsignedShort(input, offset); - } - - /** - * Shortcut for {@code getByte(input, offset) & 0xFF}. Could be implemented more efficiently. - * - * @param input the object to access - * @param offset offset to the byte to read within the byte sequence represented - * by the given object - * @return a byte by the given {@code offset}, interpreted as unsigned - */ - public int getUnsignedByte(T input, long offset) { - return getByte(input, offset) & 0xFF; - } - - /** - * Reads a single byte at the given {@code offset} in the byte sequence represented by the given - * {@code input}, returned widened to {@code int}. - * - * @param input the object to access - * @param offset offset to the byte to read within the byte sequence represented - * by the given object - * @return a byte by the given {@code offset}, widened to {@code int} - */ - public abstract int getByte(T input, long offset); - - /** - * The byte order in which all multi-byte {@code getXXX()} reads from the given {@code input} - * are performed. - * - * @param input the accessed object - * @return the byte order of all multi-byte reads from the given {@code input} - */ - public abstract ByteOrder byteOrder(T input); -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/ByteBufferAccess.java b/src/main/java/net/openhft/chronicle/hash/hashing/ByteBufferAccess.java deleted file mode 100644 index 274063f3a..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/ByteBufferAccess.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.hash.hashing; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -final class ByteBufferAccess extends Access { - public static final ByteBufferAccess INSTANCE = new ByteBufferAccess(); - - private ByteBufferAccess() {} - - @Override - public long getLong(ByteBuffer input, long offset) { - return input.getLong((int) offset); - } - - @Override - public long getUnsignedInt(ByteBuffer input, long offset) { - return Primitives.unsignedInt(getInt(input, offset)); - } - - @Override - public int getInt(ByteBuffer input, long offset) { - return input.getInt((int) offset); - } - - @Override - public int getUnsignedShort(ByteBuffer input, long offset) { - return Primitives.unsignedShort(getShort(input, offset)); - } - - @Override - public int getShort(ByteBuffer input, long offset) { - return input.getShort((int) offset); - } - - @Override - public int getUnsignedByte(ByteBuffer input, long offset) { - return Primitives.unsignedByte(getByte(input, offset)); - } - - @Override - public int getByte(ByteBuffer input, long offset) { - return input.get((int) offset); - } - - @Override - public ByteOrder byteOrder(ByteBuffer input) { - return input.order(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/BytesAccess.java b/src/main/java/net/openhft/chronicle/hash/hashing/BytesAccess.java deleted file mode 100644 index a640ceace..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/BytesAccess.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.hash.hashing; - -import net.openhft.lang.io.Bytes; - -import java.nio.ByteOrder; - -@Deprecated -public final class BytesAccess extends Access { - public static final BytesAccess INSTANCE = new BytesAccess(); - - private BytesAccess() {} - - @Override - public long getLong(Bytes input, long offset) { - return input.readLong(offset); - } - - @Override - public long getUnsignedInt(Bytes input, long offset) { - return input.readUnsignedInt(offset); - } - - @Override - public int getInt(Bytes input, long offset) { - return input.readInt(offset); - } - - @Override - public int getUnsignedShort(Bytes input, long offset) { - return input.readUnsignedShort(offset); - } - - @Override - public int getShort(Bytes input, long offset) { - return input.readShort(offset); - } - - @Override - public int getUnsignedByte(Bytes input, long offset) { - return input.readUnsignedByte(offset); - } - - @Override - public int getByte(Bytes input, long offset) { - return input.readByte(offset); - } - - @Override - public ByteOrder byteOrder(Bytes input) { - return input.byteOrder(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/CharSequenceAccess.java b/src/main/java/net/openhft/chronicle/hash/hashing/CharSequenceAccess.java deleted file mode 100644 index 4b6ffcb2a..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/CharSequenceAccess.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.hash.hashing; - -import net.openhft.chronicle.hash.hashing.Access; - -import java.nio.ByteOrder; - -import static java.nio.ByteOrder.BIG_ENDIAN; -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -abstract class CharSequenceAccess extends Access { - - public static CharSequenceAccess charSequenceAccess(ByteOrder order) { - return order == LITTLE_ENDIAN ? - LittleEndianCharSequenceAccess.INSTANCE : - BigEndianCharSequenceAccess.INSTANCE; - } - - public static CharSequenceAccess nativeCharSequenceAccess() { - return charSequenceAccess(ByteOrder.nativeOrder()); - } - - private static int ix(long offset) { - return (int) (offset >> 1); - } - - static long getLong(CharSequence input, long offset, - int char0Off, int char1Off, int char2Off, int char3Off) { - int base = ix(offset); - long char0 = input.charAt(base + char0Off); - long char1 = input.charAt(base + char1Off); - long char2 = input.charAt(base + char2Off); - long char3 = input.charAt(base + char3Off); - return char0 | (char1 << 16) | (char2 << 32) | (char3 << 48); - } - - static long getUnsignedInt(CharSequence input, long offset, - int char0Off, int char1Off) { - int base = ix(offset); - long char0 = input.charAt(base + char0Off); - long char1 = input.charAt(base + char1Off); - return char0 | (char1 << 16); - } - - private CharSequenceAccess() {} - - @Override - public int getInt(CharSequence input, long offset) { - return (int) getUnsignedInt(input, offset); - } - - @Override - public int getUnsignedShort(CharSequence input, long offset) { - return input.charAt(ix(offset)); - } - - @Override - public int getShort(CharSequence input, long offset) { - return (int) (short) input.charAt(ix(offset)); - } - - static int getUnsignedByte(CharSequence input, long offset, int shift) { - return Primitives.unsignedByte(input.charAt(ix(offset)) >> shift); - } - - @Override - public int getByte(CharSequence input, long offset) { - return (int) (byte) getUnsignedByte(input, offset); - } - - private static class LittleEndianCharSequenceAccess extends CharSequenceAccess { - private static final CharSequenceAccess INSTANCE = new LittleEndianCharSequenceAccess(); - - private LittleEndianCharSequenceAccess() {} - - @Override - public long getLong(CharSequence input, long offset) { - return getLong(input, offset, 0, 1, 2, 3); - } - - @Override - public long getUnsignedInt(CharSequence input, long offset) { - return getUnsignedInt(input, offset, 0, 1); - } - - @Override - public int getUnsignedByte(CharSequence input, long offset) { - return getUnsignedByte(input, offset, ((int) offset & 1) << 3); - } - - @Override - public ByteOrder byteOrder(CharSequence input) { - return LITTLE_ENDIAN; - } - } - - private static class BigEndianCharSequenceAccess extends CharSequenceAccess { - private static final CharSequenceAccess INSTANCE = new BigEndianCharSequenceAccess(); - - private BigEndianCharSequenceAccess() {} - - @Override - public long getLong(CharSequence input, long offset) { - return getLong(input, offset, 3, 2, 1, 0); - } - - @Override - public long getUnsignedInt(CharSequence input, long offset) { - return getUnsignedInt(input, offset, 1, 0); - } - - @Override - public int getUnsignedByte(CharSequence input, long offset) { - return getUnsignedByte(input, offset, (((int) offset & 1) ^ 1) << 3); - } - - @Override - public ByteOrder byteOrder(CharSequence input) { - return BIG_ENDIAN; - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/CityHash_1_1.java b/src/main/java/net/openhft/chronicle/hash/hashing/CityHash_1_1.java deleted file mode 100644 index 380ce5782..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/CityHash_1_1.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * 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.hash.hashing; - -import static java.lang.Long.reverseBytes; -import static java.lang.Long.rotateRight; -import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static net.openhft.chronicle.hash.hashing.LongHashFunction.NATIVE_LITTLE_ENDIAN; - -/** - * Adapted from the C++ CityHash implementation from Google at - * http://code.google.com/p/cityhash/source/browse/trunk/src/city.cc. - */ -class CityHash_1_1 { - private static final CityHash_1_1 INSTANCE = new CityHash_1_1(); - - private static final CityHash_1_1 NATIVE_CITY = NATIVE_LITTLE_ENDIAN ? - CityHash_1_1.INSTANCE : BigEndian.INSTANCE; - - private CityHash_1_1() {} - - private static final long K0 = 0xc3a5c85c97cb3127L; - private static final long K1 = 0xb492b66fbe98f273L; - private static final long K2 = 0x9ae16a3b2f90404fL; - - private static long shiftMix(long val) { - return val ^ (val >>> 47); - } - - private static long hashLen16(long u, long v) { - return hashLen16(u, v, K_MUL); - } - - private static final long K_MUL = 0x9ddfea08eb382d69L; - - private static long hashLen16(long u, long v, long mul) { - long a = shiftMix((u ^ v) * mul); - return shiftMix((v ^ a) * mul) * mul; - } - - private static long mul(long len) { - return K2 + (len << 1); - } - - private static long hash1To3Bytes(int len, int firstByte, int midOrLastByte, int lastByte) { - int y = firstByte + (midOrLastByte << 8); - int z = len + (lastByte << 2); - return shiftMix((((long) y) * K2) ^ (((long) z) * K0)) * K2; - } - - private static long hash4To7Bytes(long len, long first4Bytes, long last4Bytes) { - long mul = mul(len); - return hashLen16(len + (first4Bytes << 3), last4Bytes, mul); - } - - private static long hash8To16Bytes(long len, long first8Bytes, long last8Bytes) { - long mul = mul(len); - long a = first8Bytes + K2; - long c = rotateRight(last8Bytes, 37) * mul + a; - long d = (rotateRight(a, 25) + last8Bytes) * mul; - return hashLen16(c, d, mul); - } - - long fetch64(Access access, T in, long off) { - return access.getLong(in, off); - } - - int fetch32(Access access, T in, long off) { - return access.getInt(in, off); - } - - long toLittleEndian(long v) { - return v; - } - - int toLittleEndian(int v) { - return v; - } - - private long hashLen0To16(Access access, T in, long off, long len) { - if (len >= 8L) { - long a = fetch64(access, in, off); - long b = fetch64(access, in, off + len - 8L); - return hash8To16Bytes(len, a, b); - } else if (len >= 4L) { - long a = Primitives.unsignedInt(fetch32(access, in, off)); - long b = Primitives.unsignedInt(fetch32(access, in, off + len - 4L)); - return hash4To7Bytes(len, a, b); - } else if (len > 0L) { - int a = access.getUnsignedByte(in, off); - int b = access.getUnsignedByte(in, off + (len >> 1)); - int c = access.getUnsignedByte(in, off + len - 1L); - return hash1To3Bytes((int) len, a, b, c); - } - return K2; - } - - private long hashLen17To32(Access access, T in, long off, long len) { - long mul = mul(len); - long a = fetch64(access, in, off) * K1; - long b = fetch64(access, in, off + 8L); - long c = fetch64(access, in, off + len - 8L) * mul; - long d = fetch64(access, in, off + len - 16L) * K2; - return hashLen16(rotateRight(a + b, 43) + rotateRight(c, 30) + d, - a + rotateRight(b + K2, 18) + c, mul); - } - - private long hashLen33To64(Access access, T in, long off, long len) { - long mul = mul(len); - long a = fetch64(access, in, off) * K2; - long b = fetch64(access, in, off + 8L); - long c = fetch64(access, in, off + len - 24L); - long d = fetch64(access, in, off + len - 32L); - long e = fetch64(access, in, off + 16L) * K2; - long f = fetch64(access, in, off + 24L) * 9L; - long g = fetch64(access, in, off + len - 8L); - long h = fetch64(access, in, off + len - 16L) * mul; - long u = rotateRight(a + g, 43) + (rotateRight(b, 30) + c) * 9L; - long v = ((a + g) ^ d) + f + 1L; - long w = reverseBytes((u + v) * mul) + h; - long x = rotateRight(e + f, 42) + c; - long y = (reverseBytes((v + w) * mul) + g) * mul; - long z = e + f + c; - a = reverseBytes((x + z) * mul + y) + b; - b = shiftMix((z + a) * mul + d + h) * mul; - return b + x; - } - - long cityHash64(Access access, T in, long off, long len) { - if (len <= 32L) { - if (len <= 16L) { - return hashLen0To16(access, in, off, len); - } else { - return hashLen17To32(access, in, off, len); - } - } else if (len <= 64L) { - return hashLen33To64(access, in, off, len); - } - - long x = fetch64(access, in, off + len - 40L); - long y = fetch64(access, in, off + len - 16L) + fetch64(access, in, off + len - 56L); - long z = hashLen16(fetch64(access, in, off + len - 48L) + len, - fetch64(access, in, off + len - 24L)); - - long vFirst, vSecond, wFirst, wSecond; - - // This and following 3 blocks are produced by a single-click inline-function refactoring. - // IntelliJ IDEA ftw - // WeakHashLen32WithSeeds - long a3 = len; - long b3 = z; - long w4 = fetch64(access, in, off + len - 64L); - long x4 = fetch64(access, in, off + len - 64L + 8L); - long y4 = fetch64(access, in, off + len - 64L + 16L); - long z4 = fetch64(access, in, off + len - 64L + 24L); - a3 += w4; - b3 = rotateRight(b3 + a3 + z4, 21); - long c3 = a3; - a3 += x4 + y4; - b3 += rotateRight(a3, 44); - vFirst = a3 + z4; - vSecond = b3 + c3; - - // WeakHashLen32WithSeeds - long a2 = y + K1; - long b2 = x; - long w3 = fetch64(access, in, off + len - 32L); - long x3 = fetch64(access, in, off + len - 32L + 8L); - long y3 = fetch64(access, in, off + len - 32L + 16L); - long z3 = fetch64(access, in, off + len - 32L + 24L); - a2 += w3; - b2 = rotateRight(b2 + a2 + z3, 21); - long c2 = a2; - a2 += x3 + y3; - b2 += rotateRight(a2, 44); - wFirst = a2 + z3; - wSecond = b2 + c2; - - x = x * K1 + fetch64(access, in, off); - - len = (len - 1L) & (~63L); - do { - x = rotateRight(x + y + vFirst + fetch64(access, in, off + 8L), 37) * K1; - y = rotateRight(y + vSecond + fetch64(access, in, off + 48L), 42) * K1; - x ^= wSecond; - y += vFirst + fetch64(access, in, off + 40L); - z = rotateRight(z + wFirst, 33) * K1; - - // WeakHashLen32WithSeeds - long a1 = vSecond * K1; - long b1 = x + wFirst; - long w2 = fetch64(access, in, off); - long x2 = fetch64(access, in, off + 8L); - long y2 = fetch64(access, in, off + 16L); - long z2 = fetch64(access, in, off + 24L); - a1 += w2; - b1 = rotateRight(b1 + a1 + z2, 21); - long c1 = a1; - a1 += x2 + y2; - b1 += rotateRight(a1, 44); - vFirst = a1 + z2; - vSecond = b1 + c1; - - // WeakHashLen32WithSeeds - long a = z + wSecond; - long b = y + fetch64(access, in, off + 16L); - long w1 = fetch64(access, in, off + 32L); - long x1 = fetch64(access, in, off + 32L + 8L); - long y1 = fetch64(access, in, off + 32L + 16L); - long z1 = fetch64(access, in, off + 32L + 24L); - a += w1; - b = rotateRight(b + a + z1, 21); - long c = a; - a += x1 + y1; - b += rotateRight(a, 44); - wFirst = a + z1; - wSecond = b + c; - - long tmp = x; - x = z; - z = tmp; - - len -= 64L; - off += 64L; - } while (len != 0); - return hashLen16(hashLen16(vFirst, wFirst) + shiftMix(y) * K1 + z, - hashLen16(vSecond, wSecond) + x); - } - - private static class BigEndian extends CityHash_1_1 { - private static final BigEndian INSTANCE = new BigEndian(); - private BigEndian() {} - - @Override - long fetch64(Access access, T in, long off) { - return reverseBytes(super.fetch64(access, in, off)); - } - - @Override - int fetch32(Access access, T in, long off) { - return Integer.reverseBytes(super.fetch32(access, in, off)); - } - - @Override - long toLittleEndian(long v) { - return reverseBytes(v); - } - - @Override - int toLittleEndian(int v) { - return Integer.reverseBytes(v); - } - } - - private static class AsLongHashFunction extends LongHashFunction { - public static final AsLongHashFunction INSTANCE = new AsLongHashFunction(); - private static final long serialVersionUID = 0L; - - private Object readResolve() { - return INSTANCE; - } - - @Override - public long hashLong(long input) { - input = NATIVE_CITY.toLittleEndian(input); - long hash = hash8To16Bytes(8L, input, input); - return finalize(hash); - } - - @Override - public long hashInt(int input) { - input = NATIVE_CITY.toLittleEndian(input); - long unsignedInt = Primitives.unsignedInt(input); - long hash = hash4To7Bytes(4L, unsignedInt, unsignedInt); - return finalize(hash); - } - - @Override - public long hashShort(short input) { - return hashChar((char) input); - } - - private static final int FIRST_SHORT_BYTE_SHIFT = NATIVE_LITTLE_ENDIAN ? 0 : 8; - // JIT could probably optimize & -1 to no-op - private static final int FIRST_SHORT_BYTE_MASK = NATIVE_LITTLE_ENDIAN ? 0xFF : -1; - private static final int SECOND_SHORT_BYTE_SHIFT = 8 - FIRST_SHORT_BYTE_SHIFT; - private static final int SECOND_SHORT_BYTE_MASK = NATIVE_LITTLE_ENDIAN ? -1 : 0xFF; - - @Override - public long hashChar(char input) { - int unsignedInput = (int) input; - int firstByte = (unsignedInput >> FIRST_SHORT_BYTE_SHIFT) & FIRST_SHORT_BYTE_MASK; - int secondByte = (unsignedInput >> SECOND_SHORT_BYTE_SHIFT) & SECOND_SHORT_BYTE_MASK; - long hash = hash1To3Bytes(2, firstByte, secondByte, secondByte); - return finalize(hash); - } - - @Override - public long hashByte(byte input) { - int unsignedByte = Primitives.unsignedByte(input); - long hash = hash1To3Bytes(1, unsignedByte, unsignedByte, unsignedByte); - return finalize(hash); - } - - @Override - public long hashVoid() { - return K2; - } - - @Override - public long hash(T input, Access access, long off, long len) { - long hash; - if (access.byteOrder(input) == LITTLE_ENDIAN) { - hash = CityHash_1_1.INSTANCE.cityHash64(access, input, off, len); - } else { - hash = BigEndian.INSTANCE.cityHash64(access, input, off, len); - } - return finalize(hash); - } - - long finalize(long hash) { - return hash; - } - } - - public static LongHashFunction asLongHashFunctionWithoutSeed() { - return AsLongHashFunction.INSTANCE; - } - - private static class AsLongHashFunctionSeeded extends AsLongHashFunction { - private static final long serialVersionUID = 0L; - - private final long seed0, seed1; - private transient long voidHash; - - private AsLongHashFunctionSeeded(long seed0, long seed1) { - this.seed0 = seed0; - this.seed1 = seed1; - voidHash = finalize(K2); - } - - @Override - public long hashVoid() { - return voidHash; - } - - @Override - protected long finalize(long hash) { - return hashLen16(hash - seed0, seed1); - } - } - - public static LongHashFunction asLongHashFunctionWithSeed(long seed) { - return new AsLongHashFunctionSeeded(K2, seed); - } - - public static LongHashFunction asLongHashFunctionWithTwoSeeds(long seed0, long seed1) { - return new AsLongHashFunctionSeeded(seed0, seed1); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/HotSpotPrior7u6StringHash.java b/src/main/java/net/openhft/chronicle/hash/hashing/HotSpotPrior7u6StringHash.java deleted file mode 100644 index 82eb97ad6..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/HotSpotPrior7u6StringHash.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.hash.hashing; - -import java.lang.reflect.Field; - -enum HotSpotPrior7u6StringHash implements StringHash { - INSTANCE; - - private static final long valueOffset; - private static final long offsetOffset; - - static { - try { - Field valueField = String.class.getDeclaredField("value"); - valueOffset = UnsafeAccess.UNSAFE.objectFieldOffset(valueField); - - Field offsetField = String.class.getDeclaredField("offset"); - offsetOffset = UnsafeAccess.UNSAFE.objectFieldOffset(offsetField); - } catch (NoSuchFieldException e) { - throw new AssertionError(e); - } - } - - @Override - public long longHash(String s, LongHashFunction hashFunction, int off, int len) { - char[] value = (char[]) UnsafeAccess.UNSAFE.getObject(s, valueOffset); - int offset = UnsafeAccess.UNSAFE.getInt(s, offsetOffset); - return hashFunction.hashChars(value, offset + off, len); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/LongHashFunction.java b/src/main/java/net/openhft/chronicle/hash/hashing/LongHashFunction.java deleted file mode 100644 index 31c09363f..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/LongHashFunction.java +++ /dev/null @@ -1,496 +0,0 @@ -/* - * 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.hash.hashing; - -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.NativeBytes; -import org.jetbrains.annotations.NotNull; - -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static java.nio.ByteOrder.nativeOrder; -import static net.openhft.chronicle.hash.hashing.CharSequenceAccess.nativeCharSequenceAccess; -import static net.openhft.chronicle.hash.hashing.UnsafeAccess.*; - -/** - * Hash function producing {@code long}-valued result from byte sequences of any length and - * a plenty of different sources which "feels like byte sequences". Except {@link - * #hashBytes(byte[])}, {@link #hashBytes(ByteBuffer)} (with their "sliced" versions) and - * {@link #hashMemory(long, long)} methods, which actually accept byte sequences, notion of byte - * sequence is defined as follows: - *
    - *
  • For methods accepting arrays of Java primitives, {@code String}s and - * {@code StringBuilder}s, byte sequence is how the input's bytes are actually lay in memory. - *
  • - *
  • For methods accepting single primitive values, byte sequence is how this primitive - * would be put into memory with {@link ByteOrder#nativeOrder() native} byte order, or - * equivalently, {@code hashXxx(primitive)} has always the same result as {@code - * hashXxxs(new xxx[] {primitive})}, where "xxx" is any Java primitive type name.
  • - *
  • For {@link #hash(Object, Access, long, long)} method byte sequence abstraction - * is defined by the given {@link Access} strategy to the given object.
  • - *
- * - * @see BytesInterop#hash(LongHashFunction, Object) - * @deprecated moved to Chronicle-Algorithms: - * {@link net.openhft.chronicle.algo.hashing.LongHashFunction} - */ -@Deprecated -public abstract class LongHashFunction implements Serializable { - private static final long serialVersionUID = 0L; - - static final boolean NATIVE_LITTLE_ENDIAN = nativeOrder() == LITTLE_ENDIAN; - static final byte TRUE_BYTE_VALUE = UNSAFE.getByte(new boolean[] {true}, BOOLEAN_BASE); - static final byte FALSE_BYTE_VALUE = UNSAFE.getByte(new boolean[] {false}, BOOLEAN_BASE); - - /** - * Returns a hash function implementing - * - * CityHash64 algorithm, version 1.1 without seed values. This implementation produce - * equal results for equal input on platforms with different {@link ByteOrder}, but is slower - * on big-endian platforms than on little-endian. - * @return an instance of LongHashFunction - * - * @see #city_1_1(long) - * @see #city_1_1(long, long) - */ - public static LongHashFunction city_1_1() { - return CityHash_1_1.asLongHashFunctionWithoutSeed(); - } - - /** - * Returns a hash function implementing - * - * CityHash64 algorithm, version 1.1 using the given seed value. This implementation produce - * equal results for equal input on platforms with different {@link ByteOrder}, but is slower - * on big-endian platforms than on little-endian. - * - * @see #city_1_1() - * @see #city_1_1(long, long) - */ - public static LongHashFunction city_1_1(long seed) { - return CityHash_1_1.asLongHashFunctionWithSeed(seed); - } - - /** - * Returns a hash function implementing - * - * CityHash64 algorithm, version 1.1 using the two given seed values. This implementation - * produce equal results for equal input on platforms with different {@link ByteOrder}, but - * is slower on big-endian platforms than on little-endian. - * @return an instance of LongHashFunction - * @see #city_1_1() - * @see #city_1_1(long) - */ - public static LongHashFunction city_1_1(long seed0, long seed1) { - return CityHash_1_1.asLongHashFunctionWithTwoSeeds(seed0, seed1); - } - - private static StringHash stringHash; - static { - try { - if (System.getProperty("java.vm.name").contains("HotSpot")) { - if (System.getProperty("java.version").compareTo("1.7.0_06") >= 0) { - stringHash = ModernHotSpotStringHash.INSTANCE; - } else { - stringHash = HotSpotPrior7u6StringHash.INSTANCE; - } - } else { - // try to initialize this version anyway - stringHash = HotSpotPrior7u6StringHash.INSTANCE; - } - } catch (Throwable e) { - // ignore - } finally { - if (stringHash == null) - stringHash = UnknownJvmStringHash.INSTANCE; - } - } - - private static void checkArrayOffs(int arrayLength, int off, int len) { - if (len < 0 || off < 0 || off + len > arrayLength || off + len < 0) - throw new IndexOutOfBoundsException(); - } - - /** - * Constructor for use in subclasses. - */ - protected LongHashFunction() {} - - /** - * Returns the hash code for the given {@code long} value; this method is consistent with - * {@code LongHashFunction} methods that accept sequences of bytes, assuming the {@code input} - * value is interpreted in {@linkplain ByteOrder#nativeOrder() native} byte order. For example, - * the result of {@code hashLong(v)} call is identical to the result of - * {@code hashLongs(new long[] {v})} call for any {@code long} value. - * @param input the input - * @return a hashLong - */ - public abstract long hashLong(long input); - - /** - * Returns the hash code for the given {@code int} value; this method is consistent with - * {@code LongHashFunction} methods that accept sequences of bytes, assuming the {@code input} - * value is interpreted in {@linkplain ByteOrder#nativeOrder() native} byte order. For example, - * the result of {@code hashInt(v)} call is identical to the result of - * {@code hashInts(new int[] {v})} call for any {@code int} value. - * @param input the input - * @return a hashLong - */ - public abstract long hashInt(int input); - - /** - * Returns the hash code for the given {@code short} value; this method is consistent with - * {@code LongHashFunction} methods that accept sequences of bytes, assuming the {@code input} - * value is interpreted in {@linkplain ByteOrder#nativeOrder() native} byte order. For example, - * the result of {@code hashShort(v)} call is identical to the result of - * {@code hashShorts(new short[] {v})} call for any {@code short} value. - * As a consequence, {@code hashShort(v)} call produce always the same result as {@code - * hashChar((char) v)}. - * - * @param input the input - * @return a hashShort - */ - public abstract long hashShort(short input); - - /** - * Returns the hash code for the given {@code char} value; this method is consistent with - * {@code LongHashFunction} methods that accept sequences of bytes, assuming the {@code input} - * value is interpreted in {@linkplain ByteOrder#nativeOrder() native} byte order. For example, - * the result of {@code hashChar(v)} call is identical to the result of - * {@code hashChars(new char[] {v})} call for any {@code char} value. - * As a consequence, {@code hashChar(v)} call produce always the same result as {@code - * hashShort((short) v)}. - */ - public abstract long hashChar(char input); - - /** - * Returns the hash code for the given {@code byte} value. This method is consistent with - * {@code LongHashFunction} methods that accept sequences of bytes. For example, the result of - * {@code hashByte(v)} call is identical to the result of - * {@code hashBytes(new byte[] {v})} call for any {@code byte} value. - * - * @param input the input - * @return a hashByte - */ - public abstract long hashByte(byte input); - - /** - * Returns the hash code for the empty (zero-length) bytes sequence, - * for example {@code hashBytes(new byte[0])}. - * @return a hash - */ - public abstract long hashVoid(); - - /** - * Returns the hash code for {@code len} continuous bytes of the given {@code input} object, - * starting from the given offset. The abstraction of input as ordered byte sequence and - * "offset within the input" is defined by the given {@code access} strategy. - * - *

This method doesn't promise to throw a {@code RuntimeException} if {@code - * [off, off + len - 1]} subsequence exceeds the bounds of the bytes sequence, defined by {@code - * access} strategy for the given {@code input}, so use this method with caution. - * - * @param input the object to read bytes from - * @param access access which defines the abstraction of the given input - * as ordered byte sequence - * @param off offset to the first byte of the subsequence to hash - * @param len length of the subsequence to hash - * @param the type of the input - * @return hash code for the specified bytes subsequence - */ - public abstract long hash(T input, Access access, long off, long len); - - private long unsafeHash(Object input, long off, long len) { - return hash(input, UnsafeAccess.INSTANCE, off, len); - } - - /** - * Shortcut for {@link #hashBooleans(boolean[]) hashBooleans(new boolean[] {input})}. - * Note that this is not necessarily equal to {@code hashByte(input ? (byte) 1 : (byte) 0)}, - * because booleans could be stored differently in this JVM. - */ - public long hashBoolean(boolean input) { - return hashByte(input ? TRUE_BYTE_VALUE : FALSE_BYTE_VALUE); - } - - /** - * Shortcut for {@link #hashBooleans(boolean[], int, int) hashBooleans(input, 0, input.length)}. - */ - public long hashBooleans(@NotNull boolean[] input) { - return hashBooleans(input, 0, input.length); - } - - /** - * Returns the hash code for the specified subsequence of the given {@code boolean} array. - * - * @param input the array to read data from - * @param off index of the first {@code boolean} in the subsequence to hash - * @param len length of the subsequence to hash - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashBooleans(@NotNull boolean[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, BOOLEAN_BASE + off, len); - } - - /** - * Shortcut for {@link #hashBytes(byte[], int, int) hashBytes(input, 0, input.length)}. - */ - public long hashBytes(@NotNull byte[] input) { - return hashBytes(input, 0, input.length); - } - - /** - * Returns the hash code for the specified subsequence of the given {@code byte} array. - * - * @param input the array to read bytes from - * @param off index of the first {@code byte} in the subsequence to hash - * @param len length of the subsequence to hash - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashBytes(@NotNull byte[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, BYTE_BASE + off, len); - } - - /** - * Shortcut for {@link #hashBytes(ByteBuffer, int, int) - * hashBytes(input, input.position(), input.remaining())}. - */ - public long hashBytes(ByteBuffer input) { - return hashBytes(input, input.position(), input.remaining()); - } - - /** - * Returns the hash code for the specified subsequence of the given {@code ByteBuffer}. - * - *

This method doesn't alter the state (mark, position, limit or order) of the given - * {@code ByteBuffer}. - * - * @param input the buffer to read bytes from - * @param off index of the first {@code byte} in the subsequence to hash - * @param len length of the subsequence to hash - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.capacity()} - * or {@code len < 0} - */ - public long hashBytes(@NotNull ByteBuffer input, int off, int len) { - checkArrayOffs(input.capacity(), off, len); - return hash(input, ByteBufferAccess.INSTANCE, off, len); - } - - /** - * Shortcut for {@link #hashBytes(Bytes, long, long) - * hashBytes(input, input.position(), input.remaining())}. - */ - public long hashBytes(Bytes input) { - return hashBytes(input, input.position(), input.remaining()); - } - - /** - * Returns the hash code for the specified subsequence of the given {@code Bytes}. - * - *

This method doesn't alter the state (position or limit) of the given {@code Bytes}. - * - * @param input the {@code Bytes} to read bytes from - * @param off index of the first {@code byte} in the subsequence to hash - * @param len length of the subsequence to hash - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.capacity()} - * or {@code len < 0} - */ - public long hashBytes(Bytes input, long off, long len) { - if (len < 0 || off < 0 || off + len > input.capacity() || off + len < 0) - throw new IndexOutOfBoundsException(); - if (input instanceof NativeBytes) { - return hashMemory(input.address() + off, len); - } else { - return hash(input, toBytes(), off, len); - } - } - - /** - * Returns the hash code of bytes of the wild memory from the given address. Use with caution. - * - * @param address the address of the first byte to hash - * @param len length of the byte sequence to hash - * @return hash code for the specified byte sequence - */ - public long hashMemory(long address, long len) { - return unsafeHash(null, address, len); - } - - /** - * Shortcut for {@link #hashChars(char[], int, int) hashChars(input, 0, input.length)}. - */ - public long hashChars(@NotNull char[] input) { - return hashChars(input, 0, input.length); - } - - /** - * Returns the hash code for bytes, as they lay in memory, of the specified subsequence - * of the given {@code char} array. - * - * @param input the array to read data from - * @param off index of the first {@code char} in the subsequence to hash - * @param len length of the subsequence to hash, in chars (i. e. the length of the bytes - * sequence to hash is {@code len * 2L}) - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashChars(@NotNull char[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, CHAR_BASE + (off * 2L), len * 2L); - } - - /** - * Shortcut for {@link #hashChars(String, int, int) hashChars(input, 0, input.length())}.* - */ - public long hashChars(@NotNull String input) { - return stringHash.longHash(input, this, 0, input.length()); - } - - /** - * Returns the hash code for bytes of the specified subsequence of the given {@code String}'s - * underlying {@code char} array. - * - * @param input the string which bytes to hash - * @param off index of the first {@code char} in the subsequence to hash - * @param len length of the subsequence to hash, in chars (i. e. the length of the bytes - * sequence to hash is {@code len * 2L}) - * @return the hash code of the given {@code String}'s bytes - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length()} - * or {@code len < 0} - */ - public long hashChars(@NotNull String input, int off, int len) { - checkArrayOffs(input.length(), off, len); - return stringHash.longHash(input, this, off, len); - } - - /** - * Shortcut for {@link #hashChars(StringBuilder, int, int) hashChars(input, 0, input.length())}. - */ - public long hashChars(@NotNull StringBuilder input) { - return hashNativeChars(input); - } - - /** - * Returns the hash code for bytes of the specified subsequence of the given - * {@code StringBuilder}'s underlying {@code char} array. - * - * @param input the string builder which bytes to hash - * @param off index of the first {@code char} in the subsequence to hash - * @param len length of the subsequence to hash, in chars (i. e. the length of the bytes - * sequence to hash is {@code len * 2L}) - * @return the hash code of the given {@code String}'s bytes - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length()} - * or {@code len < 0} - */ - public long hashChars(@NotNull StringBuilder input, int off, int len) { - return hashNativeChars(input, off, len); - } - - long hashNativeChars(CharSequence input) { - return hashNativeChars(input, 0, input.length()); - } - - long hashNativeChars(CharSequence input, int off, int len) { - checkArrayOffs(input.length(), off, len); - return hash(input, nativeCharSequenceAccess(), off * 2L, len * 2L); - } - - /** - * Shortcut for {@link #hashShorts(short[], int, int) hashShorts(input, 0, input.length)}. - */ - public long hashShorts(@NotNull short[] input) { - return hashShorts(input, 0, input.length); - } - - /** - * Returns the hash code for bytes, as they lay in memory, of the specified subsequence - * of the given {@code short} array. - * - * @param input the array to read data from - * @param off index of the first {@code short} in the subsequence to hash - * @param len length of the subsequence to hash, in shorts (i. e. the length of the bytes - * sequence to hash is {@code len * 2L}) - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashShorts(@NotNull short[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, SHORT_BASE + (off * 2L), len * 2L); - } - - /** - * Shortcut for {@link #hashInts(int[], int, int) hashInts(input, 0, input.length)}. - */ - public long hashInts(@NotNull int[] input) { - return hashInts(input, 0, input.length); - } - - /** - * Returns the hash code for bytes, as they lay in memory, of the specified subsequence - * of the given {@code int} array. - * - * @param input the array to read data from - * @param off index of the first {@code int} in the subsequence to hash - * @param len length of the subsequence to hash, in ints (i. e. the length of the bytes - * sequence to hash is {@code len * 4L}) - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashInts(@NotNull int[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, INT_BASE + (off * 4L), len * 4L); - } - - /** - * Shortcut for {@link #hashLongs(long[], int, int) hashLongs(input, 0, input.length)}. - */ - public long hashLongs(@NotNull long[] input) { - return hashLongs(input, 0, input.length); - } - - /** - * Returns the hash code for bytes, as they lay in memory, of the specified subsequence - * of the given {@code long} array. - * - * @param input the array to read data from - * @param off index of the first {@code long} in the subsequence to hash - * @param len length of the subsequence to hash, in longs (i. e. the length of the bytes - * sequence to hash is {@code len * 8L}) - * @return hash code for the specified subsequence - * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} - * or {@code len < 0} - */ - public long hashLongs(@NotNull long[] input, int off, int len) { - checkArrayOffs(input.length, off, len); - return unsafeHash(input, LONG_BASE + (off * 8L), len * 8L); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/ModernHotSpotStringHash.java b/src/main/java/net/openhft/chronicle/hash/hashing/ModernHotSpotStringHash.java deleted file mode 100644 index 91ae8e2d0..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/ModernHotSpotStringHash.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.hash.hashing; - -import java.lang.reflect.Field; - -enum ModernHotSpotStringHash implements StringHash { - INSTANCE; - - private static final long valueOffset; - - static { - try { - Field valueField = String.class.getDeclaredField("value"); - valueOffset = UnsafeAccess.UNSAFE.objectFieldOffset(valueField); - } catch (NoSuchFieldException e) { - throw new AssertionError(e); - } - } - - @Override - public long longHash(String s, LongHashFunction hashFunction, int off, int len) { - char[] value = (char[]) UnsafeAccess.UNSAFE.getObject(s, valueOffset); - return hashFunction.hashChars(value, off, len); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/StringHash.java b/src/main/java/net/openhft/chronicle/hash/hashing/StringHash.java deleted file mode 100644 index 9d238689d..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/StringHash.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.hash.hashing; - -interface StringHash { - - long longHash(String s, LongHashFunction hashFunction, int off, int len); -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/UnknownJvmStringHash.java b/src/main/java/net/openhft/chronicle/hash/hashing/UnknownJvmStringHash.java deleted file mode 100644 index 834c3fa34..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/UnknownJvmStringHash.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.hash.hashing; - -enum UnknownJvmStringHash implements StringHash { - INSTANCE; - - @Override - public long longHash(String s, LongHashFunction hashFunction, int off, int len) { - return hashFunction.hashNativeChars(s, off, len); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/UnsafeAccess.java b/src/main/java/net/openhft/chronicle/hash/hashing/UnsafeAccess.java deleted file mode 100644 index e68e6a46a..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/UnsafeAccess.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.hash.hashing; - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.nio.ByteOrder; - -import static net.openhft.chronicle.hash.hashing.Primitives.*; - -final class UnsafeAccess extends Access { - public static final UnsafeAccess INSTANCE = new UnsafeAccess(); - - static final Unsafe UNSAFE; - static final long BOOLEAN_BASE; - static final long BYTE_BASE; - static final long CHAR_BASE; - static final long SHORT_BASE; - static final long INT_BASE; - static final long LONG_BASE; - - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(null); - BOOLEAN_BASE = UNSAFE.arrayBaseOffset(boolean[].class); - BYTE_BASE = UNSAFE.arrayBaseOffset(byte[].class); - CHAR_BASE = UNSAFE.arrayBaseOffset(char[].class); - SHORT_BASE = UNSAFE.arrayBaseOffset(short[].class); - INT_BASE = UNSAFE.arrayBaseOffset(int[].class); - LONG_BASE = UNSAFE.arrayBaseOffset(long[].class); - } catch (Exception e) { - throw new AssertionError(e); - } - } - - private UnsafeAccess() {} - - @Override - public long getLong(Object input, long offset) { - return UNSAFE.getLong(input, offset); - } - - @Override - public long getUnsignedInt(Object input, long offset) { - return unsignedInt(getInt(input, offset)); - } - - @Override - public int getInt(Object input, long offset) { - return UNSAFE.getInt(input, offset); - } - - @Override - public int getUnsignedShort(Object input, long offset) { - return unsignedShort(getShort(input, offset)); - } - - @Override - public int getShort(Object input, long offset) { - return UNSAFE.getShort(input, offset); - } - - @Override - public int getUnsignedByte(Object input, long offset) { - return unsignedByte(getByte(input, offset)); - } - - @Override - public int getByte(Object input, long offset) { - return UNSAFE.getByte(input, offset); - } - - @Override - public ByteOrder byteOrder(Object input) { - return ByteOrder.nativeOrder(); - } - -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/package-info.java b/src/main/java/net/openhft/chronicle/hash/hashing/package-info.java deleted file mode 100644 index a2c0c0bd5..000000000 --- a/src/main/java/net/openhft/chronicle/hash/hashing/package-info.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 . - */ - -/** - * API for hashing sequential data and zero-allocation, pretty fast implementations - * of non-cryptographic hash functions. - * - *

Available implementations: - *

    - *
  • {@code long}-valued functions: see - * {@link net.openhft.chronicle.hash.hashing.LongHashFunction} - *
      - *
    • CityHash 1.1: - * {@linkplain net.openhft.chronicle.hash.hashing.LongHashFunction#city_1_1() without - * seeds}, - * {@linkplain net.openhft.chronicle.hash.hashing.LongHashFunction#city_1_1(long) - * with one seed}, - * {@linkplain net.openhft.chronicle.hash.hashing.LongHashFunction#city_1_1(long, long) - * with two seeds}. - *
    • - *
    - *
  • - *
- */ -package net.openhft.chronicle.hash.hashing; \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java b/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java index 0630d53f2..b99e57833 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java @@ -16,18 +16,19 @@ package net.openhft.chronicle.hash.impl; +import net.openhft.chronicle.core.OS; import net.openhft.chronicle.hash.locks.IllegalInterProcessLockStateException; import java.util.concurrent.TimeUnit; import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.nio.ByteOrder.nativeOrder; -import static net.openhft.lang.io.AbstractBytes.UNSIGNED_INT_MASK; -import static net.openhft.lang.io.NativeBytes.UNSAFE; public final class BigSegmentHeader implements SegmentHeader { public static final BigSegmentHeader INSTANCE = new BigSegmentHeader(); + private static final long UNSIGNED_INT_MASK = 0xFFFFFFFFL; + static final long LOCK_OFFSET = 0L; // 64-bit static final long COUNT_WORD_OFFSET = LOCK_OFFSET; static final long WAIT_WORD_OFFSET = LOCK_OFFSET + 4L; @@ -61,7 +62,7 @@ public final class BigSegmentHeader implements SegmentHeader { @Override public long size(long address) { - return UNSAFE.getInt(address + SIZE_OFFSET) & UNSIGNED_INT_MASK; + return OS.memory().readInt(address + SIZE_OFFSET) & UNSIGNED_INT_MASK; } @Override @@ -70,12 +71,12 @@ public final class BigSegmentHeader implements SegmentHeader { throw new IllegalStateException("segment size overflow: up to " + UNSIGNED_INT_MASK + " supported, " + size + " given"); } - UNSAFE.putInt(address + SIZE_OFFSET, (int) size); + OS.memory().writeInt(address + SIZE_OFFSET, (int) size); } @Override public long deleted(long address) { - return UNSAFE.getInt(address + DELETED_OFFSET) & UNSIGNED_INT_MASK; + return OS.memory().readInt(address + DELETED_OFFSET) & UNSIGNED_INT_MASK; } @Override @@ -84,25 +85,25 @@ public final class BigSegmentHeader implements SegmentHeader { throw new IllegalStateException("segment deleted entries count overflow: up to " + UNSIGNED_INT_MASK + " supported, " + deleted + " given"); } - UNSAFE.putInt(address + DELETED_OFFSET, (int) deleted); + OS.memory().writeInt(address + DELETED_OFFSET, (int) deleted); } @Override public long nextPosToSearchFrom(long address) { - return UNSAFE.getInt(address + NEXT_POS_TO_SEARCH_FROM_OFFSET) & UNSIGNED_INT_MASK; + return OS.memory().readInt(address + NEXT_POS_TO_SEARCH_FROM_OFFSET) & UNSIGNED_INT_MASK; } @Override public void nextPosToSearchFrom(long address, long nextPosToSearchFrom) { - UNSAFE.putInt(address + NEXT_POS_TO_SEARCH_FROM_OFFSET, (int) nextPosToSearchFrom); + OS.memory().writeInt(address + NEXT_POS_TO_SEARCH_FROM_OFFSET, (int) nextPosToSearchFrom); } private static long getLockWord(long address) { - return UNSAFE.getLongVolatile(null, address + LOCK_OFFSET); + return OS.memory().readVolatileLong(null, address + LOCK_OFFSET); } private static boolean casLockWord(long address, long expected, long x) { - return UNSAFE.compareAndSwapLong(null, address + LOCK_OFFSET, expected, x); + return OS.memory().compareAndSwapLong(null, address + LOCK_OFFSET, expected, x); } private static int countWord(long lockWord) { @@ -119,15 +120,15 @@ public final class BigSegmentHeader implements SegmentHeader { } private static int getCountWord(long address) { - return UNSAFE.getIntVolatile(null, address + COUNT_WORD_OFFSET); + return OS.memory().readVolatileInt(null, address + COUNT_WORD_OFFSET); } private static boolean casCountWord(long address, int expected, int x) { - return UNSAFE.compareAndSwapInt(null, address + COUNT_WORD_OFFSET, expected, x); + return OS.memory().compareAndSwapInt(null, address + COUNT_WORD_OFFSET, expected, x); } private static void putCountWord(long address, int countWord) { - UNSAFE.putOrderedInt(null, address + COUNT_WORD_OFFSET, countWord); + OS.memory().writeOrderedInt(null, address + COUNT_WORD_OFFSET, countWord); } private static boolean writeLocked(int countWord) { @@ -165,11 +166,11 @@ public final class BigSegmentHeader implements SegmentHeader { } private static int getWaitWord(long address) { - return UNSAFE.getIntVolatile(null, address + WAIT_WORD_OFFSET); + return OS.memory().readVolatileInt(null, address + WAIT_WORD_OFFSET); } private static boolean casWaitWord(long address, int expected, int x) { - return UNSAFE.compareAndSwapInt(null, address + WAIT_WORD_OFFSET, expected, x); + return OS.memory().compareAndSwapInt(null, address + WAIT_WORD_OFFSET, expected, x); } private static void checkWaitWordForIncrement(int waitWord) { @@ -187,19 +188,19 @@ public final class BigSegmentHeader implements SegmentHeader { } private static void writeExclusiveLockHolder(long address) { - UNSAFE.putLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET, + OS.memory().writeLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET, Thread.currentThread().getId()); } private static void clearExclusiveLockHolder(long address) { - UNSAFE.putLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET, 0L); + OS.memory().writeLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET, 0L); } /** * For debugging and monitoring */ static Thread exclusiveLockHolder(long address) { - long holderId = UNSAFE.getLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET); + long holderId = OS.memory().readLong(address + EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET); if (holderId == 0L) return null; Thread[] threads = new Thread[Thread.activeCount()]; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java index 5a1ae852c..d05b78210 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java @@ -19,8 +19,8 @@ package net.openhft.chronicle.hash.impl; import net.openhft.chronicle.core.Maths; -import static net.openhft.lang.MemoryUnit.BITS; -import static net.openhft.lang.MemoryUnit.BYTES; +import static net.openhft.chronicle.algo.MemoryUnit.BITS; +import static net.openhft.chronicle.algo.MemoryUnit.BYTES; public abstract class CompactOffHeapLinearHashTable { // to fit 64 bits per slot. diff --git a/src/main/java/net/openhft/chronicle/hash/impl/CopyingInstanceData.java b/src/main/java/net/openhft/chronicle/hash/impl/CopyingInstanceData.java deleted file mode 100644 index a26f5f14e..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/CopyingInstanceData.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.hash.impl; - -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.lang.io.DirectBytes; -import net.openhft.lang.io.DirectStore; -import net.openhft.lang.io.serialization.JDKObjectSerializer; - -public abstract class CopyingInstanceData extends AbstractData { - - private final JavaLangBytesReusableBytesStore bytesStore = - new JavaLangBytesReusableBytesStore(); - - public DirectBytes getBuffer(DirectBytes b, long capacity) { - if (b != null) { - if (b.capacity() >= capacity) { - return (DirectBytes) b.clear(); - } else { - DirectStore store = (DirectStore) b.store(); - store.resize(capacity, false); - DirectBytes bytes = store.bytes(); - bytesStore.setBytes(bytes); - return bytes; - } - } else { - DirectBytes bytes = new DirectStore(JDKObjectSerializer.INSTANCE, - Math.max(1, capacity), true).bytes(); - bytesStore.setBytes(bytes); - return bytes; - } - } - - @Override - public RandomDataInput bytes() { - return bytesStore; - } - - public abstract I instance(); - - public abstract DirectBytes buffer(); - - @Override - public long offset() { - return 0; - } - - @Override - public long size() { - return buffer().limit(); - } - - @Override - public I get() { - return instance(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/hashing/Primitives.java b/src/main/java/net/openhft/chronicle/hash/impl/DummyReferenceCounted.java similarity index 66% rename from src/main/java/net/openhft/chronicle/hash/hashing/Primitives.java rename to src/main/java/net/openhft/chronicle/hash/impl/DummyReferenceCounted.java index 6f26dce82..20e4a8420 100644 --- a/src/main/java/net/openhft/chronicle/hash/hashing/Primitives.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/DummyReferenceCounted.java @@ -14,21 +14,23 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.hash.hashing; +package net.openhft.chronicle.hash.impl; -final class Primitives { +import net.openhft.chronicle.core.ReferenceCounted; - private Primitives() {} +public enum DummyReferenceCounted implements ReferenceCounted { + DUMMY_REFERENCE_COUNTED; - static long unsignedInt(int i) { - return i & 0xFFFFFFFFL; + @Override + public void reserve() throws IllegalStateException { } - static int unsignedShort(int s) { - return s & 0xFFFF; + @Override + public void release() throws IllegalStateException { } - static int unsignedByte(int b) { - return b & 0xFF; + @Override + public long refCount() { + return 0; } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java b/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java index c17f95906..66488934e 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/HashSplitting.java @@ -18,14 +18,14 @@ package net.openhft.chronicle.hash.impl; import java.io.Serializable; -import static net.openhft.lang.Maths.isPowerOf2; +import static net.openhft.chronicle.core.Maths.isPowerOf2; public interface HashSplitting extends Serializable { int segmentIndex(long hash); long segmentHash(long hash); - static class Splitting { + class Splitting { static HashSplitting forSegments(int segments) { assert segments > 0; if (segments == 1) @@ -50,7 +50,7 @@ public interface HashSplitting extends Serializable { } } - static class ForPowerOf2Segments implements HashSplitting { + class ForPowerOf2Segments implements HashSplitting { private static final long serialVersionUID = 0L; private final int mask; @@ -73,7 +73,7 @@ public interface HashSplitting extends Serializable { } //TODO optimize? - static class ForNonPowerOf2Segments implements HashSplitting { + class ForNonPowerOf2Segments implements HashSplitting { private static final long serialVersionUID = 0L; private static final int MASK = Integer.MAX_VALUE; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/IntCompactOffHeapLinearHashTable.java b/src/main/java/net/openhft/chronicle/hash/impl/IntCompactOffHeapLinearHashTable.java index 0f3a73b68..778220add 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/IntCompactOffHeapLinearHashTable.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/IntCompactOffHeapLinearHashTable.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.hash.impl; -import static net.openhft.lang.io.NativeBytes.UNSAFE; +import net.openhft.chronicle.core.OS; public final class IntCompactOffHeapLinearHashTable extends CompactOffHeapLinearHashTable { @@ -43,21 +43,21 @@ public final class IntCompactOffHeapLinearHashTable extends CompactOffHeapLinear @Override public long readEntry(long addr, long pos) { - return UNSAFE.getInt(addr + pos); + return OS.memory().readInt(addr + pos); } @Override public void writeEntryVolatile(long addr, long pos, long prevEntry, long key, long value) { - UNSAFE.putIntVolatile(null, addr + pos, (int) entry(key, value)); + OS.memory().writeVolatileInt(null, addr + pos, (int) entry(key, value)); } @Override void writeEntry(long addr, long pos, long prevEntry, long anotherEntry) { - UNSAFE.putInt(addr + pos, (int) anotherEntry); + OS.memory().writeInt(addr + pos, (int) anotherEntry); } @Override void clearEntry(long addr, long pos, long prevEntry) { - UNSAFE.putInt(addr + pos, 0); + OS.memory().writeInt(addr + pos, 0); } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/JavaLangBytesReusableBytesStore.java b/src/main/java/net/openhft/chronicle/hash/impl/JavaLangBytesReusableBytesStore.java deleted file mode 100644 index 54273a235..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/JavaLangBytesReusableBytesStore.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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.hash.impl; - -import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.core.OS; -import net.openhft.lang.io.Bytes; - -import java.nio.ByteBuffer; - -public class JavaLangBytesReusableBytesStore - implements BytesStore { - - private Bytes bytes; - - public void setBytes(Bytes bytes) { - this.bytes = bytes; - } - - @Override - public BytesStore copy() { - throw new UnsupportedOperationException(); - } - - @Override - public long capacity() { - return bytes.capacity(); - } - - @Override - public long address(long offset) throws UnsupportedOperationException { - return bytes.address() + offset; - } - - @Override - public Void underlyingObject() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean compareAndSwapInt(long offset, int expected, int value) { - return bytes.compareAndSwapInt(offset, expected, value); - } - - @Override - public boolean compareAndSwapLong(long offset, long expected, long value) { - return bytes.compareAndSwapLong(offset, expected, value); - } - - @Override - public byte readByte(long offset) { - return bytes.readByte(offset); - } - - @Override - public short readShort(long offset) { - return bytes.readShort(offset); - } - - @Override - public int readInt(long offset) { - return bytes.readInt(offset); - } - - @Override - public long readLong(long offset) { - return bytes.readLong(offset); - } - - @Override - public float readFloat(long offset) { - return bytes.readFloat(offset); - } - - @Override - public double readDouble(long offset) { - return bytes.readDouble(offset); - } - - @Override - public void nativeRead(long position, long address, long size) { - throw new UnsupportedOperationException(); - } - - @Override - public JavaLangBytesReusableBytesStore writeByte(long offset, byte i8) { - bytes.writeByte(offset, i8); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeShort(long offset, short i) { - bytes.writeShort(offset, i); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeInt(long offset, int i) { - bytes.writeInt(offset, i); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeOrderedInt(long offset, int i) { - bytes.writeOrderedInt(offset, i); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeLong(long offset, long i) { - bytes.writeLong(offset, i); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeOrderedLong(long offset, long i) { - bytes.writeOrderedLong(offset, i); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeFloat(long offset, float d) { - bytes.writeFloat(offset, d); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeDouble(long offset, double d) { - bytes.writeDouble(offset, d); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeVolatileByte(long offset, byte i8) { - OS.memory().storeFence(); - bytes.writeByte(offset, i8); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeVolatileShort(long offset, short i16) { - OS.memory().storeFence(); - bytes.writeShort(offset, i16); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeVolatileInt(long offset, int i32) { - OS.memory().storeFence(); - bytes.writeInt(offset, i32); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore writeVolatileLong(long offset, long i64) { - OS.memory().storeFence(); - bytes.writeLong(offset, i64); - return this; - } - - @Override - public JavaLangBytesReusableBytesStore write(long offsetInRDO, - byte[] bs, int offset, int length) { - bytes.write(offsetInRDO, bs, offset, length); - return this; - } - - @Override - public void write(long offsetInRDO, ByteBuffer bb, int offset, int length) { - throw new UnsupportedOperationException(); - } - - @Override - public JavaLangBytesReusableBytesStore write(long offsetInRDO, - RandomDataInput input, long offset, long length) { - throw new UnsupportedOperationException(); - } - - @Override - public void nativeWrite(long address, long position, long size) { - throw new UnsupportedOperationException(); - } - - @Override - public void reserve() throws IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void release() throws IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public long refCount() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/LongCompactOffHeapLinearHashTable.java b/src/main/java/net/openhft/chronicle/hash/impl/LongCompactOffHeapLinearHashTable.java index c15ba3f83..07735444c 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/LongCompactOffHeapLinearHashTable.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/LongCompactOffHeapLinearHashTable.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.hash.impl; -import static net.openhft.lang.io.NativeBytes.UNSAFE; +import net.openhft.chronicle.core.OS; public final class LongCompactOffHeapLinearHashTable extends CompactOffHeapLinearHashTable { @@ -43,21 +43,21 @@ public final class LongCompactOffHeapLinearHashTable extends CompactOffHeapLinea @Override public long readEntry(long addr, long pos) { - return UNSAFE.getLong(addr + pos); + return OS.memory().readLong(addr + pos); } @Override public void writeEntryVolatile(long addr, long pos, long prevEntry, long key, long value) { - UNSAFE.putLongVolatile(null, addr + pos, entry(key, value)); + OS.memory().writeVolatileLong(null, addr + pos, entry(key, value)); } @Override void writeEntry(long addr, long pos, long prevEntry, long anotherEntry) { - UNSAFE.putLong(addr + pos, anotherEntry); + OS.memory().writeLong(addr + pos, anotherEntry); } @Override void clearEntry(long addr, long pos, long prevEntry) { - UNSAFE.putLong(addr + pos, 0L); + OS.memory().writeLong(addr + pos, 0L); } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/PublicMultiStoreBytes.java b/src/main/java/net/openhft/chronicle/hash/impl/PublicMultiStoreBytes.java deleted file mode 100644 index 389b0c506..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/PublicMultiStoreBytes.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.hash.impl; - -import net.openhft.lang.io.MultiStoreBytes; - -/** - * This awful class is made for "conversion" from new ch.bytes.Bytes to old lang.io.Bytes - * - * TODO remove when Bytes system stabilize - */ -public class PublicMultiStoreBytes extends MultiStoreBytes { - public void startAddr(long startAddr) { this.startAddr = startAddr; } - public void positionAddr(long positionAddr) { this.positionAddr = positionAddr; } - public void limitAddr(long limitAddr) { this.limitAddr = limitAddr; } - public void capacityAddr(long capacityAddr) { this.capacityAddr = capacityAddr; } -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/TierCountersArea.java b/src/main/java/net/openhft/chronicle/hash/impl/TierCountersArea.java index 414c4ce6a..b59c612d8 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/TierCountersArea.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/TierCountersArea.java @@ -16,7 +16,8 @@ package net.openhft.chronicle.hash.impl; -import static net.openhft.lang.io.NativeBytes.UNSAFE; +import net.openhft.chronicle.core.Memory; +import net.openhft.chronicle.core.OS; /** * The reason why this is not a data value generated class, and offsets are allocated by @@ -27,6 +28,7 @@ import static net.openhft.lang.io.NativeBytes.UNSAFE; public enum TierCountersArea { ; + private static Memory memory = OS.memory(); public static final long NEXT_TIER_INDEX_OFFSET = 0L; public static final long PREV_TIER_INDEX_OFFSET = NEXT_TIER_INDEX_OFFSET + 8L; public static final long NEXT_POS_TO_SEARCH_FROM_TIERED_OFFSET = PREV_TIER_INDEX_OFFSET + 8L; @@ -34,43 +36,43 @@ public enum TierCountersArea { public static final long TIER_OFFSET = SEGMENT_INDEX_OFFSET + 4L; public static long nextTierIndex(long address) { - return UNSAFE.getLong(address + NEXT_TIER_INDEX_OFFSET); + return memory.readLong(address + NEXT_TIER_INDEX_OFFSET); } public static void nextTierIndex(long address, long nextTierIndex) { - UNSAFE.putLong(address + NEXT_TIER_INDEX_OFFSET, nextTierIndex); + memory.writeLong(address + NEXT_TIER_INDEX_OFFSET, nextTierIndex); } public static long nextPosToSearchFromTiered(long address) { - return UNSAFE.getLong(address + NEXT_POS_TO_SEARCH_FROM_TIERED_OFFSET); + return memory.readLong(address + NEXT_POS_TO_SEARCH_FROM_TIERED_OFFSET); } public static void nextPosToSearchFromTiered(long address, long nextPosToSearchFrom) { - UNSAFE.putLong(address + NEXT_POS_TO_SEARCH_FROM_TIERED_OFFSET, + memory.writeLong(address + NEXT_POS_TO_SEARCH_FROM_TIERED_OFFSET, nextPosToSearchFrom); } public static long prevTierIndex(long address) { - return UNSAFE.getLong(address + PREV_TIER_INDEX_OFFSET); + return memory.readLong(address + PREV_TIER_INDEX_OFFSET); } public static void prevTierIndex(long address, long prevTierIndex) { - UNSAFE.putLong(address + PREV_TIER_INDEX_OFFSET, prevTierIndex); + memory.writeLong(address + PREV_TIER_INDEX_OFFSET, prevTierIndex); } public static int segmentIndex(long address) { - return UNSAFE.getInt(address + SEGMENT_INDEX_OFFSET); + return memory.readInt(address + SEGMENT_INDEX_OFFSET); } public static void segmentIndex(long address, int segmentIndex) { - UNSAFE.putInt(address + SEGMENT_INDEX_OFFSET, segmentIndex); + memory.writeInt(address + SEGMENT_INDEX_OFFSET, segmentIndex); } public static int tier(long address) { - return UNSAFE.getInt(address + TIER_OFFSET); + return memory.readInt(address + TIER_OFFSET); } public static void tier(long address, int tier) { - UNSAFE.putInt(address + TIER_OFFSET, tier); + memory.writeInt(address + TIER_OFFSET, tier); } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 3780f0e3e..3142e6d88 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -18,28 +18,22 @@ package net.openhft.chronicle.hash.impl; import net.openhft.chronicle.algo.bytes.Access; import net.openhft.chronicle.algo.locks.*; +import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.bytes.NativeBytesStore; import net.openhft.chronicle.core.Maths; import net.openhft.chronicle.core.OS; import net.openhft.chronicle.hash.*; import net.openhft.chronicle.hash.impl.util.BuildVersion; -import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.hash.serialization.internal.MetaProvider; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.io.*; -import net.openhft.lang.io.serialization.BytesMarshallableSerializer; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.threadlocal.Provider; +import net.openhft.chronicle.values.Values; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; +import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; @@ -48,10 +42,14 @@ import java.util.concurrent.TimeUnit; import static java.lang.Long.numberOfTrailingZeros; import static java.lang.Math.max; +import static java.nio.channels.FileChannel.MapMode.READ_WRITE; +import static net.openhft.chronicle.algo.MemoryUnit.*; +import static net.openhft.chronicle.bytes.NativeBytesStore.lazyNativeBytesStoreWithFixedCapacity; +import static net.openhft.chronicle.core.OS.pageAlign; import static net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable.*; -import static net.openhft.lang.MemoryUnit.*; +import static net.openhft.chronicle.hash.impl.DummyReferenceCounted.DUMMY_REFERENCE_COUNTED; -public abstract class VanillaChronicleHash, +public abstract class VanillaChronicleHash, SC extends HashSegmentContext, ECQ extends ExternalHashQueryContext> implements ChronicleHash, Serializable { @@ -75,13 +73,12 @@ public abstract class VanillaChronicleHash kClass; public final SizeMarshaller keySizeMarshaller; - public final BytesReader originalKeyReader; - public final KI originalKeyInterop; - public final MKI originalMetaKeyInterop; - public final MetaProvider metaKeyInteropProvider; + public final SizedReader originalKeyReader; + public final DataAccess originalKeyDataAccess; - public transient Provider> keyReaderProvider; - public transient Provider keyInteropProvider; + ///////////////////////////////////////////////// + // Checksum entries + public final boolean checksumEntries; ///////////////////////////////////////////////// // Concurrency (number of segments), memory management and dependent fields @@ -120,31 +117,22 @@ public abstract class VanillaChronicleHash( - langBytes.address(), langBytes.capacity(), null, false); + public TierBulkData(BytesStore bytesStore, long offset) { + this.bytesStore = bytesStore; this.offset = offset; } public TierBulkData(TierBulkData data, long offset) { - this.langBytesStore = data.langBytesStore; - this.langBytes = data.langBytes; - this.chBytesBytesStore = data.chBytesBytesStore; + this.bytesStore = data.bytesStore; this.offset = offset; } } @@ -157,7 +145,7 @@ public abstract class VanillaChronicleHash keyBuilder = privateAPI.keyBuilder(); - kClass = keyBuilder.eClass; + kClass = keyBuilder.tClass; keySizeMarshaller = keyBuilder.sizeMarshaller(); originalKeyReader = keyBuilder.reader(); - originalKeyInterop = (KI) keyBuilder.interop(); - originalMetaKeyInterop = (MKI) keyBuilder.metaInterop(); - metaKeyInteropProvider = (MetaProvider) keyBuilder.metaInteropProvider(); + originalKeyDataAccess = keyBuilder.dataAccess(); actualSegments = privateAPI.actualSegments(); hashSplitting = HashSplitting.Splitting.forSegments(actualSegments); @@ -226,7 +212,7 @@ public abstract class VanillaChronicleHash(); - keyReaderProvider = Provider.of((Class) originalKeyReader.getClass()); - keyInteropProvider = Provider.of((Class) originalKeyInterop.getClass()); if (segmentHashLookupEntrySize == 4) { hashLookup = new IntCompactOffHeapLinearHashTable(this); } else if (segmentHashLookupEntrySize == 8) { @@ -296,10 +280,12 @@ public abstract class VanillaChronicleHash 0) { appendBulkData(0, globalMutableState.getAllocatedExtraTierBulks() - 1, - ms, sizeInBytesWithoutTiers()); + bs, sizeInBytesWithoutTiers()); } } } @@ -337,13 +327,16 @@ public abstract class VanillaChronicleHash 0) { globalMutableState.setExtraTiersInUse(tiersInUse + 1); - Bytes allocatedTierBytes = tierBytes(firstFreeTierIndex); + BytesStore allocatedTierBytes = tierBytesStore(firstFreeTierIndex); long allocatedTierOffset = tierBytesOffset(firstFreeTierIndex); - long tierBaseAddr = allocatedTierBytes.address() + allocatedTierOffset; + long tierBaseAddr = allocatedTierBytes.address(0) + allocatedTierOffset; long tierCountersAreaAddr = tierBaseAddr + segmentHashLookupOuterSize; long nextFreeTierIndex = TierCountersArea.nextTierIndex(tierCountersAreaAddr); // now, when this tier will be a part of the map, the next tier designates @@ -595,21 +579,21 @@ public abstract class VanillaChronicleHash 0) { // These bytes are bit sets in Replicated version - bytes.zeroOut(firstTierOffset - tierBulkInnerOffsetToTiers, firstTierOffset); + tierBytesStore.zeroOut(firstTierOffset - tierBulkInnerOffsetToTiers, firstTierOffset); } // Link newly allocated tiers into free tiers list long lastTierIndex = firstTierIndex + tiersInBulk - 1; for (long tierIndex = firstTierIndex; tierIndex <= lastTierIndex; tierIndex++) { long tierOffset = tierBytesOffset(tierIndex); - zeroOutNewlyMappedTier(bytes, tierOffset); + zeroOutNewlyMappedTier(tierBytesStore, tierOffset); if (tierIndex < lastTierIndex) { long tierCountersAreaOffset = tierOffset + segmentHashLookupOuterSize; - TierCountersArea.nextTierIndex(bytes.address() + tierCountersAreaOffset, + TierCountersArea.nextTierIndex(tierBytesStore.address(0) + tierCountersAreaOffset, tierIndex + 1); } } @@ -630,11 +614,11 @@ public abstract class VanillaChronicleHash> { - VanillaChronicleHash h(); +public interface VanillaChronicleHashHolder { + VanillaChronicleHash h(); } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java index 7b00d8376..65b20a8c2 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.hash.impl.stage.data.bytes; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; @@ -29,7 +30,7 @@ import net.openhft.sg.Staged; @Staged public class EntryKeyBytesData extends AbstractData { - @StageRef KeyBytesInterop ki; + @StageRef KeyBytesInterop ki; @StageRef SegmentStages s; @StageRef HashEntryStages entry; @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; @@ -68,13 +69,14 @@ public class EntryKeyBytesData extends AbstractData { } @Override - public K getUsing(K usingKey) { + public K getUsing(K using) { checkOnEachPublicOperation.checkOnEachPublicOperation(); - return innerGetUsing(usingKey); + return innerGetUsing(using); } private K innerGetUsing(K usingKey) { - s.segmentBytes.position(entry.keyOffset); - return ki.keyReader.read(s.segmentBytes, size(), usingKey); + Bytes bytes = s.segmentBytesForRead(); + bytes.readPosition(entry.keyOffset); + return ki.keyReader.read(bytes, size(), usingKey); } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java deleted file mode 100644 index 8f74c88d9..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.hash.impl.stage.data.bytes; - -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - - -@Staged -public class InputKeyBytesData extends AbstractData { - @StageRef HashInputBytes in; - @StageRef KeyBytesInterop ki; - - @Stage("CachedBytesInputKey") private K cachedBytesInputKey; - @Stage("CachedBytesInputKey") private boolean cachedBytesInputKeyRead = false; - - private void initCachedBytesInputKey() { - cachedBytesInputKey = getUsing(cachedBytesInputKey); - cachedBytesInputKeyRead = true; - } - - @Override - public RandomDataInput bytes() { - return in.inputStore; - } - - @Override - public long offset() { - return in.inputKeyOffset; - } - - @Override - public long size() { - return in.inputKeySize; - } - - @Override - public K get() { - return cachedBytesInputKey; - } - - @Override - public K getUsing(K usingKey) { - Bytes inputBytes = in.inputBytes; - inputBytes.position(in.inputKeyOffset); - return ki.keyReader.read(inputBytes, size(), usingKey); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java deleted file mode 100644 index 8d2bb2aa8..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.hash.impl.stage.data.instance; - -import net.openhft.chronicle.hash.impl.CopyingInstanceData; -import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; -import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.lang.io.DirectBytes; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public abstract class InputKeyInstanceData> - extends CopyingInstanceData implements KeyInitableData { - - @StageRef KeyBytesInterop ki; - - private K key = null; - - @Override - public void initKey(K key) { - this.key = key; - } - - @Override - public K instance() { - return key; - } - - @Stage("Buffer") private DirectBytes buffer; - @Stage("Buffer") private boolean marshalled = false; - - private void initBuffer() { - MKI mki = ki.keyMetaInterop(key); - long size = mki.size(ki.keyInterop, key); - buffer = getBuffer(this.buffer, size); - mki.write(ki.keyInterop, buffer, key); - buffer.flip(); - marshalled = true; - } - - @Override - public K getUsing(K usingKey) { - buffer.position(0); - return ki.keyReader.read(buffer, buffer.limit(), usingKey); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java index 268946336..322a3895a 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java @@ -23,7 +23,7 @@ import net.openhft.sg.Staged; @Staged public class AllocatedChunks { - @StageRef public VanillaChronicleHashHolder hh; + @StageRef public VanillaChronicleHashHolder hh; @StageRef public SegmentStages s; @StageRef public HashEntryStages entry; @StageRef public Alloc alloc; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/FallbackJavaCrc32.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/FallbackJavaCrc32.java index 961e4e446..0389a5c25 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/FallbackJavaCrc32.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/FallbackJavaCrc32.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.hash.impl.stage.entry; -import static net.openhft.lang.io.NativeBytes.UNSAFE; +import net.openhft.chronicle.core.OS; /** * Copied from @@ -102,7 +102,7 @@ public enum FallbackJavaCrc32 implements Crc32 { public int crc32(long addr, long len) { int crc = 0xffffffff; for (long limit = addr + len; addr < limit; addr++) { - int value = UNSAFE.getByte(addr) & 0xff; + int value = OS.memory().readByte(addr) & 0xff; crc = (crc << 8) ^ crc32Table[(((crc >> 24) ^ value) & 0xff)]; } return ~crc; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java index 788ac5730..d45026337 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java @@ -17,6 +17,7 @@ package net.openhft.chronicle.hash.impl.stage.entry; import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.ChecksumEntry; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.HashEntry; @@ -35,7 +36,7 @@ import static net.openhft.chronicle.algo.bytes.Access.nativeAccess; @Staged public abstract class HashEntryStages implements HashEntry, ChecksumEntry { - @StageRef public VanillaChronicleHashHolder hh; + @StageRef public VanillaChronicleHashHolder hh; @StageRef public SegmentStages s; @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; @StageRef public HashLookupPos hlp; @@ -52,7 +53,6 @@ public abstract class HashEntryStages implements HashEntry, ChecksumEntry public void initEntryOffset() { keySizeOffset = s.entrySpaceOffset + pos * hh.h().chunkSize; - s.segmentBytes.limit(s.segmentBytes.capacity()); } public long keySize = -1; @@ -69,17 +69,19 @@ public abstract class HashEntryStages implements HashEntry, ChecksumEntry public void readExistingEntry(long pos) { initPos(pos); - s.segmentBytes.position(keySizeOffset); - initKeySize(hh.h().keySizeMarshaller.readSize(s.segmentBytes)); - initKeyOffset(s.segmentBytes.position()); + Bytes segmentBytes = s.segmentBytesForRead(); + segmentBytes.readPosition(keySizeOffset); + initKeySize(hh.h().keySizeMarshaller.readSize(segmentBytes)); + initKeyOffset(segmentBytes.readPosition()); } public void writeNewEntry(long pos, Data key) { initPos(pos); initKeySize(key.size()); - s.segmentBytes.position(keySizeOffset); - hh.h().keySizeMarshaller.writeSize(s.segmentBytes, keySize); - initKeyOffset(s.segmentBytes.position()); + Bytes segmentBytes = s.segmentBytesForWrite(); + segmentBytes.writePosition(keySizeOffset); + hh.h().keySizeMarshaller.writeSize(segmentBytes, keySize); + initKeyOffset(segmentBytes.writePosition()); key.writeTo(s.segmentBS, keyOffset); } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java index 94bca664e..73db99b4e 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java @@ -50,7 +50,7 @@ public abstract class HashLookupPos { public abstract void closeHashLookupPos(); - @StageRef VanillaChronicleHashHolder hh; + @StageRef VanillaChronicleHashHolder hh; @StageRef SegmentStages s; public void putValueVolatile(long newValue) { diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java index 4d03a9554..b70685980 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupSearch.java @@ -18,10 +18,6 @@ package net.openhft.chronicle.hash.impl.stage.entry; import net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; -import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; -import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; -import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; -import net.openhft.chronicle.hash.impl.stage.query.HashQuery; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; @@ -33,7 +29,7 @@ import static net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable.UNSE public abstract class HashLookupSearch { @StageRef SegmentStages s; - @StageRef public VanillaChronicleHashHolder hh; + @StageRef public VanillaChronicleHashHolder hh; @StageRef HashLookupPos hlp; @StageRef KeySearch ks; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/NativeCrc32.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/NativeCrc32.java index 20c981fc1..bca0b455b 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/NativeCrc32.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/NativeCrc32.java @@ -30,9 +30,7 @@ public enum NativeCrc32 implements Crc32 { MethodHandles.Lookup lookup = MethodHandles.lookup(); updateByteBuffer = lookup.findStatic(CRC32.class, "updateByteBuffer", MethodType.methodType(int.class, long.class, int.class, int.class)); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { + } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java index 1a57eecaa..47b5efc94 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.hash.impl.stage.entry; +import net.openhft.chronicle.hash.locks.InterProcessLock; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; -import net.openhft.chronicle.hash.locks.InterProcessLock; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java index dbc83b5a0..8c8d42521 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java @@ -16,10 +16,13 @@ package net.openhft.chronicle.hash.impl.stage.entry; +import net.openhft.chronicle.algo.bitset.BitSetFrame; import net.openhft.chronicle.algo.bitset.ReusableBitSet; import net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame; import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.PointerBytesStore; +import net.openhft.chronicle.bytes.VanillaBytes; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.SegmentLock; import net.openhft.chronicle.hash.impl.*; @@ -27,9 +30,7 @@ import net.openhft.chronicle.hash.impl.stage.hash.Chaining; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.chronicle.hash.locks.InterProcessLock; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.impl.IterationContext; -import net.openhft.lang.collection.DirectBitSet; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -46,7 +47,7 @@ import static net.openhft.chronicle.hash.impl.VanillaChronicleHash.TIER_COUNTERS public abstract class SegmentStages implements SegmentLock, LocksInterface { @StageRef Chaining chaining; - @StageRef public VanillaChronicleHashHolder hh; + @StageRef public VanillaChronicleHashHolder hh; @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; public int segmentIndex = -1; @@ -533,7 +534,7 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { } public void nextTier() { - VanillaChronicleHash, ?, ?, ?> h = hh.h(); + VanillaChronicleHash h = hh.h(); long nextTierIndex = nextTierIndex(); if (nextTierIndex == 0) { nextTierIndex = h.allocateTier(segmentIndex, segmentTier + 1); @@ -568,8 +569,8 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { } } - @Stage("Segment") public final PublicMultiStoreBytes segmentBytes = new PublicMultiStoreBytes(); @Stage("Segment") public final PointerBytesStore segmentBS = new PointerBytesStore(); + @Stage("Segment") public final Bytes segmentBytes = new VanillaBytes(segmentBS); @Stage("Segment") public final ReusableBitSet freeList = new ReusableBitSet( new SingleThreadedFlatBitSetFrame(LONGS.align(hh.h().actualChunksPerSegment, BITS)), Access.nativeAccess(), null, 0); @@ -580,13 +581,11 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { } void initSegment() { - VanillaChronicleHash h = hh.h(); - - PublicMultiStoreBytes segmentBytes = this.segmentBytes; - segmentBytes.setBytesOffset(h.tierBytes(tierIndex), h.tierBytesOffset(tierIndex)); + VanillaChronicleHash h = hh.h(); long segmentBaseAddr = this.segmentBaseAddr; segmentBS.set(segmentBaseAddr, h.segmentSize); + segmentBytes.clear(); long freeListOffset = h.segmentHashLookupOuterSize + TIER_COUNTERS_AREA_SIZE; freeList.setOffset(segmentBaseAddr + freeListOffset); @@ -594,26 +593,38 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface { entrySpaceOffset = freeListOffset + h.segmentFreeListOuterSize + h.segmentEntrySpaceInnerOffset; } + + @Stage("Segment") + public Bytes segmentBytesForRead() { + segmentBytes.readLimit(segmentBytes.capacity()); + return segmentBytes; + } + + @Stage("Segment") + public Bytes segmentBytesForWrite() { + segmentBytes.readPosition(0); + return segmentBytes; + } void closeSegment() { entrySpaceOffset = 0; } public long allocReturnCode(int chunks) { - VanillaChronicleHash h = hh.h(); + VanillaChronicleHash h = hh.h(); if (chunks > h.maxChunksPerEntry) { throw new IllegalArgumentException("Entry is too large: requires " + chunks + " chucks, " + h.maxChunksPerEntry + " is maximum."); } long ret = freeList.setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); - if (ret == DirectBitSet.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { - if (ret != DirectBitSet.NOT_FOUND && + if (ret == BitSetFrame.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { + if (ret != BitSetFrame.NOT_FOUND && ret + chunks > h.actualChunksPerSegment && ret < h.actualChunksPerSegment) { freeList.clearRange(ret, h.actualChunksPerSegment); } ret = freeList.setNextNContinuousClearBits(0L, chunks); - if (ret == DirectBitSet.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { - if (ret != DirectBitSet.NOT_FOUND && + if (ret == BitSetFrame.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { + if (ret != BitSetFrame.NOT_FOUND && ret + chunks > h.actualChunksPerSegment && ret < h.actualChunksPerSegment) { freeList.clearRange(ret, h.actualChunksPerSegment); diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java index 37291bd7b..6e48b0742 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java @@ -17,9 +17,9 @@ package net.openhft.chronicle.hash.impl.stage.entry; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; +import net.openhft.chronicle.hash.locks.InterProcessLock; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; -import net.openhft.chronicle.hash.locks.InterProcessLock; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java index ca4ec62e3..63545ce71 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.hash.impl.stage.entry; +import net.openhft.chronicle.hash.locks.InterProcessLock; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; -import net.openhft.chronicle.hash.locks.InterProcessLock; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java index 06aacddd4..c44b8f640 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java @@ -53,7 +53,6 @@ public class Chaining extends ChainingInterface { return (T) contextChain.get(index); } - boolean used; @Override diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java index d9eb56806..5a7e56a88 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java @@ -24,7 +24,7 @@ import net.openhft.sg.Staged; public abstract class CheckOnEachPublicOperation { @StageRef OwnerThreadHolder holder; - @StageRef VanillaChronicleHashHolder hh; + @StageRef VanillaChronicleHashHolder hh; public void checkOnEachPublicOperation() { holder.checkAccessingFromOwnerThread(); diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java index ea3f2fd6b..aa76dbf39 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java @@ -17,23 +17,16 @@ package net.openhft.chronicle.hash.impl.stage.hash; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; -@Staged -public class KeyBytesInterop> { - @StageRef - VanillaChronicleHashHolder hh; - @StageRef ThreadLocalCopiesHolder ch; +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; - public final BytesReader keyReader = - hh.h().keyReaderProvider.get(ch.copies, hh.h().originalKeyReader); - public final KI keyInterop = hh.h().keyInteropProvider.get(ch.copies, hh.h().originalKeyInterop); - - public MKI keyMetaInterop(K key) { - return hh.h().metaKeyInteropProvider.get( - ch.copies, hh.h().originalMetaKeyInterop, keyInterop, key, false); - } +@Staged +public class KeyBytesInterop { + + @StageRef VanillaChronicleHashHolder hh; + + public final SizedReader keyReader = copyIfNeeded(hh.h().originalKeyReader); } diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java deleted file mode 100644 index 48ffbae17..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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.hash.impl.stage.hash; - -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import net.openhft.sg.Staged; - -@Staged -public class ThreadLocalCopiesHolder { - public final ThreadLocalCopies copies = ThreadLocalCopies.get(); -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java deleted file mode 100644 index ba6f029d5..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.hash.impl.stage.input; - -import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; -import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; -import net.openhft.lang.io.Bytes; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public class HashInputBytes { - - @StageRef VanillaChronicleHashHolder hh; - - public Bytes inputBytes = null; - public final JavaLangBytesReusableBytesStore inputStore = new JavaLangBytesReusableBytesStore(); - - public void initInputBytes(Bytes inputBytes) { - this.inputBytes = inputBytes; - inputStore.setBytes(inputBytes); - } - - @Stage("InputKeyOffsets") public long inputKeySize = -1; - @Stage("InputKeyOffsets") public long inputKeyOffset; - - private void initInputKeyOffsets() { - inputKeySize = hh.h().keySizeMarshaller.readSize(inputBytes); - inputKeyOffset = inputBytes.position(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java index 86f4dd487..b87d397cc 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java @@ -35,7 +35,7 @@ public abstract class HashSegmentIteration> @StageRef public IterationSegmentStages s; @StageRef HashEntryStages e; - @StageRef VanillaChronicleHashHolder hh; + @StageRef VanillaChronicleHashHolder hh; @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; @StageRef protected HashLookupPos hlp; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/IterationSegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/IterationSegmentStages.java index c9b2ee58a..0ff9fc843 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/IterationSegmentStages.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/IterationSegmentStages.java @@ -17,9 +17,9 @@ package net.openhft.chronicle.hash.impl.stage.iter; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; import net.openhft.chronicle.hash.impl.stage.entry.LocksInterface; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; -import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -27,7 +27,7 @@ import net.openhft.sg.Staged; @Staged public abstract class IterationSegmentStages extends SegmentStages { - @StageRef VanillaChronicleHashHolder hh; + @StageRef VanillaChronicleHashHolder hh; @StageRef HashSegmentIteration it; @StageRef HashLookupSearch hls; diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java index 9c3613d71..896c3af18 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java @@ -19,13 +19,12 @@ package net.openhft.chronicle.hash.impl.stage.query; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.HashEntry; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; -import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; -import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -36,16 +35,35 @@ import static net.openhft.chronicle.hash.impl.stage.query.KeySearch.SearchState. @Staged public abstract class HashQuery implements HashEntry { - @StageRef public VanillaChronicleHashHolder hh; + @StageRef public VanillaChronicleHashHolder hh; @StageRef public SegmentStages s; @StageRef public HashEntryStages entry; @StageRef public HashLookupSearch hashLookupSearch; @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; @StageRef public HashLookupPos hlp; - @StageRef public KeySearch ks; - - @StageRef public InputKeyInstanceData inputKeyInstanceValue; - @StageRef public InputKeyBytesData inputKeyBytesValue; + @StageRef public KeySearch ks; + + final DataAccess innerInputKeyDataAccess = hh.h().originalKeyDataAccess.copy(); + + /** + * This stage exists for hooking {@link #innerInputKeyDataAccess} usage, to trigger {@link + * DataAccess#uninit()} on context exit + */ + @Stage("InputKeyDataAccess") private boolean inputKeyDataAccessInitialized = false; + + void initInputKeyDataAccess() { + inputKeyDataAccessInitialized = true; + } + + void closeInputKeyDataAccess() { + innerInputKeyDataAccess.uninit(); + inputKeyDataAccessInitialized = false; + } + + public DataAccess inputKeyDataAccess() { + initInputKeyDataAccess(); + return innerInputKeyDataAccess; + } public void dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed() { if (s.locksInit()) { diff --git a/src/main/java/net/openhft/chronicle/hash/impl/value/instance/KeyInitableData.java b/src/main/java/net/openhft/chronicle/hash/impl/value/instance/KeyInitableData.java deleted file mode 100644 index 60bf9c87a..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/value/instance/KeyInitableData.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.hash.impl.value.instance; - -import net.openhft.chronicle.hash.Data; - -public interface KeyInitableData extends Data { - - void initKey(K key); -} diff --git a/src/main/java/net/openhft/chronicle/hash/replication/ConnectionListener.java b/src/main/java/net/openhft/chronicle/hash/replication/ConnectionListener.java index 4147ccf82..7293d830d 100644 --- a/src/main/java/net/openhft/chronicle/hash/replication/ConnectionListener.java +++ b/src/main/java/net/openhft/chronicle/hash/replication/ConnectionListener.java @@ -21,7 +21,7 @@ import java.net.InetAddress; public interface ConnectionListener { /** - * @param address the address that we are connceted to + * @param address the address that we are connected to * @param identifier the remote identifier that we are not connected to. * @param isServer if this host accepted the connection {@code isServer} is {@code true}, if * we made the connection to a remote host then {@code isServer} is {@code diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/BytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/BytesInterop.java deleted file mode 100644 index 34a295661..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/BytesInterop.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.hash.serialization; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.model.Byteable; -import org.jetbrains.annotations.NotNull; - -/** - * Writer for objects, which themselves are bytes sequence in some sense: - * {@link Byteable Byteables}, {@code byte[]} arrays, other primitive arrays, "flat" objects - * (with primitives fields only), particularly boxed primitive types. - * - *

This interface is called "BytesInterop" because it allows to work with object as they - * are already marshalled to {@code Bytes}: {@linkplain #startsWith(Bytes, Object) compare} - * with other {@code Bytes}, i. e. interoperate objects and {@code Bytes}. - * - * @param type of marshalled objects - */ -public interface BytesInterop extends BytesWriter { - - /** - * Checks if the given {@code bytes} starts (from the {@code bytes}' {@linkplain - * Bytes#position() position}) with the byte sequence the given object - * {@linkplain #write(Bytes, Object) is serialized} to, without actual serialization. - * - * @param bytes the bytes to check if starts with the serialized form of the given object. - * {@code bytes}' is positioned at the first byte to compare. {@code bytes}' limit - * is unspecified. {@code bytes}' position and limit shouldn't be altered during - * this call. - * @param e the object to serialize virtually and compare with the given {@code bytes} - * @return if the given {@code bytes} starts with the given {@code e} object's serialized form - */ - boolean startsWith(@NotNull Bytes bytes, @NotNull E e); - - /** - * Returns {@code true} if the given objects are serialized to the same sequence of bytes by - * {@link #write(Bytes, Object)} method, without actual serialization. Normally this method - * should always return the same result as {@code a.equals(b)} call, unless some fields of the - * serialized objects, accounted in {@code equals()} implementation, are ignored - * on serialization. - * - * @param a first object to compare - * @param b second object to compare - * @return if the given objects are serialized to the same sequence of bytes by this - * {@code BytesInterop} strategy - */ - boolean equivalent(@NotNull E a, @NotNull E b); - - /** - * Returns hash code for the byte sequence the given object {@linkplain #write(Bytes, Object) - * is serialized} to, without actual serialization. Formally speaking, implementation of this - * method should be equivalent to

{@code
-     * public long hash(LongHashFunction hashFunction, E e) {
-     *     long size = size(e);
-     *     long addr = theUnsafe.allocateMemory(size);
-     *     Bytes bytes = new NativeBytes(addr, size);
-     *     write(bytes, e);
-     *     return hashFunction.hashBytes(bytes, 0, size);
-     * }}
except that it should perform actual serialization and allocate memory, of cause. - * - * @param hashFunction the hash function to use for hash code computation - * @param e the object to hash - * @return hash code for the bytes sequence the given object is serialized to - */ - long hash(@NotNull LongHashFunction hashFunction, @NotNull E e); -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java index 51d0d9895..eff258b3f 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/BytesReader.java @@ -16,91 +16,36 @@ package net.openhft.chronicle.hash.serialization; -import net.openhft.chronicle.hash.ChronicleHash; -import net.openhft.lang.io.Bytes; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.ReadBytesMarshallable; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.Serializable; /** - * Deserializer (object from {@link Bytes}, mirroring the {@link BytesWriter}, i. e. assuming the - * length of the serialized form isn't written in the beginning of the serialized form itself, - * but managed by {@link ChronicleHash} implementation and passed to the reading methods. + * External version on {@link ReadBytesMarshallable}, could be used as lambda. * - *

Implementation example:


- * class LongPair { long first, second; }
- * 
- * enum LongPairArrayReader implements BytesReader<LongPair[]> {
- *     INSTANCE;
- *
- *     @Override
- *     public LongPair[] read(Bytes bytes, long size) {
- *         return read(bytes, size, null);
- *     }
- *
- *     @Override
- *     public LongPair[] read(Bytes bytes, long size, LongPair[] toReuse) {
- *         if (size > Integer.MAX_VALUE * 16L)
- *             throw new IllegalStateException("LongPair[] size couldn't be " + (size / 16L));
- *         int resLen = (int) (size / 16L);
- *         LongPair[] res;
- *         if (toReuse != null) {
- *             if (toReuse.length == resLen) {
- *                 res = toReuse;
- *             } else {
- *                 res = Arrays.copyOf(toReuse, resLen);
- *             }
- *         } else {
- *             res = new LongPair[resLen];
- *         }
- *         for (int i = 0; i < resLen; i++) {
- *             LongPair pair = res[i];
- *             if (pair == null)
- *                 res[i] = pair = new LongPair();
- *             pair.first = bytes.readLong();
- *             pair.second = bytes.readLong();
- *         }
- *         return res;
- *     }
- * }
- * - * @param the type of the object demarshalled + * @param type of objects deserialized * @see BytesWriter */ -public interface BytesReader extends Serializable { +@FunctionalInterface +public interface BytesReader extends Serializable { /** - * Reads and returns the object from {@code [position(), position() + size]} bytes of the given - * {@link Bytes}. + * Reads and returns the object from {@link Bytes#readPosition()} (i. e. the current position) + * in the given {@code in}. Should attempt to reuse the given {@code using} object, i. e. to + * read the deserialized data into the given object. If it is possible, this object then + * returned from this method back. If it is impossible for any reason, a new object should be + * created and returned. The given {@code using} object could be {@code null}, in this case this + * method, of cause, should create a new object. * - *

Implementation of this method should increment the {@code bytes}' position by the given - * size, i. e. "consume" the bytes of the deserialized object. It must not alter the - * {@code bytes}' {@link Bytes#limit() limit} and contents. + *

This method should increment the position in the given {@code Bytes}, i. e. consume the + * read bytes. {@code in} bytes shouldn't be written. * - * @param bytes the {@code Bytes} to read the object from - * @param size the size of the serialized form of the returned object - * @return the object read from the bytes - * @see BytesWriter#write(Bytes, Object) - * @see #read(Bytes, long, Object) - */ - @NotNull - E read(@NotNull Bytes bytes, long size); - - /** - * Similar to {@link #read(Bytes, long)}, but should attempt to reuse the given object, i. e. - * to read the deserialized data into the given instance. If it is possible, this objects than - * returned from this method. If it isn't possible for any reason, a new object should be - * created and returned, just like in {@link #read(Bytes, long)} method. The given object could - * be {@code null}, in this case this method should behave exactly the same as - * {@link #read(Bytes, long)} method does. - * - * @param bytes the {@code Bytes} to read the object from - * @param size the size of the serialized form of the returned object - * @param toReuse the object to read the deserialized data into + * @param in the {@code Bytes} to read the object from + * @param using the object to read the deserialized data into, could be {@code null} * @return the object read from the bytes, either reused or newly created - * @see #read(Bytes, long) */ @NotNull - E read(@NotNull Bytes bytes, long size, @Nullable E toReuse); + T read(Bytes in, T using); } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java index c39b36da9..e7642a9d5 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/BytesWriter.java @@ -16,67 +16,32 @@ package net.openhft.chronicle.hash.serialization; -import net.openhft.chronicle.hash.ChronicleHash; -import net.openhft.lang.io.Bytes; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.WriteBytesMarshallable; import org.jetbrains.annotations.NotNull; import java.io.Serializable; /** - * Serializer (object to {@link Bytes} writer) which 1) knows the length of serialized form - * of any object before actual serialization 2) doesn't include that length in the serialized - * form itself, assuming it will be passed by the {@link ChronicleHash} into - * {@link BytesReader#read(Bytes, long)} deserialization method. + * External version of {@link WriteBytesMarshallable}, could be used as lambda. * - *

Implementation example:


- * class LongPair { long first, second; }
- *
- * enum LongPairArrayWriter implements BytesWriter<LongPair[]> {
- *     INSTANCE;
- *
- *     @Override
- *     public long size(LongPair[] longPairs) {
- *         return longPairs.length * 16L;
- *     }
- *
- *     @Override
- *     public void write(Bytes bytes, LongPair[] longPairs) {
- *         for (LongPair pair : longPairs) {
- *             bytes.writeLong(pair.first);
- *             bytes.writeLong(pair.second);
- *         }
- *     }
- * }
- * - * @param the type of the object marshalled + * @param the type of objects serialized * @see BytesReader - * @see BytesInterop */ -public interface BytesWriter extends Serializable { +@FunctionalInterface +public interface BytesWriter extends Serializable { /** - * Returns the length (in bytes) of the serialized form of the given object. Serialization form - * in terms of this interface, i. e. how much bytes are written to {@code bytes} on - * {@link #write(Bytes, Object) write(bytes, e)} call. + * Serializes the given object to the given {@code out}. * - * @param e the object which serialized form length should be returned - * @return the length (in bytes) of the serialized form of the given object + *

Implementation of this method should increment the {@linkplain Bytes#writePosition() + * position} of the given {@code out} by the number of bytes written. The given object should be + * written into these range between the initial {@code bytes}' position and the position after + * this method call returns. Bytes outside of this range shouldn't be written. Any bytes + * shouldn't be read from {@code out}. + * + * @param out the {@code Bytes} to write the given object to + * @param toWrite the object to serialize */ - long size(@NotNull E e); - - /** - * Serializes the given object to the given {@code bytes}, without writing the length of the - * serialized form itself. - * - *

Implementation of this method should increment the {@code bytes}' {@linkplain - * Bytes#position() position} by {@link #size(Object) size(e)}. The given object should - * be written into these range between the initial {@code bytes}' position and the position - * after this method call returns. Implementation of this method must not alter the - * {@code bytes}' {@linkplain Bytes#limit() limit} and contents outside of the specified range. - * - * @param bytes the {@code Bytes} to write the given object to - * @param e the object to serialize to the given bytes - * @see BytesReader#read(Bytes, long) - */ - void write(@NotNull Bytes bytes, @NotNull E e); + void write(Bytes out, @NotNull T toWrite); } diff --git a/src/main/java/net/openhft/chronicle/map/InstanceOrBytesToInstance.java b/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java similarity index 74% rename from src/main/java/net/openhft/chronicle/map/InstanceOrBytesToInstance.java rename to src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java index 0b9f33c22..c6a7dbf81 100644 --- a/src/main/java/net/openhft/chronicle/map/InstanceOrBytesToInstance.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/DataAccess.java @@ -14,11 +14,16 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.hash.serialization; -import net.openhft.lang.threadlocal.ThreadLocalCopies; +import net.openhft.chronicle.hash.Data; import org.jetbrains.annotations.NotNull; -interface InstanceOrBytesToInstance { - T toInstance(@NotNull ThreadLocalCopies copies, TB instanceOrBytes, long size); +import java.io.Serializable; + +public interface DataAccess extends StatefulCopyable>, Serializable { + + Data getData(@NotNull T instance); + + void uninit(); } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java new file mode 100644 index 000000000..15d703245 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/ListMarshaller.java @@ -0,0 +1,106 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.bytes.Bytes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +/** + * Marshaller of {@code List}. Uses {@link ArrayList} as the list implementation to deserialize + * into. + * + *

This marshaller supports multimap emulation on top of Chronicle Map, that is possible but + * inefficient. See the + * README section. + * + *

Usage:

{@code
+ * ListMarshaller valueMarshaller = new ListMarshaller<>(
+ *     IntegerMarshaller.INSTANCE, IntegerMarshaller.INSTANCE);
+ * ChronicleMap> regNumbers = ChronicleMap
+ *     .of(String.class, (Class>) (Class) List.class)
+ *     .entries(10_000)
+ *     .averageKey("John Smith")
+ *     .valueMarshaller(valueMarshaller)
+ *     .averageValue(ImmutableList.of(1, 2, 3))
+ *     .create();
+ * }
+ * + *

Look for pre-defined element marshallers in {@link + * net.openhft.chronicle.hash.serialization.impl} package. This package is not included into + * Javadocs, but present in Chronicle Map distribution. If there are no existing marshallers for + * your {@code List} element type, define {@link BytesReader} and {@link BytesWriter} yourself. + * + * @param the element type of serialized Lists + * @see SetMarshaller + * @see MapMarshaller + */ +public class ListMarshaller + implements BytesReader>, BytesWriter>, StatefulCopyable> { + + private final BytesReader elementReader; + private final BytesWriter elementWriter; + + public ListMarshaller(BytesReader elementReader, BytesWriter elementWriter) { + this.elementReader = elementReader; + this.elementWriter = elementWriter; + } + + @NotNull + @Override + public List read(Bytes in, @Nullable List using) { + int size = in.readInt(); + if (using == null) { + using = new ArrayList<>(size); + } else if (using.size() < size) { + while (using.size() < size) { + using.add(null); + } + } else if (using.size() > size) { + using.subList(size, using.size()).clear(); + } + for (int i = 0; i < size; i++) { + using.set(i, elementReader.read(in, using.get(i))); + } + return using; + } + + @Override + public void write(Bytes out, @NotNull List toWrite) { + out.writeInt(toWrite.size()); + // indexed loop to avoid garbage creation + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < toWrite.size(); i++) { + elementWriter.write(out, toWrite.get(i)); + } + } + + @Override + public ListMarshaller copy() { + if (elementReader instanceof StatefulCopyable || + elementWriter instanceof StatefulCopyable) { + return new ListMarshaller<>(copyIfNeeded(elementReader), copyIfNeeded(elementWriter)); + } else { + return this; + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java new file mode 100644 index 000000000..af9491ffc --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/MapMarshaller.java @@ -0,0 +1,107 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.bytes.Bytes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +/** + * Marshaller of {@code Map}. Uses {@link HashMap} (hence default key objects' equality and + * {@code hashCode()} as the map implementation to deserialize into. + * + *

This marshaller supports multimap emulation on top of Chronicle Map, that is possible but + * inefficient. See the + * README section. + * + *

Look for pre-defined key and value marshallers in {@link + * net.openhft.chronicle.hash.serialization.impl} package. This package is not included into + * Javadocs, but present in Chronicle Map distribution. If there are no existing marshallers for + * your {@code Map} key or value types, define {@link BytesReader} and {@link BytesWriter} yourself. + * + * @param the key type of serialized Maps + * @param the value type of serialized Maps + * @see ListMarshaller + * @see SetMarshaller + */ +public class MapMarshaller + implements BytesReader>, BytesWriter>, + StatefulCopyable> { + + private final BytesReader keyReader; + private final BytesWriter keyWriter; + private final BytesReader valueReader; + private final BytesWriter valueWriter; + private final transient Deque orderedKeys = new ArrayDeque<>(); + private final transient Deque orderedValues = new ArrayDeque<>(); + + public MapMarshaller( + BytesReader keyReader, BytesWriter keyWriter, + BytesReader valueReader, BytesWriter valueWriter) { + this.keyReader = keyReader; + this.keyWriter = keyWriter; + this.valueReader = valueReader; + this.valueWriter = valueWriter; + } + + @NotNull + @Override + public Map read(Bytes in, @Nullable Map using) { + int size = in.readInt(); + if (using == null) { + using = new HashMap<>(((int) (size / 0.75))); + for (int i = 0; i < size; i++) { + using.put(keyReader.read(in, null), valueReader.read(in, null)); + } + } else { + using.forEach((k, v) -> { + orderedKeys.add(k); + orderedValues.add(v); + }); + using.clear(); + for (int i = 0; i < size; i++) { + using.put(keyReader.read(in, orderedKeys.pollFirst()), + valueReader.read(in, orderedValues.pollFirst())); + } + orderedKeys.clear(); // for GC, avoid zombie object links + orderedValues.clear(); + } + return using; + } + + @Override + public void write(Bytes out, @NotNull Map toWrite) { + out.writeInt(toWrite.size()); + toWrite.forEach((k, v) -> { + keyWriter.write(out, k); + valueWriter.write(out, v); + }); + } + + @Override + public MapMarshaller copy() { + return new MapMarshaller<>(copyIfNeeded(keyReader), copyIfNeeded(keyWriter), + copyIfNeeded(valueReader), copyIfNeeded(valueWriter)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java new file mode 100644 index 000000000..05e2b8563 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SetMarshaller.java @@ -0,0 +1,98 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.bytes.Bytes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +/** + * Marshaller of {@code Set}. Uses {@link HashSet} (hence default element objects' equality and + * {@code hashCode()}) as the set implementation to deserialize into. + * + *

This marshaller supports multimap emulation on top of Chronicle Map, that is possible but + * inefficient. See the + * README section. + * + *

Usage:

{@code
+ * SetMarshaller valueMarshaller = new SetMarshaller<>(
+ *     new StringBytesReader(), CharSequenceBytesWriter.INSTANCE);
+ * ChronicleMap> map = ChronicleMap
+ *     .of(String.class, (Class>) (Class) Set.class)
+ *     .entries(10_000)
+ *     .averageKey("fruits")
+ *     .valueMarshaller(valueMarshaller)
+ *     .averageValue(ImmutableSet.of("apples", "bananas", "grapes"))
+ *     .create();
+ * }
+ * + *

Look for pre-defined element marshallers in {@link + * net.openhft.chronicle.hash.serialization.impl} package. This package is not included into + * Javadocs, but present in Chronicle Map distribution. If there are no existing marshallers for + * your {@code Set} element type, define {@link BytesReader} and {@link BytesWriter} yourself. + * + * @param the element type of serialized Sets + * @see ListMarshaller + * @see MapMarshaller + */ +public class SetMarshaller + implements BytesReader>, BytesWriter>, StatefulCopyable> { + + private final BytesReader elementReader; + private final BytesWriter elementWriter; + private final transient Deque orderedElements = new ArrayDeque<>(); + + public SetMarshaller(BytesReader elementReader, BytesWriter elementWriter) { + this.elementReader = elementReader; + this.elementWriter = elementWriter; + } + + @NotNull + @Override + public Set read(Bytes in, @Nullable Set using) { + int size = in.readInt(); + if (using == null) { + using = new HashSet<>((int) (size / 0.75)); + for (int i = 0; i < size; i++) { + using.add(elementReader.read(in, null)); + } + } else { + orderedElements.addAll(using); + using.clear(); + for (int i = 0; i < size; i++) { + using.add(elementReader.read(in, orderedElements.pollFirst())); + } + orderedElements.clear(); // for GC, avoid zombie object links + } + return using; + } + + @Override + public void write(Bytes out, @NotNull Set toWrite) { + out.writeInt(toWrite.size()); + toWrite.forEach(e -> elementWriter.write(out, e)); + } + + @Override + public SetMarshaller copy() { + return new SetMarshaller<>(copyIfNeeded(elementReader), copyIfNeeded(elementWriter)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java index 1a6f177f4..97a42f382 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizeMarshaller.java @@ -16,21 +16,100 @@ package net.openhft.chronicle.hash.serialization; -import net.openhft.lang.io.Bytes; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.impl.ConstantSizeMarshaller; +import net.openhft.chronicle.hash.serialization.impl.StopBitSizeMarshaller; import java.io.Serializable; +/** + * Strategy of storing numbers in bytes stores (usually sizes of the subsequent chunks in + * the same bytes store). Normal number storing (4 bytes for {@code int}, 8 bytes for {@code long} + * is rather wasteful for marshalling purposes, when the number (size) to store is usually very + * small, and 1-2 bytes could be enough to encode it (this is how {@link #stopBit()} marshaller + * work). Also, this interface allows to generalize storing constantly-sized and variable-sized + * blocks of data. Constantly-sized don't require to store the size actually, the corresponding + * {@link #constant} {@code SizeMarshaller} consumes 0 bytes. + * + *

Some {@code SizeMarshaller} implementations couldn't store the whole {@code long} range, for + * example each {@link #constant} {@code SizeMarshaller} is able to "store" only a single specific + * value (it's constant size). If the marshaller is fed with the size it is not able store, it could + * throw an {@code IllegalArgumentException}. + */ public interface SizeMarshaller extends Serializable { - int sizeEncodingSize(long size); + static SizeMarshaller stopBit() { + return StopBitSizeMarshaller.INSTANCE; + } - long minEncodableSize(); + static SizeMarshaller constant(long constantSize) { + return new ConstantSizeMarshaller(constantSize); + } - int minSizeEncodingSize(); + /** + * Calculates how many bytes is takes to store the given {@code size} with this {@code + * SizeMarshaller}. + * + * @param size the size to store + * @return the number of bytes would be taken to store the given size + * @throws IllegalArgumentException might be thrown, if the given size if not storable by this + * {@code SizeMarshaller} + */ + int storingLength(long size); - int maxSizeEncodingSize(); + /** + * Returns the minimum size this {@code SizeMarshaller} is able to store. + * + * @return the minimum size this {@code SizeMarshaller} is able to store + */ + long minStorableSize(); - void writeSize(Bytes bytes, long size); + /** + * Returns the maximum size this {@code SizeMarshaller} is able to store. + * + * @return the maximum size this {@code SizeMarshaller} is able to store + */ + long maxStorableSize(); - long readSize(Bytes bytes); + /** + * Returns the minimum storing length this {@code SizeMarshaller} produces for some size in the + * given range (both bounds are inclusive). + * + * @param minSize the lower bound of the range (inclusive) + * @param maxSize the upper bound of the range (inclusive) + * @return the smallest storing length of a value in the given range + * @see #maxStoringLengthOfSizesInRange(long, long) + */ + int minStoringLengthOfSizesInRange(long minSize, long maxSize); + + /** + * Returns the maximum storing length this {@code SizeMarshaller} produces for some value in the + * given range (both bounds are inclusive). + * + * @param minSize the lower bound of the range (inclusive) + * @param maxSize the upper bound of the range (inclusive) + * @return the biggest storing length of a value in the given range + * @see #minStoringLengthOfSizesInRange(long, long) + */ + int maxStoringLengthOfSizesInRange(long minSize, long maxSize); + + /** + * Writes the given size into the streaming output. + * + * @param out the {@code StreamingDataOutput} to write the size to + * @param sizeToWrite the size to write + * @throws IllegalArgumentException might be thrown, if the given size if not storable by this + * {@code SizeMarshaller} + * @see #readSize(Bytes) + */ + void writeSize(Bytes out, long sizeToWrite); + + /** + * Reads and returns a size from the input. + * + * @param in the {@code StreamingDataInput} to read the size from + * @return the read size + * @see #writeSize(Bytes, long) + */ + long readSize(Bytes in); } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java new file mode 100644 index 000000000..763b6938d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizedReader.java @@ -0,0 +1,89 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.ChronicleHash; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +/** + * Deserializer of objects from bytes, mirroring the {@link SizedWriter}, i. e. assuming the length + * of the serialized form isn't written in the beginning of the serialized form itself, but managed + * by {@link ChronicleHash} implementation and passed to the reading methods. + * + *

Implementation example:


+ * class LongPair { long first, second; }
+ * 
+ * enum LongPairArrayReader implements{@code SizedReader} {
+ *     INSTANCE;
+ *
+ *    {@literal @}Override
+ *    {@literal @}NotNull
+ *     public LongPair[]{@literal read(@}NotNull Bytes in, long size,
+ *            {@literal @}Nullable LongPair[] using) {
+ *         if (size{@code >} Integer.MAX_VALUE * 16L)
+ *             throw new IllegalStateException("LongPair[] size couldn't be " + (size / 16L));
+ *         int resLen = (int) (size / 16L);
+ *         LongPair[] res;
+ *         if (using != null) {
+ *             if (using.length == resLen) {
+ *                 res = using;
+ *             } else {
+ *                 res = Arrays.copyOf(using, resLen);
+ *             }
+ *         } else {
+ *             res = new LongPair[resLen];
+ *         }
+ *         for (int i = 0; i{@code <} resLen; i++) {
+ *             LongPair pair = res[i];
+ *             if (pair == null)
+ *                 res[i] = pair = new LongPair();
+ *             pair.first = in.readLong();
+ *             pair.second = in.readLong();
+ *         }
+ *         return res;
+ *     }
+ * }
+ * + * @param the type of the object deserialized + * @see SizedWriter + */ +@FunctionalInterface +public interface SizedReader extends Serializable { + + /** + * Reads and returns the object from {@link Bytes#readPosition()} (i. e. the current position) + * to {@code Bytes.readPosition() + size} in the given {@code in}. Should attempt to reuse the + * given {@code using} object, i. e. to read the deserialized data into the given object. If it + * is possible, this objects then returned from this method. If it is impossible for any reason, + * a new object should be created and returned. The given {@code using} object could be {@code + * null}, in this case this method, of cause, should create a new object. + * + *

This method should increment the position in the given {@code Bytes} by the given {@code + * size}. + * + * @param in the {@code Bytes} to read the object from + * @param size the size of the serialized form of the returned object + * @param using the object to read the deserialized data into, could be {@code null} + * @return the object read from the bytes, either reused or newly created + */ + @NotNull + T read(Bytes in, long size, @Nullable T using); +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java new file mode 100644 index 000000000..ece461192 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/SizedWriter.java @@ -0,0 +1,85 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.ChronicleHash; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; + +/** + * Serializer (object to bytes writer) which 1) knows the length of serialized + * form of any object before actual serialization 2) doesn't include that length in the serialized + * form itself, assuming it will be passed by the {@link ChronicleHash} into {@link + * SizedReader#read} deserialization method. + * + *

Implementation example:


+ * class LongPair { long first, second; }
+ *
+ * enum LongPairArrayWriter implements{@code SizedWriter} {
+ *     INSTANCE;
+ *
+ *    {@literal @}Override
+ *     public long{@literal size(@}NotNull LongPair[] toWrite) {
+ *         return toWrite.length * 16L;
+ *     }
+ *
+ *    {@literal @}Override
+ *     public void{@literal write(@}NotNull Bytes out, long size,
+ *            {@literal @}NotNull LongPair[] toWrite) {
+ *         for (LongPair pair : toWrite) {
+ *             out.writeLong(pair.first);
+ *             out.writeLong(pair.second);
+ *         }
+ *     }
+ * }
+ * + * @param the type of the object marshalled + * @see SizedReader + */ +public interface SizedWriter extends Serializable { + + /** + * Returns the length (in bytes) of the serialized form of the given object. Serialization form + * in terms of this interface, i. e. how much bytes are written to {@code out} on + * {@link #write(Bytes, long, Object) write(out, size, toWrite)} call. + * + * @param toWrite the object which serialized form length should be returned + * @return the length (in bytes) of the serialized form of the given object + */ + long size(@NotNull T toWrite); + + /** + * Serializes the given object to the given {@code out}, without writing the length of the + * serialized form itself. + * + *

Implementation of this method should increment the {@linkplain Bytes#writePosition() + * position} of the given {@code out} by {@link #size(Object) size(toWrite)}. The given object + * should be written into these range between the initial {@code bytes}' position and the + * position after this method call returns. + * + * @param out the {@code Bytes} to write the given object to + * @param size the size, returned by {@link #size(Object)} for the given {@code toWrite} object. + * it is given, because size might be needed during serialization, and it's computation has + * non-constant complexity, i. e. if serializing a {@code CharSequence} using variable-length + * encoding like UTF-8. + * @param toWrite the object to serialize + * @see SizedReader#read(Bytes, long, Object) + */ + void write(Bytes out, long size, @NotNull T toWrite); +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/StatefulCopyable.java b/src/main/java/net/openhft/chronicle/hash/serialization/StatefulCopyable.java new file mode 100644 index 000000000..41b4b7fb8 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/StatefulCopyable.java @@ -0,0 +1,87 @@ +/* + * 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.hash.serialization; + +import net.openhft.chronicle.hash.serialization.impl.StringBytesReader; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.set.ChronicleSet; + +/** + * Stateful implementations of marshaller interfaces ({@link SizedReader}, {@link SizedWriter}, + * {@link BytesReader}, {@link BytesWriter}, {@link DataAccess}), configured for {@link + * ChronicleMap} or {@link ChronicleSet} in builder, should implement the {@code StatefulCopyable} + * interface. The marshaller instance is populated for each site by {@link #copy()} method. + * + *

For example, see {@link StringBytesReader} implementation:


+ * public class StringBytesReader
+ *         implements{@code BytesReader, StatefulCopyable} {
+ *
+ *     private final StringBuilder sb = new StringBuilder();
+ *
+ *    {@literal @}NotNull
+ *    {@literal @}Override
+ *     public String read(Bytes in,{@literal @}Nullable String using) {
+ *         sb.setLength(0);
+ *         in.readUtf8(sb);
+ *         return sb.toString();
+ *     }
+ *
+ *    {@literal @}Override
+ *     public StringBytesReader copy() {
+ *         return new StringBytesReader();
+ *     }
+ * }
+ * 
+ * + * @param the type of marshaller, implementing this interface + */ +public interface StatefulCopyable> { + + /** + * Creates a copy of this marshaller, with independent state. The current state itself shouldn't + * be copied (it could be "clear" in the copy), only "configuration" of the instance, on which + * {@code copy()} is called, should be inherited in the copy (e. g. the class of object + * serialized). So, {@code copy()} should be transitive, i. e. {@code marshaller.copy()} and + * {@code marshaller.copy().copy()} should result to identical instances. + * + *

The state of the instance on which {@code copy()} is called shouldn't be changed. + * + *

If some marshaller is ought to implement {@code StatefulCopyable} interface (e. g. + * {@link DataAccess}) but is stateless actually, it could return {@code this} from this method. + * + * @return the copy if this marshaller with the same configuration, but independent state + */ + T copy(); + + /** + * Checks if {@code possiblyStatefulCopyable} implements {@code StatefulCopyable}, then returns + * {@link #copy()} of it, otherwise returns the {@code possiblyStatefulCopyable} itself. + * + * @param possiblyStatefulCopyable the instance to {@code copy()} if it implements {@code + * StatefulCopyable}, or to return without modification + * @param the type of the passed instance + * @return the copy of the passed instance with independent state, of the instance back, if it + * doesn't implement {@code StatefulCopyable} + */ + static T copyIfNeeded(T possiblyStatefulCopyable) { + if (possiblyStatefulCopyable instanceof StatefulCopyable) { + //noinspection unchecked + return (T) ((StatefulCopyable) possiblyStatefulCopyable).copy(); + } + return possiblyStatefulCopyable; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java new file mode 100644 index 000000000..1fb1afcef --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BooleanMarshaller.java @@ -0,0 +1,58 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum BooleanMarshaller + implements SizedReader, BytesReader, + SizedWriter, BytesWriter { + INSTANCE; + + @Override + public long size(@NotNull Boolean e) { + return 1L; + } + + @Override + public void write(@NotNull Bytes out, long size, @NotNull Boolean toWrite) { + write(out, toWrite); + } + + @NotNull + @Override + public Boolean read(@NotNull Bytes in, long size, Boolean using) { + return read(in, null); + } + + @NotNull + @Override + public Boolean read(Bytes in, @Nullable Boolean using) { + return in.readByte() != 0; + } + + @Override + public void write(Bytes out, @NotNull Boolean toWrite) { + out.writeByte((byte) (toWrite ? 'Y' : 0)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java new file mode 100644 index 000000000..0918b8c7e --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArrayDataAccess.java @@ -0,0 +1,77 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.HeapBytesStore; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ByteArrayDataAccess extends AbstractData implements DataAccess { + + private transient byte[] array; + private final transient HeapBytesStore bs = HeapBytesStore.uninitialized(); + + @Override + public RandomDataInput bytes() { + return bs; + } + + @Override + public long offset() { + return bs.start(); + } + + @Override + public long size() { + return bs.capacity(); + } + + @Override + public byte[] get() { + return array; + } + + @Override + public byte[] getUsing(@Nullable byte[] using) { + if (using == null || using.length != array.length) + using = new byte[array.length]; + System.arraycopy(array, 0, using, 0, array.length); + return using; + } + + @Override + public Data getData(@NotNull byte[] instance) { + array = instance; + bs.init(instance); + return this; + } + + @Override + public void uninit() { + array = null; + bs.uninit(); + } + + @Override + public DataAccess copy() { + return new ByteArrayDataAccess(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java new file mode 100644 index 000000000..538cfb3d7 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteArraySizedReader.java @@ -0,0 +1,43 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum ByteArraySizedReader implements SizedReader { + INSTANCE; + + @NotNull + @Override + public byte[] read(@NotNull Bytes in, long size, @Nullable byte[] using) { + int resLen = resLen(size); + if (using == null || resLen != using.length) + using = new byte[resLen]; + in.read(using); + return using; + } + + private int resLen(long size) { + if (size < 0L || size > (long) Integer.MAX_VALUE) + throw new IllegalArgumentException("byte[] size should be non-negative int, " + + size + " given. Memory corruption?"); + return (int) size; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java new file mode 100644 index 000000000..2109957fa --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferDataAccess.java @@ -0,0 +1,99 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.*; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import sun.nio.ch.DirectBuffer; + +import java.nio.ByteBuffer; + +public class ByteBufferDataAccess extends AbstractData + implements DataAccess { + + private transient ByteBuffer bb; + private final transient HeapBytesStore heapBytesStore = HeapBytesStore.uninitialized(); + private final transient NativeBytesStore nativeBytesStore = NativeBytesStore.uninitialized(); + final transient VanillaBytes bytes = VanillaBytes.vanillaBytes(); + private transient BytesStore bytesStore; + + @Override + public RandomDataInput bytes() { + return bytesStore; + } + + @Override + public long offset() { + return bb.position(); + } + + @Override + public long size() { + return bb.remaining(); + } + + @Override + public ByteBuffer get() { + return bb; + } + + @Override + public ByteBuffer getUsing(@Nullable ByteBuffer using) { + if (using == null || using.capacity() < bb.remaining()) { + using = ByteBuffer.allocate(bb.remaining()); + } else { + using.position(0); + using.limit(bb.capacity()); + } + bytes.bytesStore(bytesStore, bb.position(), bb.remaining()); + bytes.read(using); + using.flip(); + return using; + } + + @Override + public Data getData(@NotNull ByteBuffer instance) { + bb = instance; + if (instance instanceof DirectBuffer) { + nativeBytesStore.init(instance, false); + bytesStore = nativeBytesStore; + } else { + heapBytesStore.init(instance); + bytesStore = heapBytesStore; + } + return this; + } + + @Override + public void uninit() { + bb = null; + if (bytesStore == nativeBytesStore) { + nativeBytesStore.uninit(); + } else { + heapBytesStore.uninit(); + } + } + + @Override + public DataAccess copy() { + return new ByteBufferDataAccess(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java new file mode 100644 index 000000000..7bd8f6a69 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteBufferSizedReader.java @@ -0,0 +1,46 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.ByteBuffer; + +public enum ByteBufferSizedReader implements SizedReader { + INSTANCE; + + @NotNull + @Override + public ByteBuffer read(@NotNull Bytes in, long size, @Nullable ByteBuffer using) { + if (size < 0L || size > (long) Integer.MAX_VALUE) + throw new IllegalArgumentException("ByteBuffer size should be non-negative int, " + + size + " given. Memory corruption?"); + int bufferCap = (int) size; + if (using == null || using.capacity() < bufferCap) { + using = ByteBuffer.allocate(bufferCap); + } else { + using.position(0); + using.limit(bufferCap); + } + in.read(using); + using.flip(); + return using; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java new file mode 100644 index 000000000..d2694c43a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java @@ -0,0 +1,93 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ByteableDataAccess extends InstanceCreatingMarshaller + implements DataAccess, Data { + + private transient T instance; + + public ByteableDataAccess(Class tClass) { + super(tClass); + } + + @Override + public RandomDataInput bytes() { + return instance.bytesStore(); + } + + @Override + public long offset() { + return instance.offset(); + } + + @Override + public long size() { + return instance.maxSize(); + } + + @Override + public T get() { + return instance; + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + using.bytesStore(instance.bytesStore(), offset(), size()); + return using; + } + + @Override + public int hashCode() { + return dataHashCode(); + } + + @Override + public boolean equals(Object obj) { + return dataEquals(obj); + } + + @Override + public String toString() { + return get().toString(); + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new ByteableDataAccess<>(tClass); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableSizedReader.java new file mode 100644 index 000000000..93fe0d916 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableSizedReader.java @@ -0,0 +1,46 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Reader of {@link Byteable} subclasses. + * + * @param the subtype of {@link Byteable} deserialized + */ +public class ByteableSizedReader extends InstanceCreatingMarshaller + implements SizedReader { + + public ByteableSizedReader(Class tClass) { + super(tClass); + } + + @NotNull + @Override + public final T read(@NotNull Bytes in, long size, @Nullable T using) { + if (using == null) + using = createInstance(); + using.bytesStore(in.bytesStore(), in.readPosition(), size); + return using; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java new file mode 100644 index 000000000..f5f481007 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesAsSizedReader.java @@ -0,0 +1,49 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BytesAsSizedReader + implements SizedReader, StatefulCopyable> { + + private final BytesReader reader; + + public BytesAsSizedReader(BytesReader reader) { + this.reader = reader; + } + + @NotNull + @Override + public T read(Bytes in, long size, @Nullable T using) { + return reader.read(in, using); + } + + @Override + public BytesAsSizedReader copy() { + if (reader instanceof StatefulCopyable) { + return new BytesAsSizedReader<>(StatefulCopyable.copyIfNeeded(reader)); + } else { + return this; + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java new file mode 100644 index 000000000..56910b14b --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java @@ -0,0 +1,98 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BytesMarshallableDataAccess + extends InstanceCreatingMarshaller implements DataAccess, Data { + + transient T instance; + final transient Bytes bytes = Bytes.allocateElasticDirect(1); + + public BytesMarshallableDataAccess(Class tClass) { + super(tClass); + } + + @Override + public RandomDataInput bytes() { + return bytes.bytesStore(); + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return bytes.readRemaining(); + } + + @Override + public T get() { + return instance; + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + using.readMarshallable(bytes); + bytes.readPosition(0); + return using; + } + + @Override + public int hashCode() { + return dataHashCode(); + } + + @Override + public boolean equals(Object obj) { + return dataEquals(obj); + } + + @Override + public String toString() { + return get().toString(); + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + bytes.clear(); + instance.writeMarshallable(bytes); + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new BytesMarshallableDataAccess<>(tClass); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReader.java new file mode 100644 index 000000000..44d840f44 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableReader.java @@ -0,0 +1,47 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BytesMarshallableReader + extends InstanceCreatingMarshaller implements SizedReader, BytesReader { + + public BytesMarshallableReader(Class tClass) { + super(tClass); + } + + @NotNull + @Override + public T read(@NotNull Bytes in, long size, @Nullable T using) { + return read(in, using); + } + + @NotNull + @Override + public T read(Bytes in, @Nullable T using) { + if (using == null) + using = createInstance(); + using.readMarshallable(in); + return using; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java new file mode 100644 index 000000000..c1019eca6 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceBytesWriter.java @@ -0,0 +1,40 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.ListMarshaller; +import net.openhft.chronicle.hash.serialization.SetMarshaller; +import org.jetbrains.annotations.NotNull; + +/** + * {@link BytesWriter} implementation for {@link CharSequence}, for the primary ChronicleMap's + * key or value type {@link CharSequenceSizedWriter} + {@link StringSizedReader} are more + * effective (because don't store the size twice), so this writer is useful in conjunction with + * {@link ListMarshaller} or {@link SetMarshaller}. + * + * @see CharSequenceBytesWriter + */ +public enum CharSequenceBytesWriter implements BytesWriter { + INSTANCE; + + @Override + public void write(Bytes out, @NotNull CharSequence toWrite) { + out.writeUtf8(toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java new file mode 100644 index 000000000..a23e0da41 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedReader.java @@ -0,0 +1,56 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class CharSequenceSizedReader + implements SizedReader, StatefulCopyable { + + private final transient StringBuilder sb = new StringBuilder(); + + @NotNull + @Override + public CharSequence read( + @NotNull Bytes in, long size, @Nullable CharSequence using) { + if (0 > size || size > Integer.MAX_VALUE) + throw new IllegalStateException("positive int size expected, " + size + " given"); + int csLen = (int) size; + if (!(using instanceof StringBuilder)) { + sb.setLength(0); + sb.ensureCapacity(csLen); + BytesUtil.parseUtf8(in, sb, csLen); + return sb.toString(); + } else { + StringBuilder usingSB = (StringBuilder) using; + usingSB.setLength(0); + usingSB.ensureCapacity(csLen); + BytesUtil.parseUtf8(in, usingSB, csLen); + return usingSB; + } + } + + @Override + public CharSequenceSizedReader copy() { + return new CharSequenceSizedReader(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/DeserializationFactoryConfigurableBytesReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java similarity index 58% rename from src/main/java/net/openhft/chronicle/hash/serialization/DeserializationFactoryConfigurableBytesReader.java rename to src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java index 02a87d1c6..578d3c1c8 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/DeserializationFactoryConfigurableBytesReader.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/CharSequenceSizedWriter.java @@ -14,15 +14,23 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.hash.serialization; +package net.openhft.chronicle.hash.serialization.impl; -import net.openhft.lang.io.serialization.ObjectFactory; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.serialization.SizedWriter; import org.jetbrains.annotations.NotNull; -public interface DeserializationFactoryConfigurableBytesReader> - extends BytesReader { +public enum CharSequenceSizedWriter implements SizedWriter { + INSTANCE; - @NotNull - R withDeserializationFactory(@NotNull ObjectFactory deserializationFactory); + @Override + public long size(@NotNull CharSequence toWrite) { + return BytesUtil.utf8Length(toWrite); + } + + @Override + public void write(@NotNull Bytes out, long size, @NotNull CharSequence toWrite) { + BytesUtil.appendUtf8(out, toWrite); + } } diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java new file mode 100644 index 000000000..838e7b3d1 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ConstantSizeMarshaller.java @@ -0,0 +1,63 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizeMarshaller; + +public final class ConstantSizeMarshaller implements SizeMarshaller { + private final long constantSize; + + public ConstantSizeMarshaller(long constantSize) { + this.constantSize = constantSize; + } + + @Override + public int storingLength(long size) { + return 0; + } + + @Override + public long minStorableSize() { + return constantSize; + } + + @Override + public long maxStorableSize() { + return constantSize; + } + + @Override + public int minStoringLengthOfSizesInRange(long minSize, long maxSize) { + return 0; + } + + @Override + public int maxStoringLengthOfSizesInRange(long minSize, long maxSize) { + return 0; + } + + @Override + public void writeSize(Bytes out, long sizeToWrite) { + // do nothing + } + + @Override + public long readSize(Bytes in) { + return constantSize; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java new file mode 100644 index 000000000..0b2ae48ed --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java @@ -0,0 +1,58 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum DoubleMarshaller + implements SizedReader, BytesReader, + SizedWriter, BytesWriter { + INSTANCE; + + @NotNull + @Override + public Double read(@NotNull Bytes in, long size, @Nullable Double using) { + return in.readDouble(); + } + + @Override + public long size(@NotNull Double toWrite) { + return 8L; + } + + @Override + public void write(@NotNull Bytes out, long size, @NotNull Double toWrite) { + out.writeDouble(toWrite); + } + + @NotNull + @Override + public Double read(Bytes in, @Nullable Double using) { + return in.readDouble(); + } + + @Override + public void write(Bytes out, @NotNull Double toWrite) { + out.writeDouble(toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java new file mode 100644 index 000000000..e63ab8ce7 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java @@ -0,0 +1,107 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +public class ExternalBytesMarshallableDataAccess extends InstanceCreatingMarshaller + implements DataAccess, Data { + + private final SizedReader reader; + private final BytesWriter writer; + private transient T instance; + private final transient Bytes bytes = Bytes.allocateElasticDirect(1); + + public ExternalBytesMarshallableDataAccess( + Class tClass, SizedReader reader, BytesWriter writer) { + super(tClass); + this.writer = writer; + this.reader = reader; + } + + @Override + public RandomDataInput bytes() { + return bytes.bytesStore(); + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return bytes.readRemaining(); + } + + @Override + public T get() { + return instance; + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + T result = reader.read(bytes, size(), using); + bytes.readPosition(0); + return result; + } + + @Override + public int hashCode() { + return dataHashCode(); + } + + @Override + public boolean equals(Object obj) { + return dataEquals(obj); + } + + @Override + public String toString() { + return get().toString(); + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + bytes.clear(); + writer.write(bytes, instance); + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new ExternalBytesMarshallableDataAccess<>( + tClass, copyIfNeeded(reader), copyIfNeeded(writer)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java new file mode 100644 index 000000000..b8037c545 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableDataAccess.java @@ -0,0 +1,76 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class ExternalizableDataAccess extends SerializableDataAccess { + + protected final Class tClass; + + public ExternalizableDataAccess(Class tClass) { + this.tClass = tClass; + } + + protected T createInstance() { + try { + return tClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + try { + using.readExternal(new ObjectInputStream(in)); + bytes.readPosition(0); + return using; + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + bytes.clear(); + try { + ObjectOutputStream out = new ObjectOutputStream(this.out); + instance.writeExternal(out); + out.flush(); + return this; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public DataAccess copy() { + return new ExternalizableDataAccess<>(tClass); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableReader.java new file mode 100644 index 000000000..1684501dc --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalizableReader.java @@ -0,0 +1,54 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInputStream; + +public class ExternalizableReader extends InstanceCreatingMarshaller + implements SizedReader, BytesReader { + + public ExternalizableReader(Class tClass) { + super(tClass); + } + + @NotNull + @Override + public T read(@NotNull Bytes in, long size, @Nullable T using) { + return read(in, using); + } + + @NotNull + @Override + public T read(Bytes in, @Nullable T using) { + if (using == null) + using = createInstance(); + try { + using.readExternal(new ObjectInputStream(in.inputStream())); + return using; + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java new file mode 100644 index 000000000..d2f22eb88 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java @@ -0,0 +1,71 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.map.ChronicleMapBuilder; + +import java.lang.reflect.Constructor; + +/** + * Holds new instance creation logic, common for many {@link DataAccess} and {@link SizedReader} + * implementations + * + * @param the type of objects deserialized + */ +public abstract class InstanceCreatingMarshaller { + + /** + * The class of objects deserialized. + */ + protected final Class tClass; + + /** + * Constructor for use in subclasses. + * + * @param tClass the class of objects deserialized + */ + protected InstanceCreatingMarshaller(Class tClass) { + this.tClass = tClass; + } + + /** + * Creates a new {@code T} instance by calling {@link Class#newInstance()}. If you need + * different logic, i. e. calling a constructor with parameter, override this method in a + * subclass of the specific {@link DataAccess} or {@link SizedReader} and configure in {@link + * ChronicleMapBuilder}. + * + * @return a new instance to return from {@link Data#getUsing(Object)} or {@link + * SizedReader#read(net.openhft.chronicle.bytes.Bytes, long, Object)} method + */ + protected T createInstance() { + try { + return tClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException("Some of default marshallers, chosen for the type\n" + + tClass + " by default, delegates to \n" + + this.getClass().getName() + " which assumes the type has a public no-arg\n" + + "constructor. If this is not true, you should either extend the marshaller,\n" + + "overriding createInstance() and copy() (if defined), or write and\n" + + "configure your own marshaller for " + tClass + " type from scratch, and\n" + + "configure for the Chronicle Map via keyMarshaller[s]() or\n" + + "valueMarshaller[s]() methods", e); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java new file mode 100644 index 000000000..c9d015f96 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java @@ -0,0 +1,58 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum IntegerMarshaller + implements SizedReader, BytesReader, + SizedWriter, BytesWriter { + INSTANCE; + + @NotNull + @Override + public Integer read(@NotNull Bytes in, long size, @Nullable Integer using) { + return in.readInt(); + } + + @Override + public long size(@NotNull Integer toWrite) { + return 4L; + } + + @Override + public void write(@NotNull Bytes out, long size, @NotNull Integer toWrite) { + out.writeInt(toWrite); + } + + @NotNull + @Override + public Integer read(Bytes in, @Nullable Integer using) { + return in.readInt(); + } + + @Override + public void write(Bytes out, @NotNull Integer toWrite) { + out.writeInt(toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java new file mode 100644 index 000000000..b331142d5 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java @@ -0,0 +1,58 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum LongMarshaller + implements SizedReader, BytesReader, + SizedWriter, BytesWriter { + INSTANCE; + + @Override + public long size(@NotNull Long toWrite) { + return 8L; + } + + @NotNull + @Override + public Long read(@NotNull Bytes in, long size, @Nullable Long using) { + return in.readLong(); + } + + @Override + public void write(@NotNull Bytes out, long size, @NotNull Long toWrite) { + out.writeLong(toWrite); + } + + @NotNull + @Override + public Long read(Bytes in, @Nullable Long using) { + return in.readLong(); + } + + @Override + public void write(Bytes out, @NotNull Long toWrite) { + out.writeLong(toWrite); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java new file mode 100644 index 000000000..646408384 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java @@ -0,0 +1,41 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +public class NotReusingSizedMarshallableDataAccess extends SizedMarshallableDataAccess { + public NotReusingSizedMarshallableDataAccess( + Class tClass, SizedReader sizedReader, SizedWriter sizedWriter) { + super(tClass, sizedReader, sizedWriter); + } + + @Override + protected T createInstance() { + return null; + } + + @Override + public DataAccess copy() { + return new NotReusingSizedMarshallableDataAccess<>( + tClass, copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java new file mode 100644 index 000000000..f9c97db3c --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableDataAccess.java @@ -0,0 +1,92 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.*; + +public class SerializableDataAccess extends AbstractData + implements DataAccess { + + transient T instance; + final transient Bytes bytes = Bytes.allocateElasticDirect(1); + final transient OutputStream out = bytes.outputStream(); + final transient InputStream in = bytes.inputStream(); + + @Override + public RandomDataInput bytes() { + return bytes.bytesStore(); + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return bytes.readRemaining(); + } + + @Override + public T get() { + return instance; + } + + // TODO reuse using object + @Override + public T getUsing(@Nullable T using) { + try { + T result = (T) new ObjectInputStream(in).readObject(); + bytes.readPosition(0); + return result; + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + bytes.clear(); + try { + ObjectOutputStream out = new ObjectOutputStream(this.out); + out.writeObject(instance); + out.flush(); + return this; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new SerializableDataAccess<>(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java new file mode 100644 index 000000000..f07f0c2cd --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializableReader.java @@ -0,0 +1,47 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; + +public class SerializableReader + implements SizedReader, BytesReader { + + @NotNull + @Override + public T read(@NotNull Bytes in, long size, @Nullable T using) { + return read(in, using); + } + + @NotNull + @Override + public T read(Bytes in, @Nullable T using) { + try { + return (T) new ObjectInputStream(in.inputStream()).readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java new file mode 100644 index 000000000..bee219116 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java @@ -0,0 +1,243 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.core.OS; +import net.openhft.chronicle.hash.serialization.*; +import net.openhft.chronicle.values.ValueModel; +import net.openhft.chronicle.values.Values; + +import java.io.*; +import java.lang.reflect.Modifier; +import java.nio.ByteBuffer; + +import static net.openhft.chronicle.hash.serialization.SizeMarshaller.constant; +import static net.openhft.chronicle.hash.serialization.SizeMarshaller.stopBit; + +public final class SerializationBuilder implements Cloneable, Serializable { + private static final long serialVersionUID = 0L; + + private static boolean concreteClass(Class c) { + return !c.isInterface() && !Modifier.isAbstract(c.getModifiers()); + } + + public final Class tClass; + private SizeMarshaller sizeMarshaller = stopBit(); + private SizedReader reader; + private DataAccess dataAccess; + + public final boolean sizeIsStaticallyKnown; + + boolean serializesGeneratedClasses = false; + + @SuppressWarnings("unchecked") + public SerializationBuilder(Class tClass) { + this.tClass = tClass; + configureByDefault(tClass); + sizeIsStaticallyKnown = constantSizeMarshaller(); + } + + @SuppressWarnings("unchecked") + private void configureByDefault(Class tClass) { + + if (tClass.isInterface()) { + try { + // Acquire a model before assigning readers/writers + // if the interface is not + ValueModel valueModel = ValueModel.acquire(tClass); + reader((BytesReader) new ValueReader<>(tClass)); + dataAccess(new ValueDataAccess<>(tClass)); + sizeMarshaller(constant((long) valueModel.sizeInBytes())); + serializesGeneratedClasses = true; + return; + } catch (Exception e) { + try { + tClass = Values.nativeClassFor(tClass); + serializesGeneratedClasses = true; + } catch (Exception ex) { + // ignore, fall through + } + // ignore, fall through + } + } + + if (concreteClass(tClass) && Byteable.class.isAssignableFrom(tClass)) { + reader(new ByteableSizedReader<>((Class) tClass)); + dataAccess((DataAccess) new ByteableDataAccess<>((Class) tClass)); + sizeMarshaller(constant(((Byteable) OS.memory().allocateInstance(tClass)).maxSize())); + } else if (tClass == CharSequence.class) { + reader((SizedReader) new CharSequenceSizedReader()); + writer((SizedWriter) CharSequenceSizedWriter.INSTANCE); + } else if (tClass == StringBuilder.class) { + reader((SizedReader) StringBuilderSizedReader.INSTANCE); + writer((SizedWriter) CharSequenceSizedWriter.INSTANCE); + } else if (tClass == String.class) { + reader((SizedReader) new StringSizedReader()); + notReusingWriter((SizedWriter) CharSequenceSizedWriter.INSTANCE); + } else if (tClass == Boolean.class) { + reader((SizedReader) BooleanMarshaller.INSTANCE); + notReusingWriter((SizedWriter) BooleanMarshaller.INSTANCE); + sizeMarshaller(constant(1)); + } else if (tClass == Long.class) { + reader((SizedReader) LongMarshaller.INSTANCE); + notReusingWriter((SizedWriter) LongMarshaller.INSTANCE); + sizeMarshaller(constant(8)); + } else if (tClass == Double.class) { + reader((SizedReader) DoubleMarshaller.INSTANCE); + notReusingWriter((SizedWriter) DoubleMarshaller.INSTANCE); + sizeMarshaller(constant(8)); + } else if (tClass == Integer.class) { + reader((SizedReader) IntegerMarshaller.INSTANCE); + notReusingWriter((SizedWriter) IntegerMarshaller.INSTANCE); + sizeMarshaller(constant(4)); + } else if (tClass == byte[].class) { + reader((SizedReader) ByteArraySizedReader.INSTANCE); + dataAccess((DataAccess) new ByteArrayDataAccess()); + } else if (tClass == ByteBuffer.class) { + reader((SizedReader) ByteBufferSizedReader.INSTANCE); + dataAccess((DataAccess) new ByteBufferDataAccess()); + } else if (concreteClass(tClass) && BytesMarshallable.class.isAssignableFrom(tClass)) { + reader((BytesReader) new BytesMarshallableReader<>((Class) tClass)); + dataAccess(new BytesMarshallableDataAccess<>((Class) tClass)); + } else if (concreteClass(tClass) && Externalizable.class.isAssignableFrom(tClass)) { + reader((BytesReader) new ExternalizableReader<>((Class) tClass)); + dataAccess(new ExternalizableDataAccess<>((Class) tClass)); + } else { + reader((SizedReader) new SerializableReader<>()); + dataAccess((DataAccess) new SerializableDataAccess<>()); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.writeBoolean(serializesGeneratedClasses); + if (serializesGeneratedClasses) { + out.writeObject(tClass); + } + out.defaultWriteObject(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + boolean generatedClassesSerialized = in.readBoolean(); + if (generatedClassesSerialized) { + Class eClass = (Class) in.readObject(); + // This is needed because ValueDataAccess/ValueReader tries to serialize/deserialize + // generated classes, requires them to be generated beforehand + new SerializationBuilder<>(eClass); + } + in.defaultReadObject(); + } + + public void reader(SizedReader reader) { + this.reader = reader; + } + + public void reader(BytesReader reader) { + this.reader = new BytesAsSizedReader<>(reader); + } + + public SizedReader reader() { + return StatefulCopyable.copyIfNeeded(reader); + } + + public void dataAccess(DataAccess dataAccess) { + this.dataAccess = dataAccess; + } + + public DataAccess dataAccess() { + return dataAccess.copy(); + } + + public void writer(SizedWriter writer) { + dataAccess(new SizedMarshallableDataAccess<>(tClass, reader, writer)); + } + + private void notReusingWriter(SizedWriter writer) { + dataAccess(new NotReusingSizedMarshallableDataAccess<>(tClass, reader, writer)); + } + + public void writer(BytesWriter writer) { + dataAccess(new ExternalBytesMarshallableDataAccess<>(tClass, reader, writer)); + } + + public long serializationSize(T sampleObject) { + return dataAccess().getData(sampleObject).size(); + } + + public long constantSizeBySample(T sampleObject) { + long constantSize = serializationSize(sampleObject); + if (sizeIsStaticallyKnown) { + long expectedConstantSize = constantSize(); + if (constantSize != expectedConstantSize) { + throw new IllegalStateException("Although configuring constant size by sample " + + "is not forbidden for types which size we already know statically, they " + + "should be the same. For " + tClass + " we know constant size is " + + expectedConstantSize + " statically, configured sample is " + sampleObject + + " which size in serialized form is " + constantSize); + } + } + sizeMarshaller(constant(constantSize)); + return constantSize; + } + + public SizeMarshaller sizeMarshaller() { + return sizeMarshaller; + } + + public boolean constantSizeMarshaller() { + SizeMarshaller marshaller = sizeMarshaller(); + boolean feature1 = marshaller.storingLength(marshaller.maxStorableSize()) == 0; + boolean feature2 = marshaller.minStorableSize() == marshaller.maxStorableSize(); + if (feature1 && feature2) + return true; + if (!feature1 && !feature2) + return false; + throw new IllegalStateException("SizeMarshaller " + marshaller + " has only 1 of 2 " + + "constant features: storingLength == 0 and minStorableSize == maxStorableSize." + + " Should have both"); + } + + public boolean constantStoringLengthSizeMarshaller() { + SizeMarshaller marshaller = sizeMarshaller(); + long minStorableSize = marshaller.minStorableSize(); + long maxStorableSize = marshaller.maxStorableSize(); + return marshaller.minStoringLengthOfSizesInRange(minStorableSize, maxStorableSize) == + marshaller.maxStoringLengthOfSizesInRange(minStorableSize, maxStorableSize); + } + + public long constantSize() { + if (sizeMarshaller().minStorableSize() != sizeMarshaller().maxStorableSize()) + throw new AssertionError(); + return sizeMarshaller().minStorableSize(); + } + + public SerializationBuilder sizeMarshaller(SizeMarshaller sizeMarshaller) { + this.sizeMarshaller = sizeMarshaller; + return this; + } + + @Override + public SerializationBuilder clone() { + try { + //noinspection unchecked + return (SerializationBuilder) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java new file mode 100644 index 000000000..1926bf3ad --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java @@ -0,0 +1,107 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + +public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller + implements DataAccess, Data { + + final SizedReader sizedReader; + final SizedWriter sizedWriter; + private transient T instance; + private final transient Bytes bytes = Bytes.allocateElasticDirect(1); + + public SizedMarshallableDataAccess( + Class tClass, SizedReader sizedReader, SizedWriter sizedWriter) { + super(tClass); + this.sizedWriter = sizedWriter; + this.sizedReader = sizedReader; + } + + @Override + public RandomDataInput bytes() { + return bytes.bytesStore(); + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return bytes.readRemaining(); + } + + @Override + public T get() { + return instance; + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + T result = sizedReader.read(bytes, size(), using); + bytes.readPosition(0); + return result; + } + + @Override + public int hashCode() { + return dataHashCode(); + } + + @Override + public boolean equals(Object obj) { + return dataEquals(obj); + } + + @Override + public String toString() { + return get().toString(); + } + + @Override + public Data getData(@NotNull T instance) { + this.instance = instance; + bytes.clear(); + sizedWriter.write(bytes, sizedWriter.size(instance), instance); + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new SizedMarshallableDataAccess<>( + tClass, copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter)); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java new file mode 100644 index 000000000..d76dadfcc --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StopBitSizeMarshaller.java @@ -0,0 +1,78 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.serialization.SizeMarshaller; + +import static java.lang.Math.max; +import static java.lang.Math.min; + +public enum StopBitSizeMarshaller implements SizeMarshaller { + INSTANCE; + + private static final long MIN_ENCODABLE_SIZE = Long.MIN_VALUE; + private static final long MAX_ENCODABLE_SIZE = Long.MAX_VALUE; + + private static void rangeChecks(long minSize, long maxSize) { + if (minSize > maxSize) + throw new IllegalArgumentException("minSize = " + minSize + ", maxSize = " + maxSize); + } + + @Override + public int storingLength(long size) { + return BytesUtil.stopBitLength(size); + } + + @Override + public long minStorableSize() { + return MIN_ENCODABLE_SIZE; + } + + @Override + public long maxStorableSize() { + return MAX_ENCODABLE_SIZE; + } + + @Override + public int minStoringLengthOfSizesInRange(long minSize, long maxSize) { + rangeChecks(minSize, maxSize); + // different signs + if (minSize * maxSize < 0) { + // the range includes 0 which encoding length is 1 + return 1; + } + return min(storingLength(minSize), storingLength(maxSize)); + } + + @Override + public int maxStoringLengthOfSizesInRange(long minSize, long maxSize) { + rangeChecks(minSize, maxSize); + return max(storingLength(minSize), storingLength(maxSize)); + } + + @Override + public void writeSize(Bytes out, long sizeToWrite) { + BytesUtil.writeStopBit(out, sizeToWrite); + } + + @Override + public long readSize(Bytes in) { + return BytesUtil.readStopBit(in); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java new file mode 100644 index 000000000..d2c5756a3 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBuilderSizedReader.java @@ -0,0 +1,43 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public enum StringBuilderSizedReader implements SizedReader { + INSTANCE; + + @NotNull + @Override + public StringBuilder read(Bytes in, long size, @Nullable StringBuilder using) { + if (0 > size || size > Integer.MAX_VALUE) + throw new IllegalStateException("positive int size expected, " + size + " given"); + int csLen = (int) size; + if (using == null) { + using = new StringBuilder(csLen); + } else { + using.setLength(0); + using.ensureCapacity(csLen); + } + BytesUtil.parseUtf8(in, using, csLen); + return using; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java new file mode 100644 index 000000000..a84d7608d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringBytesReader.java @@ -0,0 +1,52 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.ListMarshaller; +import net.openhft.chronicle.hash.serialization.SetMarshaller; +import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * {@link BytesReader} implementation for String, for the primary ChronicleMap's key of value type + * {@link StringSizedReader} + {@link CharSequenceSizedWriter} are more effective (because don't + * store the size twice), so this reader is useful in conjunction with {@link ListMarshaller} or + * {@link SetMarshaller}. + * + * @see CharSequenceBytesWriter + */ +public class StringBytesReader + implements BytesReader, StatefulCopyable { + + private final transient StringBuilder sb = new StringBuilder(); + + @NotNull + @Override + public String read(Bytes in, @Nullable String using) { + sb.setLength(0); + in.readUtf8(sb); + return sb.toString(); + } + + @Override + public StringBytesReader copy() { + return new StringBytesReader(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java new file mode 100644 index 000000000..487052579 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/StringSizedReader.java @@ -0,0 +1,44 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class StringSizedReader implements SizedReader, StatefulCopyable { + + private final transient StringBuilder sb = new StringBuilder(); + + @NotNull + @Override + public String read(@NotNull Bytes in, long size, @Nullable String using) { + if (0 > size || size > Integer.MAX_VALUE) + throw new IllegalStateException("positive int size expected, " + size + " given"); + sb.setLength(0); + BytesUtil.parseUtf8(in, sb, (int) size); + return sb.toString(); + } + + @Override + public StringSizedReader copy() { + return new StringSizedReader(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java new file mode 100644 index 000000000..c6f952c59 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueDataAccess.java @@ -0,0 +1,118 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.values.Copyable; +import net.openhft.chronicle.values.Values; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.ObjectInputStream; + +import static net.openhft.chronicle.bytes.NativeBytesStore.nativeStoreWithFixedCapacity; + +public class ValueDataAccess extends AbstractData implements DataAccess { + + protected final Class valueType; + private transient Byteable nativeInstance; + private transient Copyable nativeInstanceAsCopyable; + protected transient Class nativeClass; + protected transient Class heapClass; + private transient Byteable instance; + + public ValueDataAccess(Class valueType) { + this.valueType = valueType; + initTransients(); + } + + private void initTransients() { + nativeInstance = (Byteable) Values.newNativeReference(valueType); + nativeInstanceAsCopyable = (Copyable) nativeInstance; + nativeClass = (Class) nativeInstance.getClass(); + heapClass = Values.heapClassFor(valueType); + nativeInstance.bytesStore(nativeStoreWithFixedCapacity(nativeInstance.maxSize()), + 0, nativeInstance.maxSize()); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + initTransients(); + } + + protected T createInstance() { + try { + return heapClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public RandomDataInput bytes() { + return instance.bytesStore(); + } + + @Override + public long offset() { + return instance.offset(); + } + + @Override + public long size() { + return instance.maxSize(); + } + + @Override + public T get() { + return (T) instance; + } + + @Override + public T getUsing(@Nullable T using) { + if (using == null) + using = createInstance(); + ((Copyable) using).copyFrom(instance); + return using; + } + + @Override + public Data getData(@NotNull T instance) { + if (instance.getClass() == nativeClass) { + this.instance = (Byteable) instance; + } else { + nativeInstanceAsCopyable.copyFrom(instance); + this.instance = nativeInstance; + } + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public DataAccess copy() { + return new ValueDataAccess<>(valueType); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java new file mode 100644 index 000000000..1f8577ff5 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ValueReader.java @@ -0,0 +1,92 @@ +/* + * 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.hash.serialization.impl; + +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.StatefulCopyable; +import net.openhft.chronicle.values.Copyable; +import net.openhft.chronicle.values.Values; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.ObjectInputStream; + +public class ValueReader + implements SizedReader, BytesReader, StatefulCopyable> { + + protected final Class valueType; + protected transient Class heapClass; + private transient Class nativeClass; + private transient Byteable nativeReference; + + public ValueReader(Class valueType) { + this.valueType = valueType; + initTransients(); + } + + private void initTransients() { + heapClass = Values.heapClassFor(valueType); + nativeClass = Values.nativeClassFor(valueType); + nativeReference = (Byteable) Values.newNativeReference(valueType); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + initTransients(); + } + + protected T createInstance() { + try { + return heapClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @NotNull + @Override + public T read(@NotNull Bytes in, long size, @Nullable T using) { + if (size != nativeReference.maxSize()) + throw new IllegalArgumentException(); + return read(in, using); + } + + @NotNull + @Override + public T read(Bytes in, @Nullable T using) { + if (using != null && using.getClass() == nativeClass) { + ((Byteable) using).bytesStore(in.bytesStore(), in.readPosition(), + nativeReference.maxSize()); + return using; + } + if (using == null) + using = createInstance(); + nativeReference.bytesStore(in.bytesStore(), in.readPosition(), + nativeReference.maxSize()); + ((Copyable) using).copyFrom(nativeReference); + return using; + } + + @Override + public ValueReader copy() { + return new ValueReader<>(valueType); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/package-info.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/package-info.java new file mode 100644 index 000000000..8b6d74675 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/package-info.java @@ -0,0 +1,38 @@ +/* + * 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 . + */ + +/** + * The package contains many classes, implementing interfaces from the parent {@code + * net.openhft.chronicle.hash.serialization} package, and shouldn't be used in the user code (in 90% + * of cases). These classes are used automatically under the hood, primarily though {@link + * net.openhft.chronicle.hash.serialization.impl.SerializationBuilder} and it's use in {@link + * net.openhft.chronicle.map.ChronicleMapBuilder}. That is why these classes are put into the + * separate package (this package) and excluded from the generated Javadocs, to reduce noise. + * + *

The remaining 5% of cases when these classes might be useful in the user code -- overriding + * with different {@link + * net.openhft.chronicle.hash.serialization.impl.InstanceCreatingMarshaller#createInstance()} logic, + * when the default strategy (call of the default constructor) doesn't work. + * + *

Another remaining 5% of cases: configuration of complex marshallers with sub-marshallers, see + * {@link net.openhft.chronicle.hash.serialization.ListMarshaller}, {@link + * net.openhft.chronicle.hash.serialization.SetMarshaller} and {@link + * net.openhft.chronicle.hash.serialization.MapMarshaller} for some examples. + * + *

Classes in this package are undocumented and not guaranteed to stay compatible between + * Chronicle Map versions; refer to the source code and use on your own risk. + */ +package net.openhft.chronicle.hash.serialization.impl; \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BasicCopyingMetaBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/BasicCopyingMetaBytesInterop.java deleted file mode 100644 index a354b7006..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BasicCopyingMetaBytesInterop.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; - -public abstract class BasicCopyingMetaBytesInterop implements MetaBytesInterop { - private static final long serialVersionUID = 0L; - - static final Provider provider = - Provider.of(DirectBytesBuffer.class); - - static abstract class BasicCopyingMetaBytesInteropProvider> implements MetaProvider { - private static final long serialVersionUID = 0L; - - @Override - public ThreadLocalCopies getCopies(ThreadLocalCopies copies) { - return provider.getCopies(copies); - } - } - - final DirectBytesBuffer buffer; - transient long size; - transient long hash; - - protected BasicCopyingMetaBytesInterop(DirectBytesBuffer buffer) { - this.buffer = buffer; - } - - @Override - public long size(W writer, E e) { - return size; - } - - @Override - public boolean startsWith(W writer, Bytes bytes, E e) { - return bytes.startsWith(buffer.buffer); - } - - @Override - public long hash(W writer, LongHashFunction hashFunction, E e) { - long h; - if ((h = hash) == 0L) - return hash = hashFunction.hashBytes(buffer.buffer); - return h; - } - - @Override - public void write(W writer, Bytes bytes, E e) { - bytes.write(buffer.buffer, buffer.buffer.position(), size); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BooleanMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/BooleanMarshaller.java deleted file mode 100644 index 4c3482c53..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BooleanMarshaller.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -public enum BooleanMarshaller - implements BytesInterop, BytesReader, SizeMarshaller { - INSTANCE; - - @Override - public long size(@NotNull Boolean e) { - return 1L; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return 1L; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == 1L; - // do nothing - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull Boolean e) { - return e == (bytes.readByte(bytes.position()) != 0); - } - - @Override - public boolean equivalent(@NotNull Boolean a, @NotNull Boolean b) { - return a.booleanValue() == b.booleanValue(); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull Boolean e) { - return hashFunction.hashByte(e ? (byte) 'Y' : 0); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull Boolean e) { - bytes.writeByte(e ? 'Y' : 0); - } - - @Override - public long readSize(Bytes bytes) { - return 1L; - } - - @NotNull - @Override - public Boolean read(@NotNull Bytes bytes, long size) { - return bytes.readByte() != 0; - } - - @NotNull - @Override - public Boolean read(@NotNull Bytes bytes, long size, Boolean toReuse) { - return bytes.readByte() != 0; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteArrayMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteArrayMarshaller.java deleted file mode 100644 index 82f0fab9e..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteArrayMarshaller.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; - -public enum ByteArrayMarshaller implements BytesInterop, BytesReader { - INSTANCE; - - @Override - public long size(@NotNull byte[] ba) { - return ba.length; - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull byte[] ba) { - if (bytes.capacity() - bytes.position() < (long) ba.length) - return false; - long pos = bytes.position(); - for (int i = 0; i < ba.length; i++) { - if (bytes.readByte(pos + i) != ba[i]) - return false; - } - return true; - } - - @Override - public boolean equivalent(@NotNull byte[] a, @NotNull byte[] b) { - return Arrays.equals(a, b); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull byte[] ba) { - return hashFunction.hashBytes(ba); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull byte[] ba) { - bytes.write(ba); - } - - @NotNull - @Override - public byte[] read(@NotNull Bytes bytes, long size) { - byte[] ba = new byte[resLen(size)]; - bytes.read(ba); - return ba; - } - - @NotNull - @Override - public byte[] read(@NotNull Bytes bytes, long size, byte[] toReuse) { - int resLen = resLen(size); - if (toReuse == null || resLen != toReuse.length) - toReuse = new byte[resLen]; - bytes.read(toReuse); - return toReuse; - } - - private int resLen(long size) { - if (size < 0L || size > (long) Integer.MAX_VALUE) - throw new IllegalArgumentException("byte[] size should be non-negative int, " + - size + " given. Memory corruption?"); - return (int) size; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteBufferMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteBufferMarshaller.java deleted file mode 100644 index 0d1b7b191..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteBufferMarshaller.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.nio.ByteBuffer; - -public enum ByteBufferMarshaller implements BytesInterop, BytesReader { - INSTANCE; - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull ByteBuffer bb) { - int inputRemaining = bb.remaining(); - if(bytes.capacity() - bytes.position() < (long) inputRemaining) - return false; - - long pos = bytes.position(); - int inputPos = bb.position(); - - int i = 0; - if (bytes.byteOrder() == bb.order()) { - for (; i < inputRemaining - 7; i += 8) { - if (bytes.readLong(pos + (long) i) != bb.getLong(inputPos + i)) - return false; - } - if (i < inputRemaining - 3) { - if (bytes.readInt(pos + (long) i) != bb.getInt(inputPos + i)) - return false; - i += 4; - } - if (i < inputRemaining - 1) { - if (bytes.readChar(pos + (long) i) != bb.getChar(inputPos + i)) - return false; - i += 2; - } - } - for(; i < inputRemaining; i++) { - if (bytes.readByte(pos + (long) i) != bb.get(inputPos + i)) - return false; - } - - return true; - } - - @Override - public boolean equivalent(@NotNull ByteBuffer a, @NotNull ByteBuffer b) { - return a.equals(b); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull ByteBuffer bb) { - return hashFunction.hashBytes(bb); - } - - @NotNull - @Override - public ByteBuffer read(@NotNull Bytes bytes, long size) { - return read(bytes, size, null); - } - - @NotNull - @Override - public ByteBuffer read(@NotNull Bytes bytes, long size, @Nullable ByteBuffer toReuse) { - if (size < 0L || size > (long) Integer.MAX_VALUE) - throw new IllegalArgumentException("ByteBuffer size should be non-negative int, " + - size + " given. Memory corruption?"); - int intSize = (int) size; - if (toReuse == null || toReuse.capacity() < intSize) { - toReuse = ByteBuffer.allocate(intSize); - } else { - toReuse.position(0); - toReuse.limit(intSize); - } - bytes.read(toReuse); - toReuse.flip(); - return toReuse; - } - - @Override - public long size(@NotNull ByteBuffer bb) { - return (long) bb.remaining(); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull ByteBuffer bb) { - int position = bb.position(); - bytes.write(bb); - bb.position(position); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteableMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteableMarshaller.java deleted file mode 100644 index 786d5af96..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ByteableMarshaller.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.DeserializationFactoryConfigurableBytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.MultiStoreBytes; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.io.serialization.ObjectFactory; -import net.openhft.lang.model.Byteable; -import org.jetbrains.annotations.NotNull; - -public abstract class ByteableMarshaller - implements BytesInterop, MetaBytesInterop, - DeserializationFactoryConfigurableBytesReader>, - SizeMarshaller { - private static final long serialVersionUID = 0L; - - public static ByteableMarshaller of(@NotNull Class eClass) { - return new Default<>(eClass); - } - - @NotNull - @Override - public ByteableMarshaller withDeserializationFactory( - @NotNull ObjectFactory deserializationFactory) { - return new WithCustomFactory<>(tClass, deserializationFactory); - } - - @NotNull - private final Class tClass; - private long size; - - private ByteableMarshaller(@NotNull Class tClass) { - this.tClass = tClass; - } - - void initSize() { - try { - size = getInstance().maxSize(); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - - @Override - public long size(@NotNull E e) { - return size; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return size; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == this.size; - // do nothing - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull E e) { - if (bytes.capacity() - bytes.position() < size) - return false; - Bytes input = e.bytes(); - long pos = bytes.position(), inputPos = e.offset(); - - int i = 0; - for (; i < size - 7; i += 8) { - if (bytes.readLong(pos + i) != input.readLong(inputPos + i)) - return false; - } - for (; i < size; i++) { - if (bytes.readByte(pos + i) != input.readByte(inputPos + i)) - return false; - } - return true; - } - - @Override - public boolean equivalent(@NotNull E a, @NotNull E b) { - return a.bytes().compare(a.offset(), b.bytes(), b.offset(), size); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull E e) { - return hashFunction.hashBytes(e.bytes(), e.offset(), size); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull E e) { - Bytes eBytes = e.bytes(); - if (eBytes != null) { - if (eBytes != bytes || bytes.position() != e.offset()) { - bytes.write(eBytes, e.offset(), size); - } else { - bytes.skip(size); - } - } else { - throw new NullPointerException("You are trying to write a byteable object of " + - e.getClass() + ", " + - "which bytes are not assigned. I. e. most likely the object is uninitialized."); - } - } - - @Override - public long readSize(Bytes bytes) { - return size; - } - - @NotNull - @Override - public E read(@NotNull Bytes bytes, long size) { - return read(bytes, size, null); - } - - @NotNull - @Override - public E read(@NotNull Bytes bytes, long size, E toReuse) { - try { - if (toReuse == null) - toReuse = getInstance(); - setBytesAndOffset(toReuse, bytes); - bytes.skip(size); - return toReuse; - } catch (Exception ex) { - throw new IllegalStateException(ex); - } - } - - public static void setBytesAndOffset(Byteable e, Bytes bytes) { - // use the unshifting underlying Bytes (the position never changes) - // if you use a Bytes where the position changes, you risk concurrency issues. - if (bytes instanceof MultiStoreBytes) { - MultiStoreBytes msb = (MultiStoreBytes) bytes; - e.bytes(msb.underlyingBytes(), msb.underlyingOffset() + msb.position()); - } else { - e.bytes(bytes, bytes.position()); - } - } - - @SuppressWarnings("unchecked") - @NotNull - E getInstance() throws Exception { - return (E) NativeBytes.UNSAFE.allocateInstance(tClass); - } - - @Override - public boolean startsWith(Object interop, Bytes bytes, E e) { - return startsWith(bytes, e); - } - - @Override - public boolean equivalent( - Object interop, E e, - MetaBytesInterop otherMetaInterop, I2 otherInterop, E other) { - return equivalent(e, other); - } - - @Override - public long hash(Object interop, LongHashFunction hashFunction, E e) { - return hash(hashFunction, e); - } - - @Override - public long size(Object writer, E e) { - return size(e); - } - - @Override - public void write(Object writer, Bytes bytes, E e) { - write(bytes, e); - } - - private static class Default extends ByteableMarshaller { - private static final long serialVersionUID = 0L; - - Default(@NotNull Class tClass) { - super(tClass); - initSize(); - } - } - - private static class WithCustomFactory extends ByteableMarshaller { - private static final long serialVersionUID = 0L; - - @NotNull - private final ObjectFactory factory; - - WithCustomFactory(@NotNull Class tClass, - @NotNull ObjectFactory factory) { - super(tClass); - this.factory = factory; - initSize(); - } - - @NotNull - @Override - E getInstance() throws Exception { - return factory.create(); - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesBytesInterop.java deleted file mode 100644 index 2faac133e..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesBytesInterop.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -public enum BytesBytesInterop implements BytesInterop { - INSTANCE; - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull Bytes e) { - return bytes.compare(bytes.position(), e, e.position(), e.remaining()); - } - - @Override - public boolean equivalent(@NotNull Bytes a, @NotNull Bytes b) { - if (a.remaining() != b.remaining()) - return false; - return a.compare(a.position(), b, b.position(), b.remaining()); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull Bytes e) { - return hashFunction.hashBytes(e); - } - - @Override - public long size(@NotNull Bytes e) { - return e.remaining(); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull Bytes e) { - bytes.write(e, e.position(), e.remaining()); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesReaders.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesReaders.java deleted file mode 100644 index b6f66e714..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/BytesReaders.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshaller; -import org.jetbrains.annotations.NotNull; - -/** - * Utility methods returning {@link BytesReader} implementations. - */ -public final class BytesReaders { - - /** - * Returns a {@link BytesReader} wrapping the given {@link BytesMarshaller}. One of the - * bridge methods between general serialization API from {@link net.openhft.lang} and - * reader - writer - interop API, specific for ChronicleHashes, - * from {@link net.openhft.chronicle.hash.serialization} package. - * - * @param marshaller the actual reading implementation - * @param type of the objects marshalled - * @return a {@code BytesReader} wrapping the given {@code BytesMarshaller} - */ - public static BytesReader fromBytesMarshaller(BytesMarshaller marshaller) { - return new SimpleBytesReader(marshaller); - } - - /** - * Returns {@code BytesMarshaller} {@code m}, if the given reader is the result of {@link - * #fromBytesMarshaller(BytesMarshaller) fromBytesMarshaller(m)} call, {@code null} otherwise. - * - * @param reader reader to extract {@code BytesMarshaller} from - * @param type of the objects marshalled - * @return {@code BytesMarshaller} from which the specified reader was created, or {@code null} - */ - public static BytesMarshaller getBytesMarshaller(BytesReader reader) { - return reader instanceof SimpleBytesReader ? ((SimpleBytesReader) reader).marshaller : null; - } - - private static class SimpleBytesReader implements BytesReader { - private static final long serialVersionUID = 0L; - - private final BytesMarshaller marshaller; - - public SimpleBytesReader(BytesMarshaller marshaller) { - this.marshaller = marshaller; - } - - @NotNull - @Override - public E read(@NotNull Bytes bytes, long size) { - return (E) marshaller.read(bytes); - } - - @NotNull - @Override - public E read(@NotNull Bytes bytes, long size, E toReuse) { - return (E) marshaller.read(bytes, toReuse); - } - } - - private BytesReaders() { - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharArrayMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharArrayMarshaller.java deleted file mode 100644 index 781c943b2..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharArrayMarshaller.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; - -public enum CharArrayMarshaller implements BytesInterop, BytesReader { - INSTANCE; - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull char[] chars) { - if (bytes.capacity() - bytes.position() < chars.length * 2L) - return false; - long pos = bytes.position(); - for (int i = 0; i < chars.length; i++) { - if (bytes.readChar(pos + (i * 2L)) != chars[i]) - return false; - } - return true; - } - - @Override - public boolean equivalent(@NotNull char[] a, @NotNull char[] b) { - return Arrays.equals(a, b); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull char[] chars) { - return hashFunction.hashChars(chars); - } - - @NotNull - @Override - public char[] read(@NotNull Bytes bytes, long size) { - char[] chars = new char[resLen(size)]; - bytes.readFully(chars); - return chars; - } - - @NotNull - @Override - public char[] read(@NotNull Bytes bytes, long size, char[] toReuse) { - int resLen = resLen(size); - if (toReuse == null || toReuse.length != resLen) - toReuse = new char[resLen]; - bytes.readFully(toReuse); - return toReuse; - } - - private int resLen(long size) { - long resLen = size / 2L; - if (resLen < 0 || resLen > Integer.MAX_VALUE) - throw new IllegalArgumentException("char[] size should be non-negative int, " + - resLen + " given. Memory corruption?"); - return (int) resLen; - } - - @Override - public long size(@NotNull char[] chars) { - return chars.length * 2L; - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull char[] chars) { - bytes.write(chars); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceReader.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceReader.java deleted file mode 100644 index 39dc91f28..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceReader.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.AbstractBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.pool.CharSequenceInterner; -import net.openhft.lang.threadlocal.StatefulCopyable; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.io.UTFDataFormatException; - -public final class CharSequenceReader - implements BytesReader, StatefulCopyable> { - private static final long serialVersionUID = 0L; - - private enum NoInterningIdentity implements CharSequenceInterner { - INSTANCE; - - @Override - public CharSequence intern(CharSequence cs) { - return cs; - } - } - - private enum NoInterningToString implements CharSequenceInterner { - INSTANCE; - @Override - public String intern(CharSequence cs) { - return cs.toString(); - } - } - - private static final CharSequenceReader STRING_READER = - new CharSequenceReader(NoInterningToString.INSTANCE, NoInterningToString.INSTANCE); - - private static final CharSequenceReader DEFAULT_READER = - new CharSequenceReader(NoInterningIdentity.INSTANCE, NoInterningIdentity.INSTANCE); - - public static CharSequenceReader of() { - return STRING_READER; - } - - public static CharSequenceReader ofStringBuilder() { - return DEFAULT_READER; - } - - public static & Serializable> - CharSequenceReader of(@NotNull I interner, @NotNull Serializable stateIdentity) { - return new CharSequenceReader(interner, stateIdentity); - } - - private final StringBuilder sb = new StringBuilder(128); - @NotNull - private final CharSequenceInterner interner; - @NotNull - private final Serializable identity; - - private CharSequenceReader(@NotNull CharSequenceInterner interner, - @NotNull Serializable identity) { - this.interner = interner; - this.identity = identity; - } - - /** - * Method copied here because corresponding method in AbstractBytes was turned - * to instance method, but we need to call on Bytes, not AbstractBytes - */ - private static void readUTF0(Bytes b, @NotNull Appendable appendable, int utflen) - throws IOException { - int count = 0; - - while (count < utflen) { - int c = b.readUnsignedByteOrThrow(); - if (c >= 128) { - b.position(b.position() - 1); - AbstractBytes.readUTF2(b, appendable, utflen, count); - break; - } - count++; - appendable.append((char) c); - } - } - - @NotNull - @Override - public S read(@NotNull Bytes bytes, long size) { - sb.setLength(0); - try { - readUTF0(bytes, sb, (int) size); - } catch (IOException e) { - throw new IllegalStateException(e); - } - return interner.intern(sb); - } - - @NotNull - @Override - public S read(@NotNull Bytes bytes, long size, S toReuse) { - Appendable appendable; - if (toReuse instanceof Appendable) { - appendable = (Appendable) toReuse; - if (toReuse instanceof StringBuilder) { - ((StringBuilder) toReuse).setLength(0); - } else if (toReuse instanceof StringBuffer) { - ((StringBuffer) toReuse).setLength(0); - } - } else { - sb.setLength(0); - appendable = sb; - } - try { - readUTF0(bytes, appendable, (int) size); - } catch (IOException e) { - throw new IllegalStateException(e); - } - if (appendable == toReuse) - return toReuse; - return interner.intern(sb); - } - - @Override - public Object stateIdentity() { - return identity; - } - - @Override - public CharSequenceReader copy() { - return new CharSequenceReader(interner, identity); - } - - private Object readResolve() throws ObjectStreamException { - if (interner == NoInterningToString.INSTANCE) - return STRING_READER; - if (interner == NoInterningIdentity.INSTANCE) - return DEFAULT_READER; - return this; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceWriter.java deleted file mode 100644 index a6cd6d220..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CharSequenceWriter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.lang.io.AbstractBytes; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import java.io.ObjectStreamException; - -public final class CharSequenceWriter implements BytesWriter { - private static final long serialVersionUID = 0L; - private static final CharSequenceWriter INSTANCE = new CharSequenceWriter(); - - public static CharSequenceWriter instance() { - return INSTANCE; - } - - private CharSequenceWriter() {} - - @Override - public long size(@NotNull CS s) { - return AbstractBytes.findUTFLength(s); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull CS s) { - AbstractBytes.writeUTF0(bytes, s, s.length()); - } - - private Object readResolve() throws ObjectStreamException { - return INSTANCE; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CopyingMetaBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/CopyingMetaBytesInterop.java deleted file mode 100644 index 94a2b8004..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/CopyingMetaBytesInterop.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.lang.MemoryUnit; -import net.openhft.lang.io.serialization.BytesMarshaller; -import net.openhft.lang.threadlocal.ThreadLocalCopies; - -import java.io.Serializable; - -public abstract class CopyingMetaBytesInterop extends BasicCopyingMetaBytesInterop { - private static final long serialVersionUID = 1L; - - private static final long MAX_REASONABLE_SERIALIZED_SIZE = MemoryUnit.MEGABYTES.toBytes(16L); - - public static void checkMaxSizeStillReasonable(long maxSize, Exception ex) { - if (maxSize > MAX_REASONABLE_SERIALIZED_SIZE) { - throw new IllegalStateException("We try to figure out size of objects " + - "in serialized form, but it exceeds " + - MAX_REASONABLE_SERIALIZED_SIZE + " bytes. We assume this is " + - "a error and throw exception at this point. There could be two reasons:\n" + - "1) The given object is not Serializable. Configure ChronicleMapBuilder" + - ".keyMarshallers/valueMarshallers to handle the given objects.\n" + - "2) Your object are very large in serialized form (larger than " + - MAX_REASONABLE_SERIALIZED_SIZE + " bytes). If you really " + - "want larger keys/values, use ChronicleMapBuilder." + - "keySize(int)/valueSize(int)/entrySize(int) configurations", ex); - } - } - - transient W writer; - transient E cur; - - protected CopyingMetaBytesInterop(DirectBytesBuffer buffer) { - super(buffer); - } - - @Override - public boolean equivalent( - W interop, E e, MetaBytesInterop otherMetaInterop, I2 otherInterop, E other) { - return otherMetaInterop.size(otherInterop, other) == size(interop, e) && - otherMetaInterop.startsWith(otherInterop, buffer.buffer, other); - } - - DirectBytesBuffer buffer() { - return buffer; - } - - public static > - MetaBytesInterop forBytesMarshaller(Serializable bufferIdentity) { - return new DirectBytesBuffer(bufferIdentity).forBytesMarshaller; - } - - public static > - MetaBytesInterop forBytesWriter(Serializable bufferIdentity) { - return new DirectBytesBuffer(bufferIdentity).forBytesWriter; - } - - public static > - MetaProvider> providerForBytesMarshaller(boolean mutable, - long maxSize) { - return new BytesMarshallerCopyingMetaBytesInteropProvider<>(mutable, maxSize); - } - - private static class BytesMarshallerCopyingMetaBytesInteropProvider> - extends BasicCopyingMetaBytesInteropProvider> { - private static final long serialVersionUID = 0L; - private final boolean mutable; - private final long maxSize; - - public BytesMarshallerCopyingMetaBytesInteropProvider(boolean mutable, long maxSize) { - this.mutable = mutable; - this.maxSize = maxSize; - } - - @Override - public CopyingMetaBytesInterop get( - ThreadLocalCopies copies, - CopyingMetaBytesInterop originalMetaWriter, M writer, E e, boolean checked) { - DirectBytesBuffer.ForBytesMarshaller forBytesMarshaller = - provider.get(copies, originalMetaWriter.buffer()).forBytesMarshaller; - forBytesMarshaller.init(writer, e, mutable, maxSize, checked); - return forBytesMarshaller; - } - } - - public static > - MetaProvider> providerForBytesWriter(boolean mutable) { - return new BytesWriterCopyingMetaBytesInteropProvider<>(mutable); - } - - private static class BytesWriterCopyingMetaBytesInteropProvider> - extends BasicCopyingMetaBytesInteropProvider> { - private static final long serialVersionUID = 0L; - private final boolean mutable; - - public BytesWriterCopyingMetaBytesInteropProvider(boolean mutable) { - this.mutable = mutable; - } - - @Override - public CopyingMetaBytesInterop get( - ThreadLocalCopies copies, CopyingMetaBytesInterop originalMetaWriter, - W writer, E e, boolean checked) { - DirectBytesBuffer.ForBytesWriter forBytesWriter = - provider.get(copies, originalMetaWriter.buffer()).forBytesWriter; - forBytesWriter.init(writer, e, mutable, checked); - return forBytesWriter; - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java deleted file mode 100644 index 09aeffeb3..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java +++ /dev/null @@ -1,542 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.chronicle.hash.serialization.DeserializationFactoryConfigurableBytesReader; -import net.openhft.compiler.CompilerUtils; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.ObjectFactory; -import net.openhft.lang.model.*; -import org.jetbrains.annotations.NotNull; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.SortedSet; -import java.util.concurrent.ConcurrentHashMap; - -import static net.openhft.lang.model.DataValueGenerator.*; - -public final class DataValueBytesMarshallers { - - private static final boolean dumpCode = Boolean.getBoolean("dvg.dumpCode"); - private static final Map readersClassMap = - new ConcurrentHashMap<>(); - private static final Map readersWithCustomFactoriesClassMap = - new ConcurrentHashMap<>(); - private static final Map writerClassMap = - new ConcurrentHashMap<>(); - - public static BytesReader acquireBytesReader(Class tClass) { - Class readerClass = acquireReaderClass(tClass); - try { - Field instanceField = readerClass.getDeclaredField("INSTANCE"); - Object reader = instanceField.get(null); - return (BytesReader) reader; - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new AssertionError(e); - } - } - - public static BytesWriter acquireBytesWriter(Class tClass) { - Class readerClass = acquireWriterClass(tClass); - try { - Field instanceField = readerClass.getDeclaredField("INSTANCE"); - Object reader = instanceField.get(null); - return (BytesWriter) reader; - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new AssertionError(e); - } - } - - - public static Class acquireReaderClass(Class tClass) { - return readersClassMap.computeIfAbsent(tClass, - DataValueBytesMarshallers::compileReaderClass); - } - - private static Class compileReaderClass(Class tClass) { - DataValueClasses.directClassFor(tClass); - Class readerClass; - DataValueModel dvmodel = DataValueModels.acquireModel(tClass); - for (Class clazz : dvmodel.nestedModels()) { - // touch them to make sure they are loaded. - Class clazz2 = acquireReaderClass(clazz); - } - String actual = generateBytesReader(tClass); - if (dumpCode) - LoggerFactory.getLogger(DataValueGenerator.class).info(actual); - ClassLoader classLoader = tClass.getClassLoader(); - String className = bytesReaderName(tClass, false); - try { - readerClass = classLoader.loadClass(className); - } catch (ClassNotFoundException ignored) { - try { - readerClass = CompilerUtils.CACHED_COMPILER - .loadFromJava(classLoader, className, actual); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); - } - } - acquireReaderWithCustomFactory(tClass); - return readerClass; - } - - public static Class acquireWriterClass(Class tClass) { - return writerClassMap.computeIfAbsent(tClass, - DataValueBytesMarshallers::compileWriterClass); - } - - private static Class compileWriterClass(Class tClass) { - Class writerClass; - DataValueModel dvmodel = DataValueModels.acquireModel(tClass); - for (Class clazz : dvmodel.nestedModels()) { - // touch them to make sure they are loaded. - Class clazz2 = acquireWriterClass(clazz); - } - String actual = generateBytesWriter(tClass); - if (dumpCode) - LoggerFactory.getLogger(DataValueGenerator.class).info(actual); - ClassLoader classLoader = tClass.getClassLoader(); - String className = bytesWriterName(tClass, false); - try { - writerClass = classLoader.loadClass(className); - } catch (ClassNotFoundException ignored) { - try { - writerClass = CompilerUtils.CACHED_COMPILER - .loadFromJava(classLoader, className, actual); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); - } - } - return writerClass; - } - - private static Class acquireReaderWithCustomFactory(Class tClass) { - return readersWithCustomFactoriesClassMap.computeIfAbsent(tClass, - DataValueBytesMarshallers::compileReaderWithCustomFactory); - } - - private static Class compileReaderWithCustomFactory(Class tClass) { - Class c; - String actual = generateWithCustomFactoryClass(tClass); - if (dumpCode) - LoggerFactory.getLogger(DataValueGenerator.class).info(actual); - ClassLoader classLoader = tClass.getClassLoader(); - String className = withCustomFactoryName(tClass); - try { - c = classLoader.loadClass(className); - } catch (ClassNotFoundException ignored) { - try { - c = CompilerUtils.CACHED_COMPILER - .loadFromJava(classLoader, className, actual); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); - } - } - return c; - } - - private static String withCustomFactoryName(Class tClass) { - return bytesReaderName(tClass, false) + "$WithCustomFactory"; - } - - private static String generateWithCustomFactoryClass(Class tClass) { - DataValueModel dvModel = DataValueModels.acquireModel(tClass); - - SortedSet imported = newImported(); - imported.add(ObjectFactory.class); - imported.add(NotNull.class); - imported.add(dvModel.type()); - - String simpleName = tClass.getSimpleName(); - - String bytesReaderName = bytesReaderName(simpleName(tClass)); - String name = bytesReaderName + "$WithCustomFactory"; - String withCustomFactoryClass = - "public final class " + name + " extends " + bytesReaderName + " {\n" + - " private static final long serialVersionUID = 0L;\n" + - "\n" + - " @NotNull\n" + - " private final ObjectFactory<" + simpleName + "> factory;\n" + - "\n" + - " " + name + "(@NotNull ObjectFactory<" + - simpleName + "> factory) {\n" + - " this.factory = factory;\n" + - " }\n" + - "\n" + - " @Override\n" + - " " + simpleName + " getInstance() throws Exception {\n" + - " return factory.create();\n" + - " }\n" + - "}\n"; - - StringBuilder sb = new StringBuilder(); - appendPackage(dvModel, sb); - appendImported(imported, sb); - sb.append(withCustomFactoryClass); - return sb.toString(); - } - - private static String bytesReaderName(Class type, boolean simple) { - return (simple ? type.getSimpleName() : type.getName()) + "$$BytesReader"; - } - - private static String bytesReaderName(String className) { - return className + "$$BytesReader"; - } - - public static String bytesWriterName(Class type, boolean simple) { - return (simple ? simpleName(type) : type.getName()) + "$$BytesWriter"; - } - - private static String generateBytesReader(Class tClass) { - DataValueModel dvModel = DataValueModels.acquireModel(tClass); - - SortedSet imported = newImported(); - imported.add(BytesReader.class); - imported.add(DeserializationFactoryConfigurableBytesReader.class); - imported.add(ObjectFactory.class); - imported.add(Bytes.class); - imported.add(ByteableMarshaller.class); - imported.add(Byteable.class); - imported.add(dvModel.type()); - imported.add(InvocationTargetException.class); - imported.add(Constructor.class); - - StringBuilder read = generateReadBody(dvModel, imported); - - StringBuilder sb = new StringBuilder(); - appendPackage(dvModel, sb); - appendImported(imported, sb); - String simpleName = tClass.getSimpleName(); - String bytesReaderName = bytesReaderName(tClass, false); - String simpleReaderName = bytesReaderName(simpleName(tClass)); - sb.append("\n@SuppressWarnings(\"unchecked\") public class ").append(simpleReaderName) - .append(" implements DeserializationFactoryConfigurableBytesReader<") - .append(simpleName).append(", ").append(simpleReaderName).append("> {\n"); - declareSerialVersionUID(sb); - declareStaticInstance(sb, tClass); - generatePrivateConstructor(sb, simpleReaderName); - generateWithDeserializationFactory(tClass, dvModel, sb, simpleName, simpleReaderName); - generateGetInstance(sb, tClass); - generateDelegatingRead(sb, simpleName); - generateRead(read, sb, simpleName, tClass); - sb.append("}\n"); - return sb.toString(); - } - - private static void generateWithDeserializationFactory(Class tClass, - DataValueModel dvModel, - StringBuilder sb, String simpleName, - String simpleReaderName) { - appendOverride(sb); - sb.append(" public ").append(simpleReaderName) - .append(" withDeserializationFactory(ObjectFactory<").append(simpleName) - .append("> factory) {\n"); - sb.append(" try {\n"); - sb.append(" ") - .append("Class cfc = Class.forName(\"") - .append(getPackage(dvModel)) - .append(".").append(withCustomFactoryName(tClass)).append("\");\n"); - sb.append( - " Constructor constructor = cfc.getConstructor(ObjectFactory.class);\n" + - " Object reader = constructor.newInstance(factory);\n" + - " return (" + simpleReaderName + ") reader;\n" + - " } catch (ClassNotFoundException | IllegalAccessException | " + - "NoSuchMethodException | InstantiationException |\n" + - " InvocationTargetException e) {\n" + - " throw new AssertionError(e);\n" + - " }\n"); - sb.append(" }\n\n"); - } - - private static StringBuilder generateReadBody(DataValueModel dvModel, - SortedSet imported) { - StringBuilder read = new StringBuilder(); - - Map.Entry[] entries = - heapSizeOrderedFieldsGrouped(dvModel); - for (Map.Entry entry : entries) { - String name = entry.getKey(); - FieldModel model = entry.getValue(); - Class type = model.type(); - if (shouldImport(type)) - imported.add(type); - - Method setter = getSetter(model); - Method getter = getGetter(model); - - Method orderedSetter = getOrderedSetter(model); - Method volatileGetter = getVolatileGetter(model); - - Method defaultSetter = setter != null ? setter : orderedSetter; - Method defaultGetter = getter != null ? getter : volatileGetter; - if (!dvModel.isScalar(type)) { - if (model.isArray()) { - read.append(" for (int i = 0; i < ") - .append(model.indexSize().value()).append("; i++) {\n"); - read.append(" toReuse.") - .append(defaultSetter.getName()).append("(i, ") - .append(bytesReaderName(type, false)) - .append(".INSTANCE").append(".read(bytes, ") - .append(computeNonScalarOffset(dvModel, type)).append(", ") - .append("toReuse.").append(defaultGetter.getName()).append("(i)));\n"); - read.append(" }\n"); - } else { - read.append(" toReuse.") - .append(defaultSetter.getName()).append("(") - .append(bytesReaderName(type, false)) - .append(".INSTANCE").append(".read(bytes, ") - .append(computeNonScalarOffset(dvModel, type)).append(", ") - .append("toReuse.").append(defaultGetter.getName()).append("()));\n"); - } - } else { - if (model.isArray()) { - read.append(" for (int i = 0; i < ") - .append(model.indexSize().value()).append("; i++) {\n"); - saveCharSequencePosition(read, type); - read.append(" toReuse.").append(defaultSetter.getName()) - .append("(i, bytes.read").append(bytesType(type)).append("());\n"); - updateCharSequencePosition(read, model, type); - read.append(" }\n"); - } else { - read.append(" {\n"); - saveCharSequencePosition(read, type); - read.append(" toReuse.").append(defaultSetter.getName()) - .append("(bytes.read").append(bytesType(type)).append("());\n"); - updateCharSequencePosition(read, model, type); - read.append(" }\n"); - } - } - } - return read; - } - - private static void updateCharSequencePosition(StringBuilder read, FieldModel model, - Class type) { - if (CharSequence.class.isAssignableFrom(type)) - read.append(" bytes.position(pos + ") - .append(fieldSize(model)).append(");\n"); - } - - private static String generateBytesWriter(Class tClass) { - DataValueModel dvModel = DataValueModels.acquireModel(tClass); - - SortedSet imported = newImported(); - imported.add(BytesWriter.class); - imported.add(Bytes.class); - imported.add(Byteable.class); - imported.add(dvModel.type()); - - String write = generateWriteBody(dvModel, imported); - - StringBuilder sb = new StringBuilder(); - appendPackage(dvModel, sb); - appendImported(imported, sb); - sb.append("public enum ").append(bytesWriterName(tClass, true)) - .append(" implements BytesWriter<").append(tClass.getSimpleName()).append("> {\n"); - sb.append(" INSTANCE;\n\n"); - generateSize(tClass, dvModel, sb); - generateWrite(tClass, dvModel, write, sb); - generateShouldNotBeNull(tClass, sb); - sb.append("}\n"); - return sb.toString(); - } - - private static void generateShouldNotBeNull(Class tClass, StringBuilder sb) { - sb.append(" private static void shouldNotBeNull() {\n"); - sb.append(" throw new NullPointerException(\"Sub-members of " + - tClass.getSimpleName() + " shouldn't be null for this writer. You should specify" + - " custom writer (e. g. using keyMarshallers()/valueMarshallers() methods of" + - "ChronicleMapBuilder, if you want to support null fields/array elements.\");\n"); - sb.append(" }\n"); - } - - private static void generateWrite(Class tClass, DataValueModel dvModel, String write, - StringBuilder sb) { - appendOverride(sb); - sb.append(" public void write(Bytes bytes, ") - .append(tClass.getSimpleName()).append(" e) {\n"); - int size = computeNonScalarOffset(dvModel, tClass); - if (size > 16) { - sb.append(" if (e instanceof Byteable) {\n"); - sb.append( - " Bytes eBytes = ((Byteable) e).bytes();\n" + - " if (eBytes != null) {\n" + - " bytes.write(eBytes, ((Byteable) e).offset(), " + - size + ");\n" + - " } else {\n" + - " throw new NullPointerException(" + - "\"You are trying to write a byteable object of \" +\n" + - " e.getClass() + \", \" +\n" + - " \"which bytes are not assigned. I. e. most likely " + - "the object is uninitialized.\");\n" + - " }\n"); - sb.append(" return;\n"); - sb.append(" }\n"); - } - sb.append(write); - sb.append(" }\n\n"); - } - - private static void generateSize(Class tClass, DataValueModel dvModel, StringBuilder sb) { - appendOverride(sb); - sb.append(" public long size(").append(tClass.getSimpleName()).append(" e) {\n"); - sb.append(" return ").append(computeNonScalarOffset(dvModel, tClass)).append(";\n"); - sb.append(" }\n\n"); - } - - private static String generateWriteBody(DataValueModel dvModel, SortedSet imported) { - StringBuilder write = new StringBuilder(); - - Map.Entry[] entries = - heapSizeOrderedFieldsGrouped(dvModel); - for (Map.Entry entry : entries) { - String name = entry.getKey(); - FieldModel model = entry.getValue(); - Class type = model.type(); - if (shouldImport(type)) - imported.add(type); - - Method setter = getSetter(model); - Method getter = getGetter(model); - - Method orderedSetter = getOrderedSetter(model); - Method volatileGetter = getVolatileGetter(model); - - Method defaultSetter = setter != null ? setter : orderedSetter; - Method defaultGetter = getter != null ? getter : volatileGetter; - if (!dvModel.isScalar(type)) { - if (model.isArray()) { - write.append(" for (int i = 0; i < ") - .append(model.indexSize().value()).append("; i++) {\n"); - write.append(" ") - .append(normalize(type)).append(" $ = e.") - .append(defaultGetter.getName()).append("(i);\n"); - write.append(" ") - .append("if ($ == null) shouldNotBeNull();\n"); - write.append(" ") - .append(bytesWriterName(type, false)) - .append(".INSTANCE").append(".write(bytes, $);\n"); - write.append(" }\n"); - } else { - write.append(" {") - .append(normalize(type)).append(" $ = e.") - .append(defaultGetter.getName()).append("();\n"); - write.append(" ") - .append("if ($ == null) shouldNotBeNull();\n"); - write.append(" ") - .append(bytesWriterName(type, false)) - .append(".INSTANCE").append(".write(bytes, $);}\n"); - } - } else { - if (model.isArray()) { - write.append(" for (int i = 0; i < ") - .append(model.indexSize().value()).append("; i++) {\n"); - saveCharSequencePosition(write, type); - write.append(" bytes.write").append(bytesType(type)) - .append("(e.").append(defaultGetter.getName()).append("(i));\n"); - zeroOutRemainingCharSequenceBytesAndUpdatePosition(write, model, type); - write.append(" }\n"); - } else { - write.append(" {\n"); - saveCharSequencePosition(write, type); - write.append(" bytes.write").append(bytesType(type)) - .append("(e.").append(defaultGetter.getName()).append("());\n"); - zeroOutRemainingCharSequenceBytesAndUpdatePosition(write, model, type); - write.append(" }\n"); - } - } - } - return write.toString(); - } - - private static void saveCharSequencePosition(StringBuilder write, Class type) { - if (CharSequence.class.isAssignableFrom(type)) - write.append(" long pos = bytes.position();\n"); - } - - private static void zeroOutRemainingCharSequenceBytesAndUpdatePosition( - StringBuilder write, FieldModel model, Class type) { - if (CharSequence.class.isAssignableFrom(type)) { - write.append(" long newPos = pos + ").append(fieldSize(model)) - .append(";\n"); - write.append(" bytes.zeroOut(bytes.position(), newPos);\n"); - write.append(" bytes.position(newPos);\n"); - } - } - - private static void generateRead(StringBuilder read, StringBuilder sb, String simpleName, - Class cl) { - appendOverride(sb); - sb.append(" public ").append(simpleName).append(" read(Bytes bytes, long size, ") - .append(simpleName).append(" toReuse) {\n"); - sb.append(" try {\n"); - sb.append(" if (toReuse == null)\n"); - sb.append(" toReuse = getInstance();\n"); - sb.append(" if (toReuse instanceof Byteable) {\n"); - sb.append(" " + - "ByteableMarshaller.setBytesAndOffset(((Byteable) toReuse), bytes);\n"); - sb.append(" bytes.skip(size);\n"); - sb.append(" return toReuse;\n"); - sb.append(" }\n"); - sb.append(read); - sb.append(" return toReuse;\n"); - sb.append(" } catch (Exception e) {\n"); - sb.append(" throw new IllegalStateException(e);\n"); - sb.append(" }\n"); - sb.append("}\n\n"); - } - - private static void generateDelegatingRead(StringBuilder sb, String simpleName) { - appendOverride(sb); - sb.append(" public ").append(simpleName).append(" read(Bytes bytes, long size) {\n"); - sb.append(" return read(bytes, size, null);\n"); - sb.append(" }\n\n"); - } - - private static void appendOverride(StringBuilder sb) { - sb.append(" @Override\n"); - } - - private static void generatePrivateConstructor(StringBuilder sb, String bytesReaderName) { - sb.append(" ").append(bytesReaderName).append("() {}\n\n"); - } - - private static void declareStaticInstance(StringBuilder sb, Class cl) { - String bytesReaderName = bytesReaderName(simpleName(cl)); - sb.append(" public static final ").append(bytesReaderName).append(" INSTANCE = new ") - .append(bytesReaderName).append("();\n\n"); - } - - private static StringBuilder declareSerialVersionUID(StringBuilder sb) { - return sb.append(" private static final long serialVersionUID = 0L;\n\n"); - } - - private static void generateGetInstance(StringBuilder sb, Class cl) { - sb.append(" ").append(cl.getCanonicalName()) - .append(" getInstance() throws Exception {\n"); - sb.append(" ").append("return new ").append(cl.getName()).append("$$Native();\n"); - sb.append(" ").append("}\n\n"); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueMetaBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueMetaBytesInterop.java deleted file mode 100644 index eaa235fa0..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueMetaBytesInterop.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.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; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; - -public abstract class DataValueMetaBytesInterop - extends BasicCopyingMetaBytesInterop> { - private static final long serialVersionUID = 0L; - - protected DataValueMetaBytesInterop(DirectBytesBuffer buffer) { - super(buffer); - } - - @Override - public boolean equivalent( - BytesWriter interop, E e, MetaBytesInterop otherMetaInterop, I2 otherInterop, - E other) { - return e.equals(other); - } - - void init(BytesWriter 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; - this.size = size; - hash = 0L; - } - - public static MetaBytesInterop> forIdentity(Serializable bufferIdentity) { - return new DirectBytesBuffer(bufferIdentity).forDataValueWriter; - } - - public static MetaProvider, MetaBytesInterop>> - interopProvider(Class eClass) { - return new InteropProvider<>(eClass); - } - - private static class InteropProvider extends BasicCopyingMetaBytesInteropProvider< - E, BytesWriter, MetaBytesInterop>> { - private static final long serialVersionUID = 0L; - - private final Class eClass; - transient long size; - transient MetaBytesInterop metaByteableInterop; - - private InteropProvider(Class eClass) { - this.eClass = eClass; - initTransients(); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - initTransients(); - } - - private void initTransients() { - DataValueModel model = DataValueModels.acquireModel(eClass); - size = DataValueGenerator.computeNonScalarOffset(model, eClass); - // TODO make this pick up configured deserializationFactory somehow - metaByteableInterop = ByteableMarshaller.of( - (Class) DataValueClasses.directClassFor(eClass)); - } - - @Override - public MetaBytesInterop> get( - ThreadLocalCopies copies, MetaBytesInterop> originalMetaWriter, - BytesWriter 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, checked); - return forDataValueWriter; - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInterop.java deleted file mode 100644 index 353cd26b9..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInterop.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.lang.io.Bytes; - -import java.io.ObjectStreamException; - -public final class DelegatingMetaBytesInterop> - implements MetaBytesInterop { - private static final long serialVersionUID = 0L; - private static final DelegatingMetaBytesInterop INSTANCE = new DelegatingMetaBytesInterop(); - - public static > - DelegatingMetaBytesInterop instance() { - return INSTANCE; - } - - private DelegatingMetaBytesInterop() {} - - @Override - public long size(I interop, E e) { - return interop.size(e); - } - - @Override - public boolean startsWith(I interop, Bytes bytes, E e) { - return interop.startsWith(bytes, e); - } - - @Override - public boolean equivalent( - I interop, E e, MetaBytesInterop otherMetaInterop, I2 otherInterop, E other) { - return interop.equivalent(e, other); - } - - @Override - public long hash(I interop, LongHashFunction hashFunction, E e) { - return interop.hash(hashFunction, e); - } - - @Override - public void write(I interop, Bytes bytes, E e) { - interop.write(bytes, e); - } - - private Object readResolve() throws ObjectStreamException { - return INSTANCE; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInteropProvider.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInteropProvider.java deleted file mode 100644 index 3374a0526..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DelegatingMetaBytesInteropProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.lang.threadlocal.ThreadLocalCopies; - -import java.io.ObjectStreamException; - -public final class DelegatingMetaBytesInteropProvider> - implements MetaProvider> { - private static final long serialVersionUID = 0L; - private static final DelegatingMetaBytesInteropProvider INSTANCE = - new DelegatingMetaBytesInteropProvider(); - - public static > - MetaProvider> instance() { - return INSTANCE; - } - - private DelegatingMetaBytesInteropProvider() {} - - @Override - public MetaBytesInterop get( - ThreadLocalCopies copies, MetaBytesInterop originalMetaWriter, I writer, E e, - boolean checked) { - return originalMetaWriter; - } - - @Override - public ThreadLocalCopies getCopies(ThreadLocalCopies copies) { - return copies; - } - - private Object readResolve() throws ObjectStreamException { - return INSTANCE; - } -} 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 deleted file mode 100644 index cb5aa4f73..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DirectBytesBuffer.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.BytesWriter; -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; -import net.openhft.lang.threadlocal.StatefulCopyable; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; - -class DirectBytesBuffer - implements StatefulCopyable, Serializable { - private static final long serialVersionUID = 0L; - private final Serializable identity; - transient DirectBytes buffer; - - transient ForBytesMarshaller forBytesMarshaller; - transient ForBytesWriter forBytesWriter; - transient ForDataValueWriter forDataValueWriter; - private final ObjectSerializer objectSerializer = BytesMarshallableSerializer.create(); - - DirectBytesBuffer(Serializable identity) { - this.identity = identity; - initTransients(); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - initTransients(); - } - - private void initTransients() { - forBytesMarshaller = new ForBytesMarshaller(); - forBytesWriter = new ForBytesWriter(); - forDataValueWriter = new ForDataValueWriter(); - } - - Bytes obtain(long maxSize, boolean boundsChecking) { - DirectBytes buf; - if ((buf = buffer) != null) { - if (maxSize <= buf.capacity()) { - return buf.clear(); - } else { - DirectStore store = (DirectStore) buf.store(); - store.resize(maxSize, false); - return buffer = store.bytes(); - } - } else { - buffer = new DirectStore(objectSerializer, Math.max(1, maxSize), true) - .bytes(); - return buffer; - } - } - - @Override - public Object stateIdentity() { - return identity; - } - - @Override - public DirectBytesBuffer copy() { - return new DirectBytesBuffer(identity); - } - - class ForBytesMarshaller> - extends CopyingMetaBytesInterop { - private static final long serialVersionUID = 0L; - - private ForBytesMarshaller() { - super(DirectBytesBuffer.this); - } - - void init(M writer, E e, boolean mutable, long maxSize, boolean checked) { - 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; - } - } - } - } - - class ForBytesWriter> - extends CopyingMetaBytesInterop { - private static final long serialVersionUID = 0L; - - private ForBytesWriter() { - super(DirectBytesBuffer.this); - } - - void init(W writer, E e, boolean mutable, boolean checked) { - 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; - } - } - - class ForDataValueWriter extends DataValueMetaBytesInterop { - - private ForDataValueWriter() { - super(DirectBytesBuffer.this); - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DoubleMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DoubleMarshaller.java deleted file mode 100644 index a5135ae3d..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DoubleMarshaller.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import static java.lang.Double.doubleToLongBits; - -public enum DoubleMarshaller implements BytesInterop, BytesReader, SizeMarshaller { - INSTANCE; - - @Override - public long size(@NotNull Double e) { - return 8L; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return 8L; - } - - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == 8L; - // do nothing - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull Double e) { - return doubleToLongBits(e) == bytes.readLong(bytes.position()); - } - - @Override - public boolean equivalent(@NotNull Double a, @NotNull Double b) { - return doubleToLongBits(a) == doubleToLongBits(b); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull Double e) { - return hashFunction.hashLong(doubleToLongBits(e)); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull Double e) { - bytes.writeLong(doubleToLongBits(e)); - } - - @Override - public long readSize(Bytes bytes) { - return 8L; - } - - @NotNull - @Override - public Double read(@NotNull Bytes bytes, long size) { - return Double.longBitsToDouble(bytes.readLong()); - } - - @NotNull - @Override - public Double read(@NotNull Bytes bytes, long size, Double toReuse) { - return read(bytes, size); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValueMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValueMarshaller.java deleted file mode 100644 index af93b66a3..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValueMarshaller.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import static net.openhft.chronicle.hash.serialization.internal.DummyValue.DUMMY_VALUE; - -public enum DummyValueMarshaller - implements BytesInterop, BytesReader, SizeMarshaller { - INSTANCE; - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull DummyValue dummyValue) { - return true; - } - - @Override - public boolean equivalent(@NotNull DummyValue a, @NotNull DummyValue b) { - return true; - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull DummyValue dummyValue) { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public DummyValue read(@NotNull Bytes bytes, long size) { - return DUMMY_VALUE; - } - - @NotNull - @Override - public DummyValue read(@NotNull Bytes bytes, long size, DummyValue toReuse) { - return DUMMY_VALUE; - } - - @Override - public long size(@NotNull DummyValue dummyValue) { - return 0L; - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull DummyValue dummyValue) { - // do nothing - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return 0L; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == 0L; - // do nothing - } - - @Override - public long readSize(Bytes bytes) { - return 0L; - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/IntegerMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/IntegerMarshaller.java deleted file mode 100644 index 44621960a..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/IntegerMarshaller.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -public enum IntegerMarshaller - implements BytesInterop, BytesReader, SizeMarshaller { - INSTANCE; - - @Override - public long size(@NotNull Integer e) { - return 4L; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return 4L; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == 4L; - // do nothing - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull Integer e) { - return e == bytes.readInt(bytes.position()); - } - - @Override - public boolean equivalent(@NotNull Integer a, @NotNull Integer b) { - return a.intValue() == b.intValue(); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull Integer e) { - return hashFunction.hashInt(e); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull Integer e) { - bytes.writeInt(e); - } - - @Override - public long readSize(Bytes bytes) { - return 4L; - } - - @NotNull - @Override - public Integer read(@NotNull Bytes bytes, long size) { - return bytes.readInt(); - } - - @NotNull - @Override - public Integer read(@NotNull Bytes bytes, long size, Integer toReuse) { - return bytes.readInt(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/LongMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/LongMarshaller.java deleted file mode 100644 index 4dd21a9a6..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/LongMarshaller.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.chronicle.hash.serialization.BytesInterop; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -public enum LongMarshaller - implements BytesInterop, BytesReader, SizeMarshaller { - INSTANCE; - - @Override - public long size(@NotNull Long e) { - return 8L; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return 8L; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == 8L; - // do nothing - } - - @Override - public boolean startsWith(@NotNull Bytes bytes, @NotNull Long e) { - return e == bytes.readLong(bytes.position()); - } - - @Override - public boolean equivalent(@NotNull Long a, @NotNull Long b) { - return a.longValue() == b.longValue(); - } - - @Override - public long hash(@NotNull LongHashFunction hashFunction, @NotNull Long e) { - return hashFunction.hashLong(e); - } - - @Override - public void write(@NotNull Bytes bytes, @NotNull Long e) { - bytes.writeLong(e); - } - - @Override - public long readSize(Bytes bytes) { - return 8L; - } - - @NotNull - @Override - public Long read(@NotNull Bytes bytes, long size) { - return bytes.readLong(); - } - - @NotNull - @Override - public Long read(@NotNull Bytes bytes, long size, Long toReuse) { - return bytes.readLong(); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesInterop.java deleted file mode 100644 index f9cf49a6b..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesInterop.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.hashing.LongHashFunction; -import net.openhft.lang.io.Bytes; - -public interface MetaBytesInterop extends MetaBytesWriter { - - boolean startsWith(I interop, Bytes bytes, E e); - - boolean equivalent(I interop, E e, - MetaBytesInterop otherMetaInterop, I2 otherInterop, E other); - - long hash(I interop, LongHashFunction hashFunction, E e); -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesWriter.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesWriter.java deleted file mode 100644 index 4a956e100..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaBytesWriter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.lang.io.Bytes; - -import java.io.Serializable; - -public interface MetaBytesWriter extends Serializable { - long size(W writer, E e); - - void write(W writer, Bytes bytes, E e); -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaProvider.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaProvider.java deleted file mode 100644 index 71b2c7469..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/MetaProvider.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.lang.threadlocal.ThreadLocalCopies; - -import java.io.Serializable; - -public interface MetaProvider> extends Serializable { - - MW get(ThreadLocalCopies copies, MW originalMetaWriter, W writer, E e, boolean checked); - - ThreadLocalCopies getCopies(ThreadLocalCopies copies); -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ReaderWithSize.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/ReaderWithSize.java deleted file mode 100644 index 23b0a571f..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/ReaderWithSize.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.Nullable; - -public final class ReaderWithSize { - private final SizeMarshaller sizeMarshaller; - private final BytesReader originalReader; - private final Provider> readerProvider; - - public ReaderWithSize(SerializationBuilder serializationBuilder) { - sizeMarshaller = serializationBuilder.sizeMarshaller(); - originalReader = serializationBuilder.reader(); - readerProvider = (Provider>) Provider.of(originalReader.getClass()); - } - - public ThreadLocalCopies getCopies(ThreadLocalCopies copies) { - return readerProvider.getCopies(copies); - } - - public T read(Bytes in, @Nullable ThreadLocalCopies copies, @Nullable T using) { - long size = sizeMarshaller.readSize(in); - copies = readerProvider.getCopies(copies); - BytesReader reader = readerProvider.get(copies, originalReader); - return reader.read(in, size, using); - } - - public T readNullable(Bytes in, @Nullable ThreadLocalCopies copies, T using) { - if (in.readBoolean()) - return null; - return read(in, copies, using); - } - - public BytesReader readerForLoop(@Nullable ThreadLocalCopies copies) { - copies = readerProvider.getCopies(copies); - return readerProvider.get(copies, originalReader); - } - - public T readInLoop(Bytes in, BytesReader reader) { - long size = sizeMarshaller.readSize(in); - return reader.read(in, size); - } - - public T readNullableInLoop(Bytes in, BytesReader reader) { - if (in.readBoolean()) - return null; - return readInLoop(in, reader); - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/SerializationBuilder.java deleted file mode 100755 index 106c6f248..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/SerializationBuilder.java +++ /dev/null @@ -1,577 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.*; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -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.*; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.*; -import java.lang.reflect.Modifier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; - -import static net.openhft.chronicle.hash.serialization.internal.SizeMarshallers.constant; -import static net.openhft.chronicle.hash.serialization.internal.SizeMarshallers.stopBit; -import static net.openhft.chronicle.hash.impl.util.Objects.hash; - -public final class SerializationBuilder implements Cloneable, Serializable { - private static final long serialVersionUID = 0L; - - private static final Bytes EMPTY_BYTES = new ByteBufferBytes(ByteBuffer.allocate(0)); - - 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) || - Externalizable.class.isAssignableFrom(c); - } - - private static final List knownJDKImmutableClasses = Arrays.asList( - String.class, Boolean.class, Byte.class, Short.class, Character.class, Integer.class, - Float.class, Long.class, Double.class, BigDecimal.class, BigInteger.class, URL.class - ); - - private static boolean instancesAreMutable(Class c) { - return !knownJDKImmutableClasses.contains(c); - } - - public enum Role {KEY, VALUE} - - private enum CopyingInterop {FROM_MARSHALLER, FROM_WRITER} - - private final Role role; - public final Class eClass; - private boolean instancesAreMutable; - private SizeMarshaller sizeMarshaller = stopBit(); - private BytesReader reader; - private Object interop; - private CopyingInterop copyingInterop = null; - private MetaBytesInterop metaInterop; - private MetaProvider metaInteropProvider; - private long maxSize; - - public final boolean sizeIsStaticallyKnown; - - boolean serializesGeneratedClasses = false; - - @SuppressWarnings("unchecked") - public SerializationBuilder(Class eClass, Role role) { - this.role = role; - this.eClass = eClass; - configureByDefault(eClass, role); - sizeIsStaticallyKnown = constantSizeMarshaller(); - } - - private void configureByDefault(Class eClass, Role role) { - instancesAreMutable = instancesAreMutable(eClass); - - if (eClass.isInterface()) { - try { - BytesReader reader = DataValueBytesMarshallers.acquireBytesReader(eClass); - BytesWriter writer = DataValueBytesMarshallers.acquireBytesWriter(eClass); - DataValueModel model = DataValueModels.acquireModel(eClass); - int size = DataValueGenerator.computeNonScalarOffset(model, eClass); - reader(reader); - copyingInterop(null); - setInterop(writer); - metaInterop((MetaBytesInterop) DataValueMetaBytesInterop.forIdentity(role)); - metaInteropProvider(DataValueMetaBytesInterop.interopProvider(eClass)); - sizeMarshaller(constant((long) size)); - serializesGeneratedClasses = true; - return; - } catch (Exception e) { - try { - eClass = DataValueClasses.directClassFor(eClass); - serializesGeneratedClasses = true; - } catch (Exception ex) { - // ignore, fall through - } - // ignore, fall through - } - } - - ObjectFactory factory = concreteClass(eClass) && marshallerUseFactory(eClass) ? - new NewInstanceObjectFactory(eClass) : - NullObjectFactory.of(); - - if (concreteClass(eClass) && Byteable.class.isAssignableFrom(eClass)) { - ByteableMarshaller byteableMarshaller = ByteableMarshaller.of((Class) eClass); - sizeMarshaller(byteableMarshaller); - reader(byteableMarshaller); - interop(byteableMarshaller); - } else if (eClass == CharSequence.class || eClass == String.class) { - reader((BytesReader) CharSequenceReader.of()); - writer((BytesWriter) CharSequenceWriter.instance()); - } else if (eClass == StringBuilder.class) { - reader((BytesReader) CharSequenceReader.ofStringBuilder()); - writer((BytesWriter) CharSequenceWriter.instance()); - } else if (eClass == Boolean.class) { - sizeMarshaller(BooleanMarshaller.INSTANCE); - reader((BytesReader) BooleanMarshaller.INSTANCE); - interop((BytesInterop) BooleanMarshaller.INSTANCE); - } else if (eClass == Long.class) { - sizeMarshaller(LongMarshaller.INSTANCE); - reader((BytesReader) LongMarshaller.INSTANCE); - interop((BytesInterop) LongMarshaller.INSTANCE); - } else if (eClass == Double.class) { - sizeMarshaller(DoubleMarshaller.INSTANCE); - reader((BytesReader) DoubleMarshaller.INSTANCE); - interop((BytesInterop) DoubleMarshaller.INSTANCE); - } else if (eClass == Integer.class) { - sizeMarshaller(IntegerMarshaller.INSTANCE); - reader((BytesReader) IntegerMarshaller.INSTANCE); - interop((BytesInterop) IntegerMarshaller.INSTANCE); - } else if (eClass == byte[].class) { - reader((BytesReader) ByteArrayMarshaller.INSTANCE); - interop((BytesInterop) ByteArrayMarshaller.INSTANCE); - } else if (eClass == char[].class) { - reader((BytesReader) CharArrayMarshaller.INSTANCE); - interop((BytesInterop) CharArrayMarshaller.INSTANCE); - } else if (eClass == ByteBuffer.class) { - reader((BytesReader) ByteBufferMarshaller.INSTANCE); - writer((BytesWriter) ByteBufferMarshaller.INSTANCE); - } else if (concreteClass(eClass)) { - BytesMarshaller marshaller = chooseMarshaller(eClass, eClass); - if (marshaller != null) - marshaller(marshaller); - } - if (concreteClass(eClass) && marshallerUseFactory(eClass)) { - factory(factory); - } - } - - private void writeObject(ObjectOutputStream out) throws IOException { - out.writeBoolean(serializesGeneratedClasses); - if (serializesGeneratedClasses) { - out.writeObject(eClass); - out.writeObject(role); - } - out.defaultWriteObject(); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - boolean generatedClassesSerialized = in.readBoolean(); - if (generatedClassesSerialized) { - Class eClass = (Class) in.readObject(); - Role role = (Role) in.readObject(); - new SerializationBuilder(eClass, role); - } - in.defaultReadObject(); - } - - public boolean possibleOffHeapReferences() { - if (reader instanceof CharSequenceReader) - return false; - // exclude some known classes, most notably boxed primitive types - if (!instancesAreMutable(eClass)) - return false; - if (eClass.isArray() && (eClass.getComponentType().isPrimitive() || - instancesAreMutable(eClass.getComponentType()))) - return false; - BytesMarshaller marshallerAsReader = BytesReaders.getBytesMarshaller(reader); - if (marshallerAsReader instanceof SerializableMarshaller || - marshallerAsReader instanceof ExternalizableMarshaller) - return false; - // otherwise reader could possibly keep the given bytes addresses and update off-heap memory - return true; - } - - @SuppressWarnings("unchecked") - private BytesMarshaller chooseMarshaller(Class eClass, Class classForMarshaller) { - if (BytesMarshallable.class.isAssignableFrom(eClass)) - return new BytesMarshallableMarshaller(classForMarshaller); - if (Externalizable.class.isAssignableFrom(eClass)) - return new ExternalizableMarshaller(classForMarshaller); - return null; - } - - private SerializationBuilder copyingInterop(CopyingInterop copyingInterop) { - this.copyingInterop = copyingInterop; - return this; - } - - public SerializationBuilder interop(BytesInterop interop) { - return copyingInterop(null) - .setInterop(interop) - .metaInterop(DelegatingMetaBytesInterop.>instance()) - .metaInteropProvider(DelegatingMetaBytesInteropProvider - .>instance()); - } - - public SerializationBuilder writer(BytesWriter writer) { - if (writer instanceof BytesInterop) - return interop((BytesInterop) writer); - return copyingInterop(CopyingInterop.FROM_WRITER) - .setInterop(writer) - .metaInterop(CopyingMetaBytesInterop - .>forBytesWriter(role)); - } - - public SerializationBuilder marshaller(BytesMarshaller marshaller) { - return copyingInterop(CopyingInterop.FROM_MARSHALLER) - .reader(BytesReaders.fromBytesMarshaller(marshaller)) - .setInterop(marshaller) - .metaInterop(CopyingMetaBytesInterop - .>forBytesMarshaller(role)); - } - - public SerializationBuilder maxSize(long maxSize) { - this.maxSize = maxSize; - if (copyingInterop == CopyingInterop.FROM_MARSHALLER) { - metaInteropProvider(CopyingMetaBytesInterop - .>providerForBytesMarshaller( - instancesAreMutable, maxSize)); - } else if (copyingInterop == CopyingInterop.FROM_WRITER) { - metaInteropProvider(CopyingMetaBytesInterop - .>providerForBytesWriter(instancesAreMutable)); - } - return this; - } - - public long maxSize() { - return maxSize; - } - - public long serializationSize(E sampleObject) { - Object originalInterop = this.interop; - Provider interopProvider = Provider.of(originalInterop.getClass()); - ThreadLocalCopies copies = interopProvider.getCopies(null); - Object interop = interopProvider.get(copies, originalInterop); - copies = metaInteropProvider.getCopies(copies); - MetaBytesWriter metaInterop; - if (maxSize > 0) { - // this loop is very dumb: tries to find buffer size, sufficient to serialize - // the object, by trying to serialize to small buffers first and doubling the buffer - // size on _any_ Exception (it may be IllegalArgument, IndexOutOfBounds, IllegalState, - // see JLANG-17 issue). - // TODO The question is: couldn't this cause JVM crash without throwing an exception? - findSufficientSerializationSize: - while (true) { - MetaProvider metaInteropProvider = this.metaInteropProvider; - try { - metaInterop = metaInteropProvider.get( - copies, this.metaInterop, interop, sampleObject, true); - break findSufficientSerializationSize; - } catch (Exception e) { - CopyingMetaBytesInterop.checkMaxSizeStillReasonable(maxSize, e); - maxSize(maxSize * 2); - } - } - } else { - MetaProvider metaInteropProvider = this.metaInteropProvider; - metaInterop = metaInteropProvider.get( - copies, this.metaInterop, interop, sampleObject, true); - } - return metaInterop.size(interop, sampleObject); - } - - public SerializationBuilder constantSizeBySample(E sampleObject) { - long constantSize = serializationSize(sampleObject); - if (sizeIsStaticallyKnown) { - long expectedConstantSize = pseudoReadConstantSize(); - if (constantSize != expectedConstantSize) { - throw new IllegalStateException("Although configuring constant size by sample " + - "is not forbidden for types which size we already know statically, they " + - "should be the same. For " + eClass + " we know constant size is " + - expectedConstantSize + " statically, configured sample is " + sampleObject + - " which size in serialized form is " + constantSize); - } - } - // set max size once more, because current maxSize could be x64 or x2 larger than needed - maxSize(constantSize); - sizeMarshaller(SizeMarshallers.constant(constantSize)); - return this; - } - - public SerializationBuilder objectSerializer(ObjectSerializer serializer) { - if (reader == null || interop == null) { - marshaller(new SerializableMarshaller(serializer, eClass)); - } - return this; - } - - public SerializationBuilder instancesAreMutable(boolean mutable) { - this.instancesAreMutable = mutable; - return this; - } - - public SizeMarshaller sizeMarshaller() { - return sizeMarshaller; - } - - public boolean constantSizeMarshaller() { - try { - return sizeMarshaller().sizeEncodingSize(1L) == 0; - } catch (Exception e) { - // size marshaller thrown likely IllegalArgumentException, that means it doesn't - // expect size 1. marshaller of constant size shouldn't do that, it's body should be - // just `return 0;` - return false; - } - } - - public boolean constantSizeEncodingSizeMarshaller() { - return sizeMarshaller().minSizeEncodingSize() == sizeMarshaller().maxSizeEncodingSize(); - } - - public long pseudoReadConstantSize() { - return sizeMarshaller().readSize(EMPTY_BYTES); - } - - public SerializationBuilder sizeMarshaller(SizeMarshaller sizeMarshaller) { - this.sizeMarshaller = sizeMarshaller; - return this; - } - - public BytesReader reader() { - return reader; - } - - public SerializationBuilder reader(BytesReader reader) { - this.reader = reader; - return this; - } - - public Object interop() { - return interop; - } - - private SerializationBuilder setInterop(Object interop) { - this.interop = interop; - return this; - } - - public MetaBytesInterop metaInterop() { - return metaInterop; - } - - private SerializationBuilder metaInterop(MetaBytesInterop metaInterop) { - this.metaInterop = metaInterop; - return this; - } - - @SuppressWarnings("unchecked") - public MetaProvider> metaInteropProvider() { - return (MetaProvider>) metaInteropProvider; - } - - private SerializationBuilder metaInteropProvider( - MetaProvider metaInteropProvider) { - this.metaInteropProvider = metaInteropProvider; - return this; - } - - @SuppressWarnings("unchecked") - public SerializationBuilder factory(ObjectFactory factory) { - if (reader instanceof DeserializationFactoryConfigurableBytesReader) { - DeserializationFactoryConfigurableBytesReader newReader = - ((DeserializationFactoryConfigurableBytesReader) reader) - .withDeserializationFactory(factory); - reader(newReader); - if (newReader instanceof BytesInterop) - interop((BytesInterop) newReader); - if (newReader instanceof SizeMarshaller) - sizeMarshaller((SizeMarshaller) newReader); - return this; - } - if (!marshallerUseFactory(eClass)) { - throw new IllegalStateException("Default marshaller for " + eClass + - " value don't use object factory"); - } else if (interop instanceof BytesMarshallableMarshaller) { - if (factory instanceof AllocateInstanceObjectFactory) { - interop = new BytesMarshallableMarshaller( - ((AllocateInstanceObjectFactory) factory).allocatedClass()); - } else { - interop = new BytesMarshallableMarshallerWithCustomFactory( - ((BytesMarshallableMarshaller) interop).marshaledClass(), - factory - ); - } - } else if (interop instanceof ExternalizableMarshaller) { - if (factory instanceof AllocateInstanceObjectFactory) { - interop = new ExternalizableMarshaller( - ((AllocateInstanceObjectFactory) factory).allocatedClass()); - } else { - interop = new ExternalizableMarshallerWithCustomFactory( - ((ExternalizableMarshaller) interop).marshaledClass(), - factory - ); - } - } else { - // interop is custom, it is user's responsibility to use the same factory inside - // marshaller and standalone - String role = this.role.toString().toLowerCase(); - throw new IllegalStateException( - role + "DeserializationFactory() should be called " + - "only if the Map " + role + " type is Byteable, BytesMarshallable " + - "or Externalizable subtype and no custom marshallers were configured."); - } - return this; - } - - @Override - public SerializationBuilder clone() { - try { - return (SerializationBuilder) super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - - private static class SerializableMarshaller implements BytesMarshaller { - private static final long serialVersionUID = 0L; - - private final ObjectSerializer serializer; - private final Class expectedClass; - - private SerializableMarshaller(ObjectSerializer serializer, Class expectedClass) { - this.serializer = serializer; - this.expectedClass = expectedClass; - } - - @Override - public void write(Bytes bytes, Object obj) { - try { - serializer.writeSerializable(bytes, obj, expectedClass); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - @Nullable - @Override - public Object read(Bytes bytes) { - try { - return serializer.readSerializable(bytes, null, null); - } catch (IOException e) { - throw new IllegalStateException(e); - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e); - } - } - - @Nullable - @Override - public Object read(Bytes bytes, @Nullable Object obj) { - try { - return serializer.readSerializable(bytes, null, obj); - } catch (IOException e) { - throw new IllegalStateException(e); - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e); - } - } - } - - private static class BytesMarshallableMarshallerWithCustomFactory - extends BytesMarshallableMarshaller { - private static final long serialVersionUID = 0L; - - @NotNull - private final ObjectFactory factory; - - BytesMarshallableMarshallerWithCustomFactory(@NotNull Class tClass, - @NotNull ObjectFactory factory) { - super(tClass); - this.factory = factory; - } - - @NotNull - @Override - protected T getInstance() throws Exception { - return factory.create(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != getClass()) - return false; - BytesMarshallableMarshallerWithCustomFactory that = - (BytesMarshallableMarshallerWithCustomFactory) obj; - return that.marshaledClass() == marshaledClass() && that.factory.equals(this.factory); - } - - @Override - public int hashCode() { - return hash(marshaledClass(), factory); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{marshaledClass=" + marshaledClass() + - ",factory=" + factory + "}"; - } - } - - private static class ExternalizableMarshallerWithCustomFactory - extends ExternalizableMarshaller { - private static final long serialVersionUID = 0L; - - @NotNull - private final ObjectFactory factory; - - ExternalizableMarshallerWithCustomFactory(@NotNull Class tClass, - @NotNull ObjectFactory factory) { - super(tClass); - this.factory = factory; - } - - @NotNull - @Override - protected T getInstance() throws Exception { - return factory.create(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != getClass()) - return false; - ExternalizableMarshallerWithCustomFactory that = - (ExternalizableMarshallerWithCustomFactory) obj; - return that.marshaledClass() == marshaledClass() && that.factory.equals(this.factory); - } - - @Override - public int hashCode() { - return hash(marshaledClass(), factory); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{marshaledClass=" + marshaledClass() + - ",factory=" + factory + "}"; - } - } -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/SizeMarshallers.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/SizeMarshallers.java deleted file mode 100644 index 20be3999e..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/SizeMarshallers.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.hash.serialization.internal; - -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.lang.io.Bytes; - -import static net.openhft.lang.io.IOTools.stopBitLength; - -public final class SizeMarshallers { - - public static SizeMarshaller stopBit() { - return StopBit.INSTANCE; - } - - private enum StopBit implements SizeMarshaller { - INSTANCE; - - @Override - public int sizeEncodingSize(long size) { - return stopBitLength(size); - } - - @Override - public long minEncodableSize() { - return 0L; - } - - @Override - public int minSizeEncodingSize() { - return 1; - } - - @Override - public int maxSizeEncodingSize() { - return 9; - } - - @Override - public void writeSize(Bytes bytes, long size) { - bytes.writeStopBit(size); - } - - @Override - public long readSize(Bytes bytes) { - return bytes.readStopBit(); - } - } - - public static SizeMarshaller constant(long size) { - return new ConstantSizeMarshaller(size); - } - - private static class ConstantSizeMarshaller implements SizeMarshaller { - private static final long serialVersionUID = 0L; - - private final long size; - - private ConstantSizeMarshaller(long size) { - this.size = size; - } - - @Override - public int sizeEncodingSize(long size) { - return 0; - } - - @Override - public long minEncodableSize() { - return size; - } - - @Override - public int minSizeEncodingSize() { - return 0; - } - - @Override - public int maxSizeEncodingSize() { - return 0; - } - - @Override - public void writeSize(Bytes bytes, long size) { - assert size == this.size; - // do nothing - } - - @Override - public long readSize(Bytes bytes) { - return size; - } - } - - private SizeMarshallers() {} -} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/package-info.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/package-info.java deleted file mode 100644 index 409c572f9..000000000 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 . - */ - -/** - * Classes, which should be part of the parent {@code net.openhft.chronicle.hash.serialization} - * package, but shouldn't be used in the user code (in 99% of cases). This package isn't - * documented in published javadocs. - */ -package net.openhft.chronicle.hash.serialization.internal; \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/package-info.java b/src/main/java/net/openhft/chronicle/hash/serialization/package-info.java new file mode 100644 index 000000000..9455a319d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/package-info.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ + +/** + * The package contains interfaces for serializing objects and values between Java heap and {@link + * net.openhft.chronicle.bytes.Bytes} or {@link net.openhft.chronicle.bytes.BytesStore}. + * + *

Reading methods in the interfaces in this package could use {@link + * net.openhft.chronicle.bytes.StreamingDataInput} as the "input" parameter type and {@link + * net.openhft.chronicle.bytes.StreamingDataOutput} as the "output" parameter type, but always use + * just {@link net.openhft.chronicle.bytes.Bytes} and {@link net.openhft.chronicle.bytes.BytesStore + * }, though this is "unsafe" because somebody could make a mistake and write into bytes supposed to + * be read-only or read some garbage bytes. This is done because of the poor support of + * StreamingDataInput/StreamingDataOutput in Chronicle Bytes and other projects. {@link + * net.openhft.chronicle.bytes.Byteable}, {@link net.openhft.chronicle.bytes.BytesMarshallable}, + * Chronicle Wire and others support only BytesStore or Bytes, but not read/write separated + * interfaces. + */ +package net.openhft.chronicle.hash.serialization; \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java index 2deb66d20..b3d30c506 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChannelReplicator.java @@ -16,12 +16,11 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.core.io.CloseablesManager; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.ThrottlingConfig; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.thread.NamedThreadFactory; +import net.openhft.chronicle.threads.NamedThreadFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -70,8 +69,9 @@ abstract class AbstractChannelReplicator implements Closeable { private final ExecutorService connectExecutorService = Executors.newCachedThreadPool( new NamedThreadFactory("TCP-connect", true) { + @NotNull @Override - public Thread newThread(@net.openhft.lang.model.constraints.NotNull Runnable r) { + public Thread newThread(@NotNull Runnable r) { return lastThread = super.newThread(r); } }); @@ -79,7 +79,7 @@ abstract class AbstractChannelReplicator implements Closeable { private volatile Thread lastThread; private Throwable startedHere; private Future future; - private final Queue pendingRegistrations = new ConcurrentLinkedQueue(); + private final Queue pendingRegistrations = new ConcurrentLinkedQueue<>(); @Nullable private final Throttler throttler; @@ -89,8 +89,9 @@ abstract class AbstractChannelReplicator implements Closeable { throws IOException { executorService = Executors.newSingleThreadExecutor( new NamedThreadFactory(name, true) { + @NotNull @Override - public Thread newThread(@net.openhft.lang.model.constraints.NotNull Runnable r) { + public Thread newThread(@NotNull Runnable r) { return lastThread = super.newThread(r); } }); @@ -434,60 +435,27 @@ abstract class AbstractChannelReplicator implements Closeable { } } - static class EntryCallback extends Replica.EntryCallback implements BufferResizer { + static class EntryCallback extends Replica.EntryCallback { private final Replica.EntryExternalizable externalizable; - @NotNull - private ByteBufferBytes in; - - @NotNull - private ByteBuffer out; + /** For writing entries for replication from Ch Map memory */ + private Bytes entryIn; EntryCallback(@NotNull final Replica.EntryExternalizable externalizable, final int tcpBufferSize) { this.externalizable = externalizable; - out = ByteBuffer.allocateDirect(tcpBufferSize); - in = new ByteBufferBytes(out); + entryIn = Bytes.elasticByteBuffer(tcpBufferSize); } @NotNull - public ByteBufferBytes in() { - return in; + public Bytes entryIn() { + return entryIn; } @NotNull - public ByteBuffer out() { - return out; - } - - - @Override - public Bytes resizeBuffer(int size) { - - if (LOG.isDebugEnabled()) - LOG.debug("resizing buffer to size=" + size); - - if (size < out.capacity()) - throw new IllegalStateException("it not possible to resize the buffer smaller"); - - assert size < Integer.MAX_VALUE; - - final ByteBuffer result = ByteBuffer.allocate(size).order(ByteOrder.nativeOrder()); - final long bytesPosition = in.position(); - - in = new ByteBufferBytes(result); - - out.position(0); - out.limit((int) bytesPosition); - in.write(out); - out = result; - - assert out.capacity() == in.capacity(); - assert out.capacity() == size; - assert out.capacity() == in.capacity(); - assert in.limit() == in.capacity(); - return in; + public ByteBuffer socketOut() { + return entryIn.underlyingObject(); } @Override @@ -495,76 +463,41 @@ abstract class AbstractChannelReplicator implements Closeable { return !externalizable.identifierCheck(entry, chronicleId); } - @Override - public boolean onEntry(@NotNull final Bytes entry, - final int chronicleId, - final long bootstrapTime) { + public boolean onEntry( + @NotNull final Bytes entry, final int chronicleId, final long bootstrapTime) { - long startOfEntry = entry.position(); - long pos0 = in.position(); - long start = 0; - try { - // used to denote that this is not a heartbeat - in.writeByte(STATEFUL_UPDATE); + long pos0 = entryIn.writePosition(); + // used to denote that this is not a heartbeat + entryIn.writeByte(STATEFUL_UPDATE); - long sizeLocation = in.position(); + long sizeLocation = entryIn.writePosition(); - // this is where we will store the size of the entry - in.skip(SIZE_OF_SIZE); + // this is where we will store the size of the entry + entryIn.writeSkip(SIZE_OF_SIZE); - start = in.position(); + long start = entryIn.writePosition(); - externalizable.writeExternalEntry(entry, in, chronicleId, bootstrapTime); - - if (in.position() == start) { - in.position(pos0); - return false; - } - - // write the length of the entry, just before the start, so when we read it back - // we read the length of the entry first and hence know how many preceding writer to read - final long bytesWritten = (int) (in.position() - start); - - if (bytesWritten > Integer.MAX_VALUE) - throw new IllegalStateException("entry too large, " + - "entries are limited to a size of " + Integer.MAX_VALUE); - - if (LOG.isDebugEnabled()) - LOG.debug("sending entry of entrySize=" + (int) bytesWritten); - - in.writeInt(sizeLocation, (int) bytesWritten); - - } catch (IllegalArgumentException e) { - - // reset the entries position - entry.position(startOfEntry); - - // reset the in-buffers position - in.position(pos0); - long remaining = in.remaining(); - int entrySize = externalizable.sizeOfEntry(entry, chronicleId); - - - if (entrySize > remaining) { - - long newSize = start + entrySize; - - // This can occur when we pack a number of entries into the buffer and the - // last entry is very large. - if (newSize > Integer.MAX_VALUE) - return false; - - resizeBuffer((int) newSize); - - in.position(pos0); - entry.position(startOfEntry); - - return onEntry(entry, chronicleId, bootstrapTime); - } else - throw e; + externalizable.writeExternalEntry(entry, entryIn, chronicleId, bootstrapTime); + if (entryIn.writePosition() == start) { + entryIn.writePosition(pos0); + return false; } + + // write the length of the entry, just before the start, so when we read it back + // we read the length of the entry first and hence know how many preceding writer + // to read + final long bytesWritten = (int) (entryIn.writePosition() - start); + + if (bytesWritten > Integer.MAX_VALUE) + throw new IllegalStateException("entry size " + bytesWritten + " too large, " + + "entries are limited to a size of " + Integer.MAX_VALUE); + + if (LOG.isDebugEnabled()) + LOG.debug("sending entry of entrySize=" + (int) bytesWritten); + + entryIn.writeInt(sizeLocation, (int) bytesWritten); return true; } } diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java index e7c8d5523..44ec55356 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java @@ -177,7 +177,15 @@ interface AbstractChronicleMap extends ChronicleMap, Serializable { try { return forEachEntryWhile(c -> { K k = c.key().get(); - V v = (V) m.get(k instanceof CharSequence ? k.toString() : k); + V v = (V) m.get(k); + if (v instanceof CharSequence) { + return CharSequences.equivalent( + (CharSequence) v, (CharSequence) c.value().get()); + } else if (v instanceof Set) { + return v.equals(c.value().get()); + } else if (v instanceof Map) { + return v.equals(c.value().get()); + } return v != null && c.value().equals(c.context().wrapValueAsData(v)); }); } catch (ClassCastException unused) { @@ -195,7 +203,7 @@ interface AbstractChronicleMap extends ChronicleMap, Serializable { // TODO quick and dirty. Think about how generic guava/koloboke equivalence interface could be // used. See also BytesInterop.equivalent() and hash(). - public static int hashCode(Object obj) { + static int hashCode(Object obj) { if (!(obj instanceof CharSequence)) { return obj.hashCode(); } else { diff --git a/src/main/java/net/openhft/chronicle/map/Alignment.java b/src/main/java/net/openhft/chronicle/map/Alignment.java deleted file mode 100644 index fe8904695..000000000 --- a/src/main/java/net/openhft/chronicle/map/Alignment.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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; - -/** - * Memory addresses alignment strategies. - * - * @see ChronicleMapBuilder#entryAndValueAlignment(Alignment) - */ -public enum Alignment { - /** - * Doesn't align memory addresses. - */ - NO_ALIGNMENT { - @Override - public void alignPositionAddr(Bytes bytes) { - // no-op - } - - @Override - public long alignAddr(long addr) { - return addr; - } - - @Override - int alignSize(int size) { - return size; - } - - @Override - int alignment() { - return 1; - } - }, - - /** - * Aligns memory addresses on 4-byte boundary. - */ - OF_4_BYTES { - @Override - public void alignPositionAddr(Bytes bytes) { - bytes.alignPositionAddr(4); - } - - @Override - public long alignAddr(long addr) { - return (addr + 3) & ~3; - } - - @Override - int alignSize(int size) { - return (size + 3) & ~3; - } - - @Override - int alignment() { - return 4; - } - }, - - /** - * Aligns memory addresses on 8-byte boundary. - */ - OF_8_BYTES { - @Override - public void alignPositionAddr(Bytes bytes) { - bytes.alignPositionAddr(8); - } - - @Override - public long alignAddr(long addr) { - return (addr + 7) & ~7; - } - - @Override - int alignSize(int size) { - return (size + 7) & ~7; - } - - @Override - int alignment() { - return 8; - } - }; - - private static final Alignment[] VALUES = values(); - - static Alignment fromOrdinal(int ordinal) { - return VALUES[ordinal]; - } - - public abstract void alignPositionAddr(Bytes bytes); - - public abstract long alignAddr(long addr); - - abstract int alignSize(int size); - - abstract int alignment(); -} diff --git a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java index 2c574f6b1..4dad860b3 100644 --- a/src/main/java/net/openhft/chronicle/map/ChannelProvider.java +++ b/src/main/java/net/openhft/chronicle/map/ChannelProvider.java @@ -16,21 +16,23 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.algo.bitset.BitSet; +import net.openhft.chronicle.algo.bitset.ReusableBitSet; +import net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame; +import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.HeapBytesStore; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.ReplicationHub; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.UdpTransportConfig; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.collection.SingleThreadedDirectBitSet; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.IOException; -import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.LinkedTransferQueue; @@ -78,7 +80,7 @@ public final class ChannelProvider implements Closeable { udpConfig); channelProvider.add(udpReplicator); if (tcpConfig == null) - LOG.warn(Replicators.ONLY_UDP_WARN_MESSAGE); + LOG.warn(Replicator.ONLY_UDP_WARN_MESSAGE); } implMapping.put(hub, channelProvider); return channelProvider; @@ -308,7 +310,7 @@ public final class ChannelProvider implements Closeable { private final EntryExternalizable[] channelEntryExternalizables; private final AtomicReferenceArray systemModificationIterator = new AtomicReferenceArray(128); - private final DirectBitSet systemModificationIteratorBitSet = + private final BitSet systemModificationIteratorBitSet = newBitSet(systemModificationIterator.length()); private final AtomicReferenceArray modificationIterator = new AtomicReferenceArray(128); @@ -352,9 +354,10 @@ public final class ChannelProvider implements Closeable { * @param numberOfBits the number of bits the bit set should include * @return a new DirectBitSet backed by a byteBuffer */ - private static DirectBitSet newBitSet(int numberOfBits) { - final ByteBufferBytes bytes = new ByteBufferBytes(wrap(new byte[(numberOfBits + 7) / 8])); - return new SingleThreadedDirectBitSet(bytes); + private static BitSet newBitSet(int numberOfBits) { + HeapBytesStore bs = BytesStore.wrap(new byte[(numberOfBits + 7) / 8]); + SingleThreadedFlatBitSetFrame frame = new SingleThreadedFlatBitSetFrame(numberOfBits); + return new ReusableBitSet(frame, Access.checkedBytesStoreAccess(), bs, 0); } public ChronicleChannel createChannel(int channel) { @@ -381,13 +384,13 @@ public final class ChannelProvider implements Closeable { } } - private static ByteBufferBytes toBootstrapMessage(int chronicleChannel, final long lastModificationTime, final byte localIdentifier) { - final ByteBufferBytes writeBuffer = new ByteBufferBytes(ByteBuffer.allocate(1 + 1 + 2 + 8)); + private static Bytes toBootstrapMessage( + int chronicleChannel, final long lastModificationTime, final byte localIdentifier) { + final Bytes writeBuffer = Bytes.wrapForWrite(new byte[1 + 1 + 2 + 8]); writeBuffer.writeByte(BOOTSTRAP_MESSAGE); writeBuffer.writeByte(localIdentifier); writeBuffer.writeUnsignedShort(chronicleChannel); writeBuffer.writeLong(lastModificationTime); - writeBuffer.flip(); return writeBuffer; } @@ -418,7 +421,7 @@ public final class ChannelProvider implements Closeable { i = (int) systemModificationIteratorBitSet.nextSetBit(i + 1)) { byte remoteIdentifier = (byte) i; final long lastModificationTime = replica.lastModificationTime(remoteIdentifier); - final ByteBufferBytes message = + final Bytes message = toBootstrapMessage(chronicleChannel, lastModificationTime, localIdentifier); systemModificationIterator.get(remoteIdentifier).addPayload(message); @@ -485,7 +488,7 @@ public final class ChannelProvider implements Closeable { final PayloadProvider iterator = new PayloadProvider() { - final Queue payloads = new LinkedTransferQueue(); + final Queue payloads = new LinkedTransferQueue<>(); ModificationNotifier modificationNotifier0; @Override @@ -514,7 +517,7 @@ public final class ChannelProvider implements Closeable { @Override public void addPayload(Bytes bytes) { - if (bytes.remaining() == 0) + if (bytes.readRemaining() == 0) return; payloads.add(bytes); // notifies that a change has been made, this will nudge the OP_WRITE @@ -547,7 +550,7 @@ public final class ChannelProvider implements Closeable { final EntryExternalizable asEntryExternalizable = new EntryExternalizable() { @Override public int sizeOfEntry(@NotNull Bytes entry, int chronicleId) { - return (int) entry.remaining(); + return (int) entry.readRemaining(); } @Override @@ -558,7 +561,7 @@ public final class ChannelProvider implements Closeable { @Override public void writeExternalEntry(@NotNull Bytes entry, @NotNull Bytes destination, int na, long bootstrapTime) { - destination.write(entry, entry.position(), entry.remaining()); + destination.write(entry, entry.readPosition(), entry.readRemaining()); } @Override @@ -567,11 +570,11 @@ public final class ChannelProvider implements Closeable { messageHandler.onMessage(source); } }; - private final DirectBitSet systemModificationIteratorBitSet; + private final BitSet systemModificationIteratorBitSet; private final AtomicReferenceArray systemModificationIterator; private final MessageHandler messageHandler; - SystemQueue(DirectBitSet systemModificationIteratorBitSet, + SystemQueue(BitSet systemModificationIteratorBitSet, AtomicReferenceArray systemModificationIterator, MessageHandler messageHandler) { this.systemModificationIteratorBitSet = systemModificationIteratorBitSet; @@ -580,7 +583,7 @@ public final class ChannelProvider implements Closeable { } } - public class ChronicleChannel extends Replicator implements Closeable { + public class ChronicleChannel implements Replicator, Closeable { private final int chronicleChannel; @@ -593,9 +596,9 @@ public final class ChannelProvider implements Closeable { } @Override - protected Closeable applyTo(ChronicleMapBuilder builder, - Replica map, EntryExternalizable entryExternalizable, - final ReplicatedChronicleMap replicatedMap) { + public Closeable applyTo(ChronicleMapBuilder builder, + Replica map, EntryExternalizable entryExternalizable, + final ReplicatedChronicleMap replicatedMap) { add(chronicleChannel, map, entryExternalizable); return this; } diff --git a/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java b/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java index 3a21d6371..4a9206835 100644 --- a/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java +++ b/src/main/java/net/openhft/chronicle/map/ChroncileMapJsonSerializer.java @@ -19,7 +19,8 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import net.openhft.xstream.converters.ByteBufferConverter; -import net.openhft.xstream.converters.DataValueConverter; +import net.openhft.xstream.converters.StringBuilderConverter; +import net.openhft.xstream.converters.ValueConverter; import net.openhft.xstream.converters.VanillaChronicleMapConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,7 +69,8 @@ class JsonSerializer { registerChronicleMapConverter(map, xstream); xstream.registerConverter(new ByteBufferConverter()); - xstream.registerConverter(new DataValueConverter()); + xstream.registerConverter(new ValueConverter()); + xstream.registerConverter(new StringBuilderConverter()); for (Object c : jsonConverters) { if (c instanceof Converter) { diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java index ac52276e4..2f429f4d4 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java @@ -16,12 +16,11 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Byteable; import net.openhft.chronicle.core.util.SerializableFunction; import net.openhft.chronicle.hash.ChronicleHash; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshaller; -import net.openhft.lang.model.Byteable; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.SizedWriter; import org.jetbrains.annotations.NotNull; import java.io.Closeable; @@ -72,9 +71,10 @@ public interface ChronicleMap extends ConcurrentMap, * Returns the value to which the specified key is mapped, or {@code null} if this map contains * no mapping for the key. * - *

If the value class allows reusing, particularly if it is a {@link Byteable} subclass, - * consider {@link #getUsing(Object, Object)} method instead of this to reduce garbage - * creation. + *

If the value class allows reusing, consider {@link #getUsing(Object, Object)} method + * instead of this to reduce garbage creation. Read the section about usage + * patterns in the Chronicle Map 3 Tutorial for more. * * @param key the key whose associated value is to be returned * @return the value to which the specified key is mapped after this method call, or {@code @@ -89,11 +89,9 @@ public interface ChronicleMap extends ConcurrentMap, * object, if possible, or returns {@code null}, if this map contains no mapping for the key. * *

If the specified key is present in the map, the value data is read to the provided {@code - * value} object via value marshaller's {@link BytesMarshaller#read(Bytes, Object) read(Bytes, - * value)} or value reader's {@link BytesReader#read(Bytes, long, Object) read(Bytes, size, - * value)} method, depending on what deserialization strategy is configured on the builder, - * using which this map was constructed. If the value deserializer is able to reuse the given - * {@code value} object, calling this method instead of {@link #get(Object)} could help to + * value} object via value reader's {@link SizedReader#read(net.openhft.chronicle.bytes.Bytes, long, Object) + * read(StreamingDataInput, size, value)} method. If the value deserializer is able to reuse the + * given {@code value} object, calling this method instead of {@link #get(Object)} could help to * reduce garbage creation. * *

The provided {@code value} object is allowed to be {@code null}, in this case {@code @@ -106,17 +104,16 @@ public interface ChronicleMap extends ConcurrentMap, * no mapping for the key * @see #get(Object) * @see #acquireUsing(Object, Object) - * @see ChronicleMapBuilder#valueMarshaller(BytesMarshaller) + * @see ChronicleMapBuilder#valueMarshallers(SizedReader, SizedWriter) */ V getUsing(K key, V usingValue); /** * Acquire a value for a key, creating if absent. * - *

If the specified key is absent in the map, {@linkplain ChronicleMapBuilder#defaultValue( - * Object) default value} is taken or {@linkplain ChronicleMapBuilder#defaultValueProvider( - * DefaultValueProvider) default value provider} is called. Then this object is put to this map - * for the specified key. + *

If the specified key is absent in the map, {@linkplain + * ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value provider} is + * called. Then this object is put to this map for the specified key. * *

Then, either if the key was initially absent in the map or already present, the value is * deserialized just as during {@link #getUsing(Object, Object) getUsing(key, usingValue)} call, @@ -133,9 +130,8 @@ public interface ChronicleMap extends ConcurrentMap, * }} * * - *

Where {@code defaultValue(key)} returns either {@linkplain ChronicleMapBuilder#defaultValue(Object) - * default value} or {@link ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) - * defaultValueProvider.} + *

Where {@code defaultValue(key)} returns {@link + * ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) defaultValueProvider}. * *

If the {@code ChronicleMap} is off-heap updatable, i. e. created via {@link * ChronicleMapBuilder} builder (values are {@link Byteable}), there is one more option of what diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index 7e84c5436..60e4d5201 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -16,6 +16,8 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.core.OS; import net.openhft.chronicle.hash.ChronicleHashBuilder; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; @@ -24,25 +26,11 @@ import net.openhft.chronicle.hash.impl.stage.entry.ChecksumStrategy; import net.openhft.chronicle.hash.impl.util.math.PoissonDistribution; import net.openhft.chronicle.hash.replication.*; import net.openhft.chronicle.hash.serialization.*; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter; -import net.openhft.chronicle.hash.serialization.internal.MetaProvider; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; import net.openhft.chronicle.map.replication.MapRemoteOperations; import net.openhft.chronicle.set.ChronicleSetBuilder; -import net.openhft.lang.Maths; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.BytesStore; -import net.openhft.lang.io.DirectStore; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.io.serialization.*; -import net.openhft.lang.io.serialization.impl.AllocateInstanceObjectFactory; -import net.openhft.lang.io.serialization.impl.NewInstanceObjectFactory; -import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.thread.NamedThreadFactory; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; +import net.openhft.chronicle.threads.NamedThreadFactory; +import net.openhft.chronicle.values.ValueModel; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,13 +45,14 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static java.lang.Double.isNaN; -import static java.lang.Math.ceil; import static java.lang.Math.round; +import static net.openhft.chronicle.bytes.NativeBytesStore.lazyNativeBytesStoreWithFixedCapacity; +import static net.openhft.chronicle.core.Maths.*; import static net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable.*; import static net.openhft.chronicle.hash.impl.util.Objects.builderEquals; import static net.openhft.chronicle.map.DefaultSpi.mapEntryOperations; import static net.openhft.chronicle.map.DefaultSpi.mapRemoteOperations; -import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType; +import static net.openhft.chronicle.map.VanillaChronicleMap.alignAddr; /** * {@code ChronicleMapBuilder} manages {@link ChronicleMap} configurations; could be used as a @@ -96,9 +85,8 @@ import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType; * #entries(long)} method documentation for more information on this. * *

If you key or value type is not constantly sized and known to {@code ChronicleHashBuilder}, i. - * e. it is not a boxed primitive, data value generated interface, {@link Byteable}, etc. (see the - * complete list TODO insert the link to the complete list), you must provide the {@code - * ChronicleHashBuilder} with some information about you keys or values: if they are + * e. it is not a boxed primitive, value interface, or {@link Byteable}, you must provide the + * {@code ChronicleHashBuilder} with some information about you keys or values: if they are * constantly-sized, call {@link #constantKeySizeBySample(Object)}, otherwise {@link * ChronicleHashBuilder#averageKeySize(double)} method, accordingly for values. * @@ -111,8 +99,11 @@ public final class ChronicleMapBuilder implements ChronicleHashBuilder, ChronicleMapBuilder> { static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 127; - private static final int DEFAULT_KEY_OR_VALUE_SIZE = 120; private static final long DEFAULT_ENTRIES = 1 << 20; + + private static final int UNDEFINED_ALIGNMENT_CONFIG = -1; + private static final int NO_ALIGNMENT = 1; + /** * If want to increase this number, note {@link OldDeletedEntriesCleanup} uses array to store * all segment indexes -- so it could be current JVM max array size, not Integer.MAX_VALUE @@ -125,15 +116,11 @@ public final class ChronicleMapBuilder implements private static final Logger LOG = LoggerFactory.getLogger(ChronicleMapBuilder.class.getName()); - private static final StringBuilder EMPTY_STRING_BUILDER = new StringBuilder(); - private static final double UNDEFINED_DOUBLE_CONFIG = Double.NaN; private static final int XML_SERIALIZATION = 1; private static final int BINARY_SERIALIZATION = 2; - static final long RUNTIME_PAGE_SIZE = (long) NativeBytes.UNSAFE.pageSize(); - private static boolean isDefined(double config) { return !isNaN(config); } @@ -162,10 +149,8 @@ public final class ChronicleMapBuilder implements private int actualChunkSize = 0; private int worstAlignment = -1; private int maxChunksPerEntry = -1; - private Alignment alignment = null; + private int alignment = UNDEFINED_ALIGNMENT_CONFIG; private long entries = -1L; - private long lockTimeOut = 20000L; - private TimeUnit lockTimeOutUnit = TimeUnit.MILLISECONDS; private double maxBloatFactor = 1.0; private boolean allowSegmentTiering = true; private double nonTieredSegmentsPercentile = 0.99999; @@ -189,10 +174,6 @@ public final class ChronicleMapBuilder implements TimeUnit cleanupTimeoutUnit = TimeUnit.MINUTES; private boolean cleanupRemovedEntries = true; - private BytesMarshallerFactory bytesMarshallerFactory; - private ObjectSerializer objectSerializer; - private V defaultValue = null; - private ConstantValueProvider constantValueProvider = null; DefaultValueProvider defaultValueProvider = DefaultSpi.defaultValueProvider(); private SingleChronicleHashReplication singleHashReplication = null; @@ -208,13 +189,8 @@ public final class ChronicleMapBuilder implements private boolean persisted; ChronicleMapBuilder(Class keyClass, Class valueClass) { - keyBuilder = new SerializationBuilder<>(keyClass, SerializationBuilder.Role.KEY); - valueBuilder = new SerializationBuilder<>(valueClass, SerializationBuilder.Role.VALUE); - - if (CharSequence.class == valueClass) - defaultValue = (V) ""; - if (StringBuilder.class == valueClass) - defaultValue = (V) EMPTY_STRING_BUILDER; + keyBuilder = new SerializationBuilder<>(keyClass); + valueBuilder = new SerializationBuilder<>(valueClass); } /** @@ -245,10 +221,6 @@ public final class ChronicleMapBuilder implements } } - private static long divideUpper(long dividend, long divisor) { - return ((dividend - 1L) / divisor) + 1L; - } - private static String pretty(int value) { return value > 0 ? value + "" : "not configured"; } @@ -339,7 +311,6 @@ public final class ChronicleMapBuilder implements * Map gitCommitMessagesByHash = * ChronicleMapBuilder.of(byte[].class, String.class) * .constantKeySizeBySample(new byte[20]) - * .immutableKeys() * .create();} * * @see #averageKeySize(double) @@ -401,7 +372,7 @@ public final class ChronicleMapBuilder implements /** * Configures the average number of bytes, taken by serialized form of values, put into maps, * created by this builder, by serializing the given {@code averageValue} using the configured - * {@link #valueMarshallers(BytesWriter, BytesReader) value marshallers}. In some cases, {@link + * {@link #valueMarshallers(SizedReader, SizedWriter) value marshallers}. In some cases, {@link * #averageValueSize(double)} might be easier to use, than constructing the "average value". * If value size is always the same, call {@link #constantValueSizeBySample(Object)} method * instead of this one. @@ -449,7 +420,7 @@ public final class ChronicleMapBuilder implements private static void checkSizeIsNotStaticallyKnown(SerializationBuilder builder) { if (builder.sizeIsStaticallyKnown) - throw new IllegalStateException("Size of type " + builder.eClass + + throw new IllegalStateException("Size of type " + builder.tClass + " is statically known and shouldn't be specified manually"); } @@ -491,9 +462,8 @@ public final class ChronicleMapBuilder implements if (isDefined(configuredSize)) return configuredSize; if (builder.constantSizeMarshaller()) - return builder.pseudoReadConstantSize(); + return builder.constantSize(); if (average != null) { - builder.maxSize(DEFAULT_KEY_OR_VALUE_SIZE); return builder.serializationSize(average); } return Double.NaN; @@ -503,17 +473,16 @@ public final class ChronicleMapBuilder implements * {@inheritDoc} * * @throws IllegalStateException is sizes of both keys and values of maps created by this - * builder are constant, hence chunk size shouldn't be configured - * by user - * @see #entryAndValueAlignment(Alignment) + * builder are constant, hence chunk size shouldn't be configured by user + * @see #entryAndValueOffsetAlignment(int) * @see #entries(long) * @see #maxChunksPerEntry(int) */ @Override public ChronicleMapBuilder actualChunkSize(int actualChunkSize) { if (constantlySizedEntries()) { - throw new IllegalStateException("Sizes of key type: " + keyBuilder.eClass + " and " + - "value type: " + valueBuilder.eClass + " are both constant, " + + throw new IllegalStateException("Sizes of key type: " + keyBuilder.tClass + " and " + + "value type: " + valueBuilder.tClass + " are both constant, " + "so chunk size shouldn't be specified manually"); } if (actualChunkSize <= 0) @@ -539,22 +508,22 @@ public final class ChronicleMapBuilder implements private EntrySizeInfo entrySizeInfo() { double size = 0; double keySize = averageKeySize(); - size += averageSizeEncodingSize(keyBuilder, keySize); + size += averageSizeStoringLength(keyBuilder, keySize); size += keySize; if (replicated) size += ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES; if (checksumEntries()) size += ChecksumStrategy.CHECKSUM_STORED_BYTES; double valueSize = averageValueSize(); - size += averageSizeEncodingSize(valueBuilder, valueSize); - Alignment alignment = valueAlignment(); + size += averageSizeStoringLength(valueBuilder, valueSize); + int alignment = valueAlignment(); int worstAlignment; if (worstAlignmentComputationRequiresValueSize(alignment)) { long constantSizeBeforeAlignment = round(size); if (constantlySizedValues()) { // see segmentEntrySpaceInnerOffset() long totalDataSize = constantSizeBeforeAlignment + constantValueSize(); - worstAlignment = (int) (alignment.alignAddr(totalDataSize) - totalDataSize); + worstAlignment = (int) (alignAddr(totalDataSize, alignment) - totalDataSize); } else { determineAlignment: if (actualChunkSize > 0) { @@ -582,13 +551,13 @@ public final class ChronicleMapBuilder implements return new EntrySizeInfo(size, worstAlignment); } - private boolean worstAlignmentComputationRequiresValueSize(Alignment alignment) { - return alignment != Alignment.NO_ALIGNMENT && - constantlySizedKeys() && valueBuilder.constantSizeEncodingSizeMarshaller(); + private boolean worstAlignmentComputationRequiresValueSize(int alignment) { + return alignment != NO_ALIGNMENT && + constantlySizedKeys() && valueBuilder.constantStoringLengthSizeMarshaller(); } - private int worstAlignmentWithoutValueSize(Alignment alignment) { - return alignment.alignment() - 1; + private int worstAlignmentWithoutValueSize(int alignment) { + return alignment - 1; } int segmentEntrySpaceInnerOffset() { @@ -596,37 +565,36 @@ public final class ChronicleMapBuilder implements // to be always the same, we should _misalign_ the first chunk. if (!constantlySizedEntries()) return 0; - return (int) (constantValueSize() % valueAlignment().alignment()); + return (int) (constantValueSize() % valueAlignment()); } private long constantValueSize() { - return valueBuilder.pseudoReadConstantSize(); + return valueBuilder.constantSize(); } boolean constantlySizedKeys() { return keyBuilder.constantSizeMarshaller() || sampleKey != null; } - private static double averageSizeEncodingSize( + private static double averageSizeStoringLength( SerializationBuilder builder, double averageSize) { SizeMarshaller sizeMarshaller = builder.sizeMarshaller(); if (averageSize == round(averageSize)) - return sizeMarshaller.sizeEncodingSize(round(averageSize)); + return sizeMarshaller.storingLength(round(averageSize)); long lower = (long) averageSize; long upper = lower + 1; - int lowerEncodingSize = sizeMarshaller.sizeEncodingSize(lower); - int upperEncodingSize = sizeMarshaller.sizeEncodingSize(upper); - if (lowerEncodingSize == upperEncodingSize) - return lowerEncodingSize; + int lowerStoringLength = sizeMarshaller.storingLength(lower); + int upperStoringLength = sizeMarshaller.storingLength(upper); + if (lowerStoringLength == upperStoringLength) + return lowerStoringLength; return lower * (upper - averageSize) + upper * (averageSize - lower); } private int worstAlignmentAssumingChunkSize( long constantSizeBeforeAlignment, int chunkSize) { - Alignment valueAlignment = valueAlignment(); - long firstAlignment = valueAlignment.alignAddr(constantSizeBeforeAlignment) - + int alignment = valueAlignment(); + long firstAlignment = alignAddr(constantSizeBeforeAlignment, alignment) - constantSizeBeforeAlignment; - int alignment = valueAlignment.alignment(); int gcdOfAlignmentAndChunkSize = greatestCommonDivisor(alignment, chunkSize); if (gcdOfAlignmentAndChunkSize == alignment) return (int) firstAlignment; @@ -641,7 +609,7 @@ public final class ChronicleMapBuilder implements int worstAlignment() { if (worstAlignment >= 0) return worstAlignment; - Alignment alignment = valueAlignment(); + int alignment = valueAlignment(); if (!worstAlignmentComputationRequiresValueSize(alignment)) return worstAlignment = worstAlignmentWithoutValueSize(alignment); return worstAlignment = entrySizeInfo().worstAlignment; @@ -716,47 +684,47 @@ public final class ChronicleMapBuilder implements } /** - * Configures alignment strategy of address in memory of entries and independently of address in - * memory of values within entries in ChronicleMaps, created by this builder. + * Configures alignment of address in memory of entries and independently of address in memory + * of values within entries ((i. e. final addresses in native memory are multiples of the given + * alignment) for ChronicleMaps, created by this builder. * *

Useful when values of the map are updated intensively, particularly fields with volatile * access, because it doesn't work well if the value crosses cache lines. Also, on some * (nowadays rare) architectures any misaligned memory access is more expensive than aligned. * - *

If values couldn't reference off-heap memory (i. e. it is not {@link Byteable} or "data - * value generated"), alignment configuration makes no sense and forbidden. + *

If values couldn't reference off-heap memory (i. e. it is not {@link Byteable} or a value + * interface), alignment configuration makes no sense. * - *

Default is {@link Alignment#NO_ALIGNMENT} if values couldn't reference off-heap memory, - * otherwise chosen heuristically (configure explicitly for being sure and to compare - * performance in your case). + *

Default is {@link ValueModel#recommendedOffsetAlignment()} if the value type is a value + * interface, otherwise 1 (that is effectively no alignment) or chosen heuristically (configure + * explicitly for being sure and to compare performance in your case). * * @param alignment the new alignment of the maps constructed by this builder * @return this {@code ChronicleMapOnHeapUpdatableBuilder} back * @throws IllegalStateException if values of maps, created by this builder, couldn't reference * off-heap memory */ - public ChronicleMapBuilder entryAndValueAlignment(Alignment alignment) { + public ChronicleMapBuilder entryAndValueOffsetAlignment(int alignment) { + if (alignment <= 0) { + throw new IllegalArgumentException("Alignment should be positive integer, " + + alignment + " given"); + } + if (!isPowerOf2(alignment)) { + throw new IllegalArgumentException("Alignment should be a power of 2, " + alignment + + " given"); + } this.alignment = alignment; - checkAlignmentOnlyIfValuesPossiblyReferenceOffHeap(); return this; } - private void checkAlignmentOnlyIfValuesPossiblyReferenceOffHeap() { - if (!valueBuilder.possibleOffHeapReferences() && - (alignment == Alignment.OF_4_BYTES || alignment == Alignment.OF_8_BYTES)) - throw new IllegalStateException("Entry and value alignment should be configured only " + - "if values might point to off-heap memory"); - } - - Alignment valueAlignment() { - if (alignment != null) + int valueAlignment() { + if (alignment != UNDEFINED_ALIGNMENT_CONFIG) return alignment; - Class firstPrimitiveFieldType = firstPrimitiveFieldType(valueBuilder.eClass); - if (firstPrimitiveFieldType == long.class || firstPrimitiveFieldType == double.class) - return Alignment.OF_8_BYTES; - if (firstPrimitiveFieldType == int.class || firstPrimitiveFieldType == float.class) - return Alignment.OF_4_BYTES; - return Alignment.NO_ALIGNMENT; + try { + return ValueModel.acquire(valueBuilder.tClass).recommendedOffsetAlignment(); + } catch (Exception e) { + return NO_ALIGNMENT; + } } @Override @@ -861,7 +829,7 @@ public final class ChronicleMapBuilder implements } private int estimateSegments() { - return (int) Math.min(Maths.nextPower2(entries() / 32, 1), estimateSegmentsBasedOnSize()); + return (int) Math.min(nextPower2(entries() / 32, 1), estimateSegmentsBasedOnSize()); } //TODO review because this heuristic doesn't seem to perform well @@ -956,7 +924,7 @@ public final class ChronicleMapBuilder implements // This condition should likely filter cases when we target very small hash lookup // size + entry size is small. // * 5 => segment will lose not more than 20% of memory, 10% on average - if (entrySpaceSize < RUNTIME_PAGE_SIZE * 5L) + if (entrySpaceSize < OS.pageSize() * 5L) return -1; return trySegments(entriesPerSegment, MAX_SEGMENTS); } @@ -981,7 +949,7 @@ public final class ChronicleMapBuilder implements private long trySegments(long entriesPerSegment, int maxSegments) { long segments = segmentsGivenEntriesPerSegmentFixed(entriesPerSegment); - segments = Maths.nextPower2(Math.max(segments, minSegments()), 1L); + segments = nextPower2(Math.max(segments, minSegments()), 1L); return segments <= maxSegments ? segments : -segments; } @@ -1122,15 +1090,11 @@ public final class ChronicleMapBuilder implements ", actualChunkSize=" + pretty(actualChunkSize) + ", valueAlignment=" + valueAlignment() + ", entries=" + entries() + - ", lockTimeOut=" + lockTimeOut + " " + lockTimeOutUnit + ", putReturnsNull=" + putReturnsNull() + ", removeReturnsNull=" + removeReturnsNull() + ", timeProvider=" + timeProvider() + - ", bytesMarshallerFactory=" + pretty(bytesMarshallerFactory) + - ", objectSerializer=" + pretty(objectSerializer) + ", keyBuilder=" + keyBuilder + ", valueBuilder=" + valueBuilder + - ", defaultValue=" + defaultValue + '}'; } @@ -1173,82 +1137,48 @@ public final class ChronicleMapBuilder implements return timeProvider; } - BytesMarshallerFactory bytesMarshallerFactory() { - return bytesMarshallerFactory == null ? - bytesMarshallerFactory = new VanillaBytesMarshallerFactory() : - bytesMarshallerFactory; - } - @Override - public ChronicleMapBuilder bytesMarshallerFactory( - BytesMarshallerFactory bytesMarshallerFactory) { - this.bytesMarshallerFactory = bytesMarshallerFactory; - return this; - } - - ObjectSerializer acquireObjectSerializer(ObjectSerializer defaultSerializer) { - return objectSerializer == null ? - BytesMarshallableSerializer.create(bytesMarshallerFactory(), defaultSerializer) : - objectSerializer; - } - - /** - * {@inheritDoc} - * Example:

{@code Map map =
-     *     ChronicleMapBuilder.of(Key.class, Value.class)
-     *     .entries(1_000_000)
-     *     .averageKeySize(50).averageValueSize(200)
-     *     // this class hasn't implemented yet, just for example
-     *     .objectSerializer(new KryoObjectSerializer())
-     *     .create();}
- * This serializer is used to serialize both keys and values, if they both require this: - * loosely typed, nullable, and custom {@linkplain #keyMarshaller(BytesMarshaller) key} and - * {@linkplain #valueMarshaller(BytesMarshaller) value} marshallers are not configured. - */ - @Override - public ChronicleMapBuilder objectSerializer(ObjectSerializer objectSerializer) { - this.objectSerializer = objectSerializer; - return this; - } - - @Override - public ChronicleMapBuilder keyMarshaller( - @NotNull BytesMarshaller keyMarshaller) { - keyBuilder.marshaller(keyMarshaller); + public ChronicleMapBuilder keyReaderAndDataAccess( + SizedReader keyReader, @NotNull DataAccess keyDataAccess) { + keyBuilder.reader(keyReader); + keyBuilder.dataAccess(keyDataAccess); return this; } @Override public ChronicleMapBuilder keyMarshallers( - @NotNull BytesWriter keyWriter, @NotNull BytesReader keyReader) { - keyBuilder.writer(keyWriter); + @NotNull SizedReader keyReader, @NotNull SizedWriter keyWriter) { keyBuilder.reader(keyReader); + keyBuilder.writer(keyWriter); return this; } + @Override + public & SizedWriter> + ChronicleMapBuilder keyMarshaller(@NotNull M sizedMarshaller) { + return keyMarshallers(sizedMarshaller, sizedMarshaller); + } + + @Override + public ChronicleMapBuilder keyMarshallers( + @NotNull BytesReader keyReader, @NotNull BytesWriter keyWriter) { + keyBuilder.reader(keyReader); + keyBuilder.writer(keyWriter); + return this; + } + + @Override + public & BytesWriter> + ChronicleMapBuilder keyMarshaller(@NotNull M marshaller) { + return keyMarshallers(marshaller, marshaller); + } + @Override public ChronicleMapBuilder keySizeMarshaller(@NotNull SizeMarshaller keySizeMarshaller) { keyBuilder.sizeMarshaller(keySizeMarshaller); return this; } - /** - * @throws IllegalStateException {@inheritDoc} - * @see #valueDeserializationFactory(ObjectFactory) - */ - @Override - public ChronicleMapBuilder keyDeserializationFactory( - @NotNull ObjectFactory keyDeserializationFactory) { - keyBuilder.factory(keyDeserializationFactory); - return this; - } - - @Override - public ChronicleMapBuilder immutableKeys() { - keyBuilder.instancesAreMutable(false); - return this; - } - @Override public ChronicleMapBuilder aligned64BitMemoryOperationsAtomic( boolean aligned64BitMemoryOperationsAtomic) { @@ -1276,45 +1206,76 @@ public final class ChronicleMapBuilder implements } /** - * Configures the {@code BytesMarshaller} used to serialize/deserialize values to/from off-heap - * memory in maps, created by this builder. See the - * section about serialization in ChronicleMap manual for more information. + * Configures the {@code DataAccess} and {@code SizedReader} used to serialize and deserialize + * values to and from off-heap memory in maps, created by this builder. * - * @param valueMarshaller the marshaller used to serialize values + * @param valueReader the new bytes → value object reader strategy + * @param valueDataAccess the new strategy of accessing the values' bytes for writing * @return this builder back - * @see #valueMarshallers(BytesWriter, BytesReader) - * @see #objectSerializer(ObjectSerializer) - * @see #keyMarshaller(BytesMarshaller) + * @see #valueMarshallers(SizedReader, SizedWriter) + * @see ChronicleHashBuilder#keyReaderAndDataAccess(SizedReader, DataAccess) */ - public ChronicleMapBuilder valueMarshaller( - @NotNull BytesMarshaller valueMarshaller) { - valueBuilder.marshaller(valueMarshaller); + public ChronicleMapBuilder valueReaderAndDataAccess( + SizedReader valueReader, @NotNull DataAccess valueDataAccess) { + valueBuilder.reader(valueReader); + valueBuilder.dataAccess(valueDataAccess); return this; } /** * Configures the marshallers, used to serialize/deserialize values to/from off-heap memory in - * maps, created by this builder. See the - * section about serialization in ChronicleMap manual for more information. - * Configuring marshalling this way results to a little bit more compact in-memory layout of - * the map, comparing to a single interface configuration: {@link #valueMarshaller( - *BytesMarshaller)}. Passing {@link BytesInterop} instead of plain {@link BytesWriter} - * is, of cause, possible, but currently pointless for values. + * maps, created by this builder. * - * @param valueWriter the new value object → {@link Bytes} writer (interop) strategy - * @param valueReader the new {@link Bytes} → value object reader strategy + * @param valueReader the new bytes → value object reader strategy + * @param valueWriter the new value object → bytes writer strategy * @return this builder back - * @see #valueMarshaller(BytesMarshaller) + * @see #valueReaderAndDataAccess(SizedReader, DataAccess) * @see #valueSizeMarshaller(SizeMarshaller) - * @see #keyMarshallers(BytesWriter, BytesReader) + * @see ChronicleHashBuilder#keyMarshallers(SizedReader, SizedWriter) */ public ChronicleMapBuilder valueMarshallers( - @NotNull BytesWriter valueWriter, @NotNull BytesReader valueReader) { - valueBuilder.writer(valueWriter); + @NotNull SizedReader valueReader, @NotNull SizedWriter valueWriter) { valueBuilder.reader(valueReader); + valueBuilder.writer(valueWriter); return this; } + /** + * Shortcut for {@link #valueMarshallers(SizedReader, SizedWriter) + * valueMarshallers(sizedMarshaller, sizedMarshaller)}. + */ + public & SizedWriter> + ChronicleMapBuilder valueMarshaller(@NotNull M sizedMarshaller) { + return valueMarshallers(sizedMarshaller, sizedMarshaller); + } + + /** + * Configures the marshallers, used to serialize/deserialize values to/from off-heap memory in + * maps, created by this builder. + * + * @param valueReader the new bytes → value object reader strategy + * @param valueWriter the new value object → bytes writer strategy + * @return this builder back + * @see #valueReaderAndDataAccess(SizedReader, DataAccess) + * @see #valueSizeMarshaller(SizeMarshaller) + * @see ChronicleHashBuilder#keyMarshallers(BytesReader, BytesWriter) + */ + public ChronicleMapBuilder valueMarshallers( + @NotNull BytesReader valueReader, @NotNull BytesWriter valueWriter) { + valueBuilder.reader(valueReader); + valueBuilder.writer(valueWriter); + return this; + } + + /** + * Shortcut for {@link #valueMarshallers(BytesReader, BytesWriter) + * valueMarshallers(marshaller, marshaller)}. + */ + public & BytesWriter> + ChronicleMapBuilder valueMarshaller(@NotNull M marshaller) { + return valueMarshallers(marshaller, marshaller); + } + /** * Configures the marshaller used to serialize actual value sizes to off-heap memory in maps, * created by this builder. @@ -1334,61 +1295,12 @@ public final class ChronicleMapBuilder implements return this; } - /** - * Configures factory which is used to create a new value instance, if value class is either - * {@link Byteable}, {@link BytesMarshallable} or {@link Externalizable} subclass, or value type - * is eligible for data value generation, or configured custom value reader is an instance of - * {@link DeserializationFactoryConfigurableBytesReader}, in maps, created by this builder. - * Default value deserialization factory is {@link NewInstanceObjectFactory}, which creates a - * new value instance using {@link Class#newInstance()} default constructor. You could provide - * an {@link AllocateInstanceObjectFactory}, which uses {@code Unsafe.allocateInstance(Class)} - * (you might want to do this for better performance or if you don't want to initialize fields), - * or a factory which calls a value class constructor with some arguments, or a factory which - * internally delegates to instance pool or {@link ThreadLocal}, to reduce allocations. - * - * @param valueDeserializationFactory the value factory used to produce instances to deserialize - * data in - * @return this builder back - * @throws IllegalStateException if it is not possible to apply deserialization factory to value - * deserializers, currently configured for this builder - * @see #keyDeserializationFactory(ObjectFactory) - */ - public ChronicleMapBuilder valueDeserializationFactory( - @NotNull ObjectFactory valueDeserializationFactory) { - valueBuilder.factory(valueDeserializationFactory); - return this; - } - - /** - * Specifies the value to be put for each key queried in {@link ChronicleMap#acquireUsing - * acquireUsing()} method, if the key is absent in the map, created by this builder. - * - *

This configuration overrides any previous {@link #defaultValueProvider( - * DefaultValueProvider)} configuration to this builder. - * - * @param defaultValue the default value to be put to the map for absent keys during {@code - * acquireUsing()} calls - * @return this builder object back - * @see #defaultValueProvider(DefaultValueProvider) - */ - public ChronicleMapBuilder defaultValue(V defaultValue) { - if (defaultValue == null) - throw new IllegalArgumentException("default ChronicleMap value couldn't be null"); - this.defaultValue = defaultValue; - this.constantValueProvider = null; - return this; - } - /** * Specifies the function to obtain a value for the key during {@link ChronicleMap#acquireUsing * acquireUsing()} calls, if the key is absent in the map, created by this builder. * - *

This configuration overrides any previous {@link #defaultValue(Object)} configuration - * to this builder. - * * @param defaultValueProvider the strategy to obtain a default value by the absent key * @return this builder object back - * @see #defaultValue(Object) */ public ChronicleMapBuilder defaultValueProvider( @NotNull DefaultValueProvider defaultValueProvider) { @@ -1397,62 +1309,6 @@ public final class ChronicleMapBuilder implements return this; } - /** - * Non-public because should be called only after {@link #preMapConstruction()} - */ - ConstantValueProvider constantValueProvider() { - if (constantValueProvider != null) - return constantValueProvider; - V defaultValue = this.defaultValue; - if (defaultValue == null) - defaultValue = zeroValue(); - if (defaultValue == null) - return null; - Object originalValueWriter = valueBuilder.interop(); - Provider writerProvider = Provider.of(originalValueWriter.getClass()); - ThreadLocalCopies copies = writerProvider.getCopies(null); - Object valueWriter = writerProvider.get(copies, originalValueWriter); - MetaProvider metaWriterProvider = valueBuilder.metaInteropProvider(); - copies = metaWriterProvider.getCopies(copies); - MetaBytesWriter metaValueWriter = metaWriterProvider.get(copies, - valueBuilder.metaInterop(), valueWriter, defaultValue, true); - return new ConstantValueProvider<>(defaultValue, metaValueWriter, valueWriter); - } - - private V zeroValue() { - if (Byteable.class.isAssignableFrom(valueBuilder.eClass)) { - try { - Object v = NativeBytes.UNSAFE.allocateInstance(valueBuilder.eClass); - Byteable defaultValue = (Byteable) v; - defaultValue.bytes(DirectStore.allocate(defaultValue.maxSize()).bytes(), 0); - return (V) v; - } catch (InstantiationException e) { - return null; - } - } else { - try { - return DataValueClasses.newDirectInstance(valueBuilder.eClass); - } catch (Exception e) { - if (valueBuilder.eClass == Long.class) { - return (V) (Long) 0L; - } else if (valueBuilder.eClass == Integer.class) { - return (V) (Integer) 0; - } else if (valueBuilder.eClass == Short.class) { - return (V) (Short) (short) 0; - } else if (valueBuilder.eClass == Character.class) { - return (V) (Character) (char) 0; - } else if (valueBuilder.eClass == Byte.class) { - return (V) (Byte) (byte) 0; - } else if (valueBuilder.eClass == Float.class) { - return (V) (Float) 0.0f; - } else if (valueBuilder.eClass == Double.class) { - return (V) (Double) 0.0; - } - return null; - } - } - } - @Override public ChronicleMapBuilder replication(SingleChronicleHashReplication replication) { this.singleHashReplication = replication; @@ -1526,8 +1382,8 @@ public final class ChronicleMapBuilder implements throw new IOException("Unknown map header serialization type: " + serialization); } - VanillaChronicleMap map = - (VanillaChronicleMap) m; + @SuppressWarnings("unchecked") + VanillaChronicleMap map = (VanillaChronicleMap) m; map.initTransientsFromBuilder(this); initTransientsFromReplication(map, singleHashReplication, channel); map.initBeforeMapping(fis.getChannel()); @@ -1561,7 +1417,7 @@ public final class ChronicleMapBuilder implements if (!file.exists()) throw new FileNotFoundException("Unable to create " + file); - VanillaChronicleMap map = newMap(singleHashReplication, channel); + VanillaChronicleMap map = newMap(singleHashReplication, channel); try (FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos)) { @@ -1578,7 +1434,7 @@ public final class ChronicleMapBuilder implements } private static void initTransientsFromReplication( - VanillaChronicleMap map, + VanillaChronicleMap map, SingleChronicleHashReplication singleHashReplication, ReplicationChannel channel) { if (map instanceof ReplicatedChronicleMap) { AbstractReplication replication; @@ -1595,7 +1451,7 @@ public final class ChronicleMapBuilder implements } private static boolean trySerializeHeaderViaXStream( - VanillaChronicleMap map, ObjectOutputStream oos) + VanillaChronicleMap map, ObjectOutputStream oos) throws IOException { Class xStreamClass; try { @@ -1637,13 +1493,14 @@ public final class ChronicleMapBuilder implements persisted = false; try { - VanillaChronicleMap map = newMap(singleHashReplication, channel); + VanillaChronicleMap map = newMap(singleHashReplication, channel); // TODO this method had been moved // if(OS.warnOnWindows(map.sizeInBytesWithoutTiers())){ // throw new IllegalStateException("Windows cannot support this configuration"); // } - BytesStore bytesStore = new DirectStore(JDKObjectSerializer.INSTANCE, - map.sizeInBytesWithoutTiers(), false); + + BytesStore bytesStore = + lazyNativeBytesStoreWithFixedCapacity(map.sizeInBytesWithoutTiers()); map.createMappedStoreAndSegments(bytesStore); return establishReplication(map, singleHashReplication, channel); } catch (IOException e) { @@ -1652,7 +1509,7 @@ public final class ChronicleMapBuilder implements } } - private VanillaChronicleMap newMap( + private VanillaChronicleMap newMap( SingleChronicleHashReplication singleHashReplication, ReplicationChannel channel) throws IOException { preMapConstruction(); @@ -1674,30 +1531,14 @@ public final class ChronicleMapBuilder implements keyBuilder, averageKeySize, averageKey, sampleKey, "Key"); averageValueSize = preMapConstruction( valueBuilder, averageValueSize, averageValue, sampleValue, "Value"); - if (sampleKey == null) - keyBuilder.maxSize(bufferSize(keyBuilder, averageSizeIfDefined(averageKeySize))); - if (sampleValue == null) - valueBuilder.maxSize(bufferSize(valueBuilder, averageSizeIfDefined(averageValueSize))); stateChecks(); } - private double averageSizeIfDefined(double averageKeyOrValueSize) { - if (isDefined(averageKeyOrValueSize)) - return averageKeyOrValueSize; - assert actualChunksPerSegment > 0 && entriesPerSegment > 0 : "average key or value size " + - "could be not defined here, only if allLowLevelConfigurationsAreManual() " + - "returns true in preMapConstruction()"; - return actualChunksPerSegment * 1.0 / entriesPerSegment * actualChunkSize; - } - private double preMapConstruction( SerializationBuilder builder, double configuredAverageSize, E average, E sample, String dim) { - builder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE)); if (sample != null) { - builder.maxSize(DEFAULT_KEY_OR_VALUE_SIZE); - builder.constantSizeBySample(sample); - return builder.maxSize(); + return builder.constantSizeBySample(sample); } else { double result = averageKeyOrValueSize(configuredAverageSize, builder, average); if (!isNaN(result) || allLowLevelConfigurationsAreManual()) { @@ -1712,7 +1553,6 @@ public final class ChronicleMapBuilder implements } private void stateChecks() { - checkAlignmentOnlyIfValuesPossiblyReferenceOffHeap(); checkActualChunksPerSegmentIsConfiguredOnlyIfOtherLowLevelConfigsAreManual(); checkActualChunksPerSegmentGreaterOrEqualToEntries(); } @@ -1723,7 +1563,7 @@ public final class ChronicleMapBuilder implements } private ChronicleMap establishReplication( - VanillaChronicleMap map, + VanillaChronicleMap map, SingleChronicleHashReplication singleHashReplication, ReplicationChannel channel) throws IOException { if (map instanceof ReplicatedChronicleMap) { @@ -1737,9 +1577,9 @@ public final class ChronicleMapBuilder implements List replicators = new ArrayList<>(2); if (singleHashReplication != null) { if (singleHashReplication.tcpTransportAndNetwork() != null) - replicators.add(Replicators.tcp(singleHashReplication)); + replicators.add(Replicator.tcp(singleHashReplication)); if (singleHashReplication.udpTransport() != null) - replicators.add(Replicators.udp(singleHashReplication.udpTransport())); + replicators.add(Replicator.udp(singleHashReplication.udpTransport())); } else if (channel != null) { ReplicationHub hub = channel.hub(); @@ -1756,7 +1596,7 @@ public final class ChronicleMapBuilder implements Closeable token = replicator.applyTo(this, result, result, (ReplicatedChronicleMap)map); if (replicators.size() == 1 && token.getClass() == UdpReplicator.class) { - LOG.warn(Replicators.ONLY_UDP_WARN_MESSAGE); + LOG.warn(Replicator.ONLY_UDP_WARN_MESSAGE); } result.addCloseable(token); } @@ -1785,23 +1625,6 @@ public final class ChronicleMapBuilder implements }); } - private long bufferSize(SerializationBuilder builder, double averageSize) { - if (builder.constantSizeMarshaller()) - return round(ceil(averageSize)); - - int maxChunksPerEntry = maxChunksPerEntry(); - // if maxChunksPerEntry is Integer.MAX_VALUE, we, of cause, - // are not going to allocate such big buffers - int limitedMaxChunksPerEntry = Math.min(64, maxChunksPerEntry); - long limitedMaxEntrySize = limitedMaxChunksPerEntry * chunkSize(); - - // if expected map size is about 1000, seems rather wasteful to allocate - // key and value serialization buffers each x64 of expected entry size.. - long limitFactor = Math.max(2L, entries() >> 10); - - return Math.min(round(ceil(limitFactor * averageSize)), limitedMaxEntrySize); - } - /** * Inject your SPI code around basic {@code ChronicleMap}'s operations with entries: * removing entries, replacing the entries' value and inserting the new entry. diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java index dab56be6f..93daacabb 100644 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilderPrivateAPI.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; class ChronicleMapBuilderPrivateAPI implements ChronicleHashBuilderPrivateAPI { diff --git a/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java b/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java deleted file mode 100644 index 9a4845bfb..000000000 --- a/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.chronicle.hash.Data; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; -import net.openhft.lang.io.ByteBufferBytes; - -import java.io.Serializable; -import java.nio.ByteBuffer; - -public final class ConstantValueProvider implements Serializable { - private static final long serialVersionUID = 0L; - - private transient V value; - private final int size; - private final byte[] serializedValueBytes; - - ConstantValueProvider(V value, MetaBytesWriter metaValueWriter, W valueWriter) { - this.value = value; - size = (int) metaValueWriter.size(valueWriter, value); - serializedValueBytes = new byte[size]; - ByteBufferBytes bytes = new ByteBufferBytes(ByteBuffer.wrap(serializedValueBytes)); - metaValueWriter.write(valueWriter, bytes, value); - } - - boolean wasDeserialized() { - return value == null; - } - - void initTransients(BytesReader reader) { - value = reader.read(new ByteBufferBytes(ByteBuffer.wrap(serializedValueBytes)), size); - } - - public V defaultValue() { - return value; - } -} diff --git a/src/main/java/net/openhft/chronicle/map/DefaultSpi.java b/src/main/java/net/openhft/chronicle/map/DefaultSpi.java index dc416b871..f9f87005c 100644 --- a/src/main/java/net/openhft/chronicle/map/DefaultSpi.java +++ b/src/main/java/net/openhft/chronicle/map/DefaultSpi.java @@ -16,7 +16,9 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.map.replication.MapRemoteOperations; +import org.jetbrains.annotations.NotNull; final class DefaultSpi implements MapMethods, MapEntryOperations, MapRemoteOperations, DefaultValueProvider { @@ -36,4 +38,9 @@ final class DefaultSpi implements MapMethods, MapEntryOperations, MapRemoteOpera static DefaultValueProvider defaultValueProvider() { return DEFAULT_SPI; } + + @Override + public Data defaultValue(@NotNull MapAbsentEntry absentEntry) { + return absentEntry.defaultValue(); + } } diff --git a/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java b/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java index 2c23d57cb..cea2b1d2e 100644 --- a/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java +++ b/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java @@ -25,8 +25,8 @@ import org.jetbrains.annotations.NotNull; * * @param map key class * @param map value class - * @see ChronicleMapBuilder#defaultValue(Object) */ +@FunctionalInterface public interface DefaultValueProvider { /** @@ -34,9 +34,7 @@ public interface DefaultValueProvider { * {@code absentEntry} context. This is primarily used in {@link ChronicleMap#acquireUsing} * operation implementation, i. e. {@link MapMethods#acquireUsing}. * - * @implNote simply delegates to {@link MapAbsentEntry#defaultValue()}. + * The default implementation simply delegates to {@link MapAbsentEntry#defaultValue()}. */ - default Data defaultValue(@NotNull MapAbsentEntry absentEntry) { - return absentEntry.defaultValue(); - } + Data defaultValue(@NotNull MapAbsentEntry absentEntry); } diff --git a/src/main/java/net/openhft/chronicle/map/MapBuilder.java b/src/main/java/net/openhft/chronicle/map/MapBuilder.java deleted file mode 100644 index c4f3321f5..000000000 --- a/src/main/java/net/openhft/chronicle/map/MapBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 java.util.HashMap; -import java.util.Map; - -/** - * Common configurations of {@link ChronicleMapBuilder}. - * - * @param concrete builder class - */ -public interface MapBuilder> { - - - C putReturnsNull(boolean putReturnsNull); - - C removeReturnsNull(boolean removeReturnsNull); -} diff --git a/src/main/java/net/openhft/chronicle/map/NodeDiscovery.java b/src/main/java/net/openhft/chronicle/map/NodeDiscovery.java deleted file mode 100644 index ef3876d57..000000000 --- a/src/main/java/net/openhft/chronicle/map/NodeDiscovery.java +++ /dev/null @@ -1,1096 +0,0 @@ -/* - * 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.chronicle.hash.replication.RemoteNodeValidator; -import net.openhft.chronicle.hash.replication.ReplicationHub; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.hash.replication.UdpTransportConfig; -import net.openhft.lang.collection.ATSDirectBitSet; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.channels.DatagramChannel; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static java.nio.ByteBuffer.allocateDirect; -import static java.util.concurrent.TimeUnit.SECONDS; -import static net.openhft.chronicle.map.ConcurrentExpiryMap.getDefaultAddress; -import static net.openhft.chronicle.map.DiscoveryNodeBytesMarshallable.ProposedNodes; -import static net.openhft.chronicle.map.NodeDiscoveryBroadcaster.BOOTSTRAP_BYTES; -import static net.openhft.chronicle.map.NodeDiscoveryBroadcaster.LOG; - -/** - * @author Rob Austin. - * - * This code is in alpha, and still has to undergo refactoring - */ -class NodeDiscovery { - - public static final int DEFAULT_UDP_BROADCAST_PORT = 8129; - public static final short DEFAULT_TCP_PORT = (short) 8123; - public static final int SERIALIZED_ENTRY_SIZE = 1024; - - private final AddressAndPort ourAddressAndPort; - private final UdpTransportConfig udpConfig; - - public static final InetAddress IP_MULIT_CAST_GROUP; - - static { - InetAddress mask = null; - try { - mask = Inet4Address.getByName("224.0.8.0"); - } catch (Exception e) { - mask = null; - } - IP_MULIT_CAST_GROUP = mask; - } - - private final DiscoveryNodeBytesMarshallable discoveryNodeBytesMarshallable; - private final AtomicReference nodeDiscoveryEventListenerAtomicReference = - new AtomicReference(); - - private KnownNodes knownNodes; - - public NodeDiscovery() throws IOException { - this((short) DEFAULT_UDP_BROADCAST_PORT, DEFAULT_TCP_PORT, getDefaultAddress(), IP_MULIT_CAST_GROUP); - } - - public NodeDiscovery(short udpBroadcastPort, - short tcpPort, - @NotNull InetAddress tcpAddress, - @NotNull InetAddress udpMultiCastGroup) throws IOException { - this.ourAddressAndPort = new AddressAndPort(tcpAddress.getAddress(), tcpPort); - this.udpConfig = UdpTransportConfig.multiCast(udpMultiCastGroup, udpBroadcastPort, - ConcurrentExpiryMap.defaultNetworkInterface()); - knownNodes = new KnownNodes(); - - discoveryNodeBytesMarshallable = new DiscoveryNodeBytesMarshallable - (knownNodes, nodeDiscoveryEventListenerAtomicReference, ourAddressAndPort); - - final NodeDiscoveryBroadcaster nodeDiscoveryBroadcaster - = new NodeDiscoveryBroadcaster(udpConfig, SERIALIZED_ENTRY_SIZE, discoveryNodeBytesMarshallable); - - discoveryNodeBytesMarshallable.setModificationNotifier(nodeDiscoveryBroadcaster); - } - - public synchronized ReplicationHubFindByName mapByName() throws - IOException, InterruptedException { - - final AtomicInteger ourProposedIdentifier = new AtomicInteger(); - final AtomicBoolean useAnotherIdentifier = new AtomicBoolean(); - - final Set knownHostPorts = new ConcurrentSkipListSet(); - final DirectBitSet knownAndProposedIdentifiers = new ATSDirectBitSet(new ByteBufferBytes(ByteBuffer.allocate - (128 / 8))); - - final AtomicReference countDownLatch - = new AtomicReference(new CountDownLatch(1)); - - final NodeDiscoveryEventListener nodeDiscoveryEventListener = new NodeDiscoveryEventListener() { - @Override - public void onRemoteNodeEvent(@NotNull final KnownNodes remoteNodes, - @NotNull final ConcurrentExpiryMap proposedIdentifiersWithHost) { - LOG.info("onRemoteNodeEvent " + remoteNodes + ", proposedIdentifiersWithHost=" + proposedIdentifiersWithHost); - - knownHostPorts.addAll(remoteNodes.addressAndPorts()); - - orBitSets(remoteNodes.identifiers(), knownAndProposedIdentifiers); - - for (ProposedNodes proposedIdentifierWithHost : - proposedIdentifiersWithHost.values()) { - if (!proposedIdentifierWithHost.addressAndPort().equals(ourAddressAndPort)) { - int proposedIdentifier = proposedIdentifierWithHost.identifier(); - if (proposedIdentifier != -1) { - knownAndProposedIdentifiers.set(proposedIdentifier, true); - } - - knownHostPorts.add(proposedIdentifierWithHost.addressAndPort()); - - if (proposedIdentifier == ourProposedIdentifier.get()) - useAnotherIdentifier.set(true); - } - } - countDownLatch.get().countDown(); - } - }; - - nodeDiscoveryEventListenerAtomicReference.set(nodeDiscoveryEventListener); - - final ProposedNodes ourHostPort = new - ProposedNodes(ourAddressAndPort, (byte) -1); - - // to start with we will send a bootstrap that just contains our hostname without and identifier - - for (int i = 0; i < 10; i++) { - discoveryNodeBytesMarshallable.sendBootStrap(ourHostPort); - - // once the count down latch is trigger we know we go something back from one of the nodes - if (countDownLatch.get().await(i * 20, TimeUnit.MILLISECONDS)) - break; - } - - // we should now get back some identifiers - // the identifiers will come back to the callback on the nio thread, the update arrives at the - // onRemoteNodeEvent - - Thread.sleep(1000); - - byte identifier; - - // now we are going to propose an identifier - boolean isFistTime = true; - - OUTER: - for (; ; ) { - useAnotherIdentifier.set(false); - identifier = proposeRandomUnusedIdentifier(knownAndProposedIdentifiers, isFistTime); - ourProposedIdentifier.set(identifier); - LOG.info("proposing to use identifier=" + identifier); - - isFistTime = false; - - final ProposedNodes proposedNodes = new - ProposedNodes(ourAddressAndPort, identifier); - - Thread.sleep(1000); - - countDownLatch.set(new CountDownLatch(1)); - - for (int i = 0; i < 20; i++) { - discoveryNodeBytesMarshallable.sendBootStrap(proposedNodes); - - // once the count down latch is trigger we know we go something back from one of the nodes - if (countDownLatch.get().await(i * 20, TimeUnit.MILLISECONDS)) { - if (useAnotherIdentifier.get()) { - // given that another node host proposed the same identifier, we will choose a different one. - LOG.info("Another node is using identifier=" + identifier + ", " + - "going to have to select another one, we will wait 500ms before continuing"); - continue OUTER; - } else { - break OUTER; - } - } else { - LOG.debug("timed-out getting a response from the server so sending another boot-strap " + - "message"); - } - } - - LOG.info("looks like we are the only node in the grid, so going to use identifier=" + identifier); - - break; - } - - // we should make a local copy as this may change - - final RemoteNodeValidator remoteNodeValidator = new RemoteNodeValidator() { - private final ConcurrentMap identifiers = new ConcurrentHashMap(); - - @Override - public boolean validate(byte remoteIdentifier, SocketAddress remoteAddress) { - final SocketAddress lastKnownAddress = identifiers.putIfAbsent(remoteIdentifier, remoteAddress); - if (remoteAddress.equals(lastKnownAddress)) - return true; - knownNodes.identifiers().set(remoteIdentifier); - return lastKnownAddress == null; - } - }; - - // remove self - final HashSet knownHostPorts0 = new HashSet<>(knownHostPorts); - knownHostPorts0.remove(ourAddressAndPort); - - // add our identifier and host:port to the list of known identifiers - knownNodes.add(ourAddressAndPort, identifier); - - /* final TcpTransportAndNetworkConfig tcpConfig = TcpTransportAndNetworkConfig - .of(ourAddressAndPort.getPort(), - toInetSocketCollection(knownHostPorts0)); -*/ - - LOG.info("Using Remote identifier=" + identifier); - nodeDiscoveryEventListenerAtomicReference.set(null); - - TcpTransportAndNetworkConfig tcpConfig = TcpTransportAndNetworkConfig.of(8123, new - InetSocketAddress("192.168.1.253", 8123)); - - final ReplicationHub replicationHub = ReplicationHub.builder() - .tcpTransportAndNetwork(tcpConfig) - .remoteNodeValidator(remoteNodeValidator) - .createWithId(identifier); - - return new ReplicationHubFindByName(replicationHub); - } - - private static Collection toInetSocketCollection(Set source) - throws UnknownHostException { - - // make a safe copy - final HashSet addressAndPorts = new HashSet(source); - - if (addressAndPorts.isEmpty()) - return Collections.emptyList(); - - ArrayList addresses = - new ArrayList(addressAndPorts.size()); - - for (final AddressAndPort addressAndPort : addressAndPorts) { - addresses.add(new InetSocketAddress(InetAddress.getByAddress(addressAndPort.address()) - .getHostAddress(), addressAndPort.port())); - } - return addresses; - } - - /** - * bitwise OR's the two bit sets or put another way, merges the source bitset into the - * destination bitset and returns the destination - * - * @param source to or - * @param destination to or - * @return result. - */ - private DirectBitSet orBitSets(@NotNull final DirectBitSet source, - @NotNull final DirectBitSet destination) { - // merges the two bit-sets together - for (int i = (int) source.nextSetBit(0); i > 0; - i = (int) source.nextSetBit(i + 1)) { - try { - destination.set(i, true); - } catch (IndexOutOfBoundsException e) { - LOG.error("", e); - } - } - - return destination; - } - - static byte proposeRandomUnusedIdentifier(final DirectBitSet knownIdentifiers, - boolean isFirstTime) throws UnknownHostException { - byte possible; - - // the first time, rather than choosing a random number, we will choose the last value of the IP - // address as our random number, ( or at least something that is based upon it) - if (isFirstTime) { - byte[] address = InetAddress.getLocalHost().getAddress(); - int lastAddress = address[address.length - 1]; - if (lastAddress > 127) - lastAddress = lastAddress - 127; - if (lastAddress > 127) - lastAddress = lastAddress - 127; - - possible = (byte) lastAddress; - } else - possible = (byte) (Math.random() * 128); - - int count = 0; - for (; ; ) { - if (knownIdentifiers.setIfClear(possible)) { - return possible; - } - - count++; - - if (count == 128) { - throw new IllegalStateException("The grid is full, its not possible for any more nodes to " + - "going the grid."); - } - - if (possible == Byte.MAX_VALUE) - possible = 0; - else - possible++; - } - } - -} - -/** - * Broadcast the nodes host ports and identifiers over UDP, to make it easy to join a grid of remote - * nodes just by name, this functionality requires UDP - * - * @author Rob Austin. - */ -class NodeDiscoveryBroadcaster extends UdpChannelReplicator { - - public static final Logger LOG = LoggerFactory.getLogger(NodeDiscoveryBroadcaster.class.getName()); - - private static final byte UNUSED = (byte) -1; - - static final ByteBufferBytes BOOTSTRAP_BYTES; - - static { - final String BOOTSTRAP = "BOOTSTRAP"; - BOOTSTRAP_BYTES = new ByteBufferBytes(ByteBuffer.allocate(2 + BOOTSTRAP.length())); - BOOTSTRAP_BYTES.write((short) BOOTSTRAP.length()); - BOOTSTRAP_BYTES.append(BOOTSTRAP); - } - - static String toString(DirectBitSet bitSet) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < bitSet.size(); i++) { - builder.append(bitSet.get(i) ? '1' : '0'); - } - return builder.toString(); - } - - /** - * @param replicationConfig - * @param externalizable - * @throws java.io.IOException - */ - NodeDiscoveryBroadcaster( - final UdpTransportConfig replicationConfig, - final int serializedEntrySize, - final BytesMarshallable externalizable) - throws IOException { - - super(replicationConfig, UNUSED); - - final UdpSocketChannelEntryWriter writer = new UdpSocketChannelEntryWriter(1024, externalizable, this); - final UdpSocketChannelEntryReader reader = new UdpSocketChannelEntryReader(1024, externalizable); - - setReader(reader); - setWriter(writer); - - start(); - } - - static class UdpSocketChannelEntryReader implements EntryReader { - - private final ByteBuffer in; - private final ByteBufferBytes out; - private final BytesMarshallable externalizable; - - /** - * @param serializedEntrySize the maximum size of an entry include the meta data - * @param externalizable supports reading and writing serialize entries - */ - UdpSocketChannelEntryReader(final int serializedEntrySize, - @NotNull final BytesMarshallable externalizable) { - // we make the buffer twice as large just to give ourselves headroom - in = allocateDirect(serializedEntrySize * 2); - - out = new ByteBufferBytes(in); - out.limit(0); - in.clear(); - this.externalizable = externalizable; - } - - /** - * reads entries from the socket till it is empty - * - * @param socketChannel the socketChannel that we will read from - * @throws IOException - * @throws InterruptedException - */ - public void readAll(@NotNull final DatagramChannel socketChannel) throws IOException, - InterruptedException { - - out.clear(); - in.clear(); - - socketChannel.receive(in); - - final int bytesRead = in.position(); - - if (bytesRead < SIZE_OF_SIZE + SIZE_OF_SIZE) - return; - - out.limit(in.position()); - - final int invertedSize = out.readInt(); - final int size = out.readInt(); - - // check the the first 4 bytes are the inverted len followed by the len - // we do this to check that this is a valid start of entry, otherwise we throw it away - if (~size != invertedSize) - return; - - if (out.remaining() != size) - return; - - externalizable.readMarshallable(out); - } - } - - static class UdpSocketChannelEntryWriter implements EntryWriter { - - private final ByteBuffer out; - private final ByteBufferBytes in; - - @NotNull - private final BytesMarshallable externalizable; - private UdpChannelReplicator udpReplicator; - - UdpSocketChannelEntryWriter(final int serializedEntrySize, - @NotNull final BytesMarshallable externalizable, - @NotNull final UdpChannelReplicator udpReplicator) { - this.externalizable = externalizable; - this.udpReplicator = udpReplicator; - - // we make the buffer twice as large just to give ourselves headroom - out = allocateDirect(serializedEntrySize * 2); - in = new ByteBufferBytes(out); - } - - /** - * @param socketChannel the socketChannel that we will write to - * @throws InterruptedException - * @throws IOException - */ - public int writeAll(@NotNull final DatagramChannel socketChannel) - throws InterruptedException, IOException { - - out.clear(); - in.clear(); - - // skip the size inverted - in.skip(SIZE_OF_SIZE); - - // skip the size - in.skip(SIZE_OF_SIZE); - - long start = in.position(); - - // writes the contents of - externalizable.writeMarshallable(in); - - long size = in.position() - start; - - // we'll write the size inverted at the start - in.writeInt(0, ~((int) size)); - in.writeInt(SIZE_OF_SIZE, (int) size); - - out.limit((int) in.position()); - - udpReplicator.disableWrites(); - - return socketChannel.write(out); - } - } - -} - -class KnownNodes implements BytesMarshallable { - - private Bytes activeIdentifiersBitSetBytes; - private ConcurrentSkipListSet addressAndPorts = new ConcurrentSkipListSet(); - private ATSDirectBitSet atsDirectBitSet; - - KnownNodes() { - this.activeIdentifiersBitSetBytes = new ByteBufferBytes(ByteBuffer.allocate(128 / 8)); - this.addressAndPorts = new ConcurrentSkipListSet(); - this.atsDirectBitSet = new ATSDirectBitSet(this.activeIdentifiersBitSetBytes); - } - - public Set addressAndPorts() { - return addressAndPorts; - } - - public void add(AddressAndPort inetSocketAddress, byte identifier) { - identifiers().set(identifier); - addressAndPorts.add(inetSocketAddress); - } - - /** - * all the known identifiers - * - * @return - */ - public DirectBitSet identifiers() { - return atsDirectBitSet; - } - - @Override - public void readMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes in) throws IllegalStateException { - short size = in.readShort(); - - for (int i = 0; i < size; i++) { - final AddressAndPort addressAndPort = new AddressAndPort(); - addressAndPort.readMarshallable(in); - addressAndPorts.add(addressAndPort); - } - - final ByteBufferBytes activeIdentifiersBitSetBytes = new ByteBufferBytes(ByteBuffer.allocate(128 / 8)); - activeIdentifiersBitSetBytes.readMarshallable(in); - - final ATSDirectBitSet bitset = new ATSDirectBitSet(activeIdentifiersBitSetBytes); - for (long next = bitset.nextSetBit(0); next > 0; next = bitset.nextSetBit(next + 1)) { - atsDirectBitSet.set(next); - } - } - - @Override - public void writeMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes out) { - // make a safe copy - final Set addressAndPorts = new HashSet(this.addressAndPorts); - - // write the size - out.writeShort(addressAndPorts.size()); - - for (AddressAndPort bytesMarshallable : addressAndPorts) { - bytesMarshallable.writeMarshallable(out); - } - - activeIdentifiersBitSetBytes.clear(); - activeIdentifiersBitSetBytes.writeMarshallable(out); - } - - @Override - public String toString() { - return "RemoteNodes{" + - " addressAndPorts=" + addressAndPorts + - ", bitSet=" + NodeDiscoveryBroadcaster.toString(atsDirectBitSet) + - '}'; - } -} - -class AddressAndPort implements Comparable, BytesMarshallable { - private byte[] address; - private short port; - - AddressAndPort(byte[] address, short port) { - this.address = address; - this.port = port; - } - - public AddressAndPort() { - } - - public byte[] getAddress() { - return address; - } - - public short getPort() { - return port; - } - - public byte[] address() { - return address; - } - - public short port() { - return port; - } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || AddressAndPort.class != o.getClass()) return false; - - AddressAndPort that = (AddressAndPort) o; - - if (port != that.port) return false; - if (!Arrays.equals(address, that.address)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = Arrays.hashCode(address); - result = 31 * result + (int) port; - return result; - } - - @Override - public int compareTo(AddressAndPort o) { - int i = 0; - for (byte b : address) { - int compare = Byte.compare(b, o.address[i++]); - if (compare != 0) - return compare; - } - return Short.compare(port, o.port); - } - - @Override - public String toString() { - return "{" + - "address=" + numericToTextFormat(address) + - ", port=" + port + - '}'; - } - - final static int INADDRSZ = 16; - final static int INT16SZ = 2; - - static String numericToTextFormat(byte[] src) { - if (src.length == 4) { - return (src[0] & 0xff) + "." + (src[1] & 0xff) + "." + (src[2] & 0xff) + "." + (src[3] & 0xff); - } - - StringBuilder sb = new StringBuilder(39); - for (int i = 0; i < (INADDRSZ / INT16SZ); i++) { - sb.append(Integer.toHexString(((src[i << 1] << 8) & 0xff00) - | (src[(i << 1) + 1] & 0xff))); - if (i < (INADDRSZ / INT16SZ) - 1) { - sb.append(":"); - } - } - - return sb.toString(); - } - - @Override - public void readMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes in) throws IllegalStateException { - short len = in.readShort(); - address = new byte[len]; - - for (int i = 0; i < len; i++) { - address[i] = in.readByte(); - } - port = in.readShort(); - } - - @Override - public void writeMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes out) { - out.writeShort(getAddress().length); - for (byte address : getAddress()) { - out.write(address); - } - out.writeShort(port); - } -} - -class DiscoveryNodeBytesMarshallable implements BytesMarshallable { - - private AddressAndPort sourceAddressAndPort = new AddressAndPort(); - private final KnownNodes remoteNode; - - private final AtomicBoolean bootstrapRequired = new AtomicBoolean(); - private final AtomicReference nodeDiscoveryEventListener; - - private ProposedNodes ourProposedIdentifier; - - final ConcurrentExpiryMap proposedIdentifiersWithHost = new - ConcurrentExpiryMap(AddressAndPort.class, - ProposedNodes.class); - - private AddressAndPort ourAddressAndPort; - - public ProposedNodes getOurProposedIdentifier() { - return ourProposedIdentifier; - } - - private void setOurProposedIdentifier(ProposedNodes ourProposedIdentifier) { - this.ourProposedIdentifier = ourProposedIdentifier; - } - - public void setModificationNotifier(Replica.ModificationNotifier modificationNotifier) { - this.modificationNotifier = modificationNotifier; - } - - Replica.ModificationNotifier modificationNotifier; - - public DiscoveryNodeBytesMarshallable(@NotNull final KnownNodes remoteNode, - @NotNull final AtomicReference - nodeDiscoveryEventListener, - @NotNull final AddressAndPort ourAddressAndPort) { - this.remoteNode = remoteNode; - this.nodeDiscoveryEventListener = nodeDiscoveryEventListener; - this.ourAddressAndPort = ourAddressAndPort; - } - - public KnownNodes getRemoteNodes() { - return remoteNode; - } - - /** - * this is used to tell nodes that are connecting to us which host and ports are in our grid, - * along with all the identifiers. - */ - @Override - public void writeMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes out) { - if (bootstrapRequired.getAndSet(false)) { - writeBootstrap(out); - return; - } - - // the host and port the message came from - ourAddressAndPort.writeMarshallable(out); - - remoteNode.writeMarshallable(out); - - // we are no going to broadcast all the nodes that have been bootstaping in the last second - proposedIdentifiersWithHost.expireEntries(System.currentTimeMillis() - SECONDS.toMillis(1)); - - proposedIdentifiersWithHost.writeMarshallable(out); - } - - private boolean writeBootstrap(Bytes out) { - final ProposedNodes ourProposedIdentifier = getOurProposedIdentifier(); - if (ourProposedIdentifier == null || ourProposedIdentifier.addressAndPort == null) - return false; - - BOOTSTRAP_BYTES.clear(); - out.write(BOOTSTRAP_BYTES, BOOTSTRAP_BYTES.position(), BOOTSTRAP_BYTES.remaining()); - - ourProposedIdentifier.writeMarshallable(out); - return true; - } - - /** - * @param in - * @return returns true if the UDP message contains the text 'BOOTSTRAP' - */ - private ProposedNodes readBootstrapMessage(Bytes in) { - final long start = in.position(); - - try { - - long size = BOOTSTRAP_BYTES.limit(); - - if (size > in.remaining()) - return null; - - // reads the text bootstrap - for (int i = 0; i < size; i++) { - final byte byteRead = in.readByte(); - final byte expectedByte = BOOTSTRAP_BYTES.readByte(i); - - if (!(expectedByte == byteRead)) - return null; - } - - final ProposedNodes result = new ProposedNodes(); - result.readMarshallable(in); - - return result; - } finally { - in.position(start); - } - } - - @Override - public void readMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes in) throws IllegalStateException { - - final ProposedNodes bootstrap = readBootstrapMessage(in); - if (bootstrap != null) { - if (bootstrap.addressAndPort().equals(this.ourAddressAndPort)) - return; - - if (LOG.isDebugEnabled()) - LOG.debug("Received Bootstrap from " + bootstrap); - - proposedIdentifiersWithHost.put(bootstrap.addressAndPort, bootstrap); - - // we've received a bootstrap message so will will now rebroadcast what we know, - // after a random delay - // Thread.sleep((int) (Math.random() * 9.0)); - - // this is used to turn on the OP_WRITE, so that we can broadcast back the known host and - // ports in the grid - onChange(); - return; - } - - // the host and port the message came from - this.sourceAddressAndPort.readMarshallable(in); - if (sourceAddressAndPort.equals(ourAddressAndPort)) - return; - - LOG.debug("Received Proposal"); - - this.remoteNode.readMarshallable(in); - this.proposedIdentifiersWithHost.readMarshallable(in); - - NodeDiscoveryEventListener listener = nodeDiscoveryEventListener.get(); - if (listener != null) - listener.onRemoteNodeEvent(remoteNode, proposedIdentifiersWithHost); - } - - public void onChange() { - if (modificationNotifier != null) - modificationNotifier.onChange(); - } - - static class ProposedNodes implements BytesMarshallable { - - private byte identifier; - private long timestamp; - private AddressAndPort addressAndPort; - - public ProposedNodes() { - } - - public byte identifier() { - return identifier; - } - - ProposedNodes(@NotNull final AddressAndPort addressAndPort, - byte identifier) { - this.addressAndPort = addressAndPort; - this.identifier = identifier; - this.timestamp = System.currentTimeMillis(); - } - - AddressAndPort addressAndPort() { - return addressAndPort; - } - - @Override - public void readMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes in) throws IllegalStateException { - addressAndPort = new AddressAndPort(); - addressAndPort.readMarshallable(in); - timestamp = in.readLong(); - identifier = in.readByte(); - } - - @Override - public void writeMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes out) { - addressAndPort.writeMarshallable(out); - out.writeLong(timestamp); - out.writeByte(identifier); - } - - @Override - public String toString() { - return "{" + - "identifier=" + identifier + - ", timestamp=" + timestamp + - ", addressAndPort=" + addressAndPort + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || ProposedNodes.class != o.getClass()) return false; - - ProposedNodes that = (ProposedNodes) o; - - if (identifier != that.identifier) return false; - if (!addressAndPort.equals(that.addressAndPort)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = (int) identifier; - result = 31 * result + addressAndPort.hashCode(); - return result; - } - } - - /** - * sends a bootstrap message to the other nodes in the grid, the bootstrap message contains the - * host:port and perhaps even proposed identifier of the node that sent it. - * - * @param proposedNodes - */ - public void sendBootStrap(ProposedNodes proposedNodes) { - setOurProposedIdentifier(proposedNodes); - bootstrapRequired.set(true); - onChange(); - } - -} - -interface NodeDiscoveryEventListener { - /** - * called when we have received a UDP message, this is called after the message has been parsed - */ - void onRemoteNodeEvent(KnownNodes remoteNode, ConcurrentExpiryMap proposedIdentifiersWithHost); -} - -class ConcurrentExpiryMap implements BytesMarshallable { - - final ConcurrentMap map = new - ConcurrentHashMap(); - private final Class kClass; - private final Class vClass; - - ConcurrentExpiryMap(Class kClass, Class vClass) { - this.kClass = kClass; - this.vClass = vClass; - } - - @Override - public String toString() { - return "ConcurrentExpiryMap{" + map + '}'; - } - - @Override - public void readMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes in) throws IllegalStateException { - - short size = in.readShort(); - try { - for (int i = 0; i < size; i++) { - final K k = kClass.newInstance(); - k.readMarshallable(in); - - final V v = vClass.newInstance(); - v.readMarshallable(in); - - map.put(k, v); - } - } catch (Exception e) { - LOG.error("", e); - } - } - - @Override - public void writeMarshallable(@net.openhft.lang.model.constraints.NotNull Bytes out) { - final Map safeCopy = new HashMap(map); - out.writeShort(safeCopy.size()); - for (Map.Entry entry : safeCopy.entrySet()) { - entry.getKey().writeMarshallable(out); - entry.getValue().writeMarshallable(out); - } - } - - class W { - final long timestamp; - final V v; - - W(V v) { - this.v = v; - this.timestamp = System.currentTimeMillis(); - } - } - - void put(final K k, final V v) { - map.put(k, v); - final W w = new W(v); - queue.add(new Map.Entry>() { - @Override - public K getKey() { - return k; - } - - @Override - public W getValue() { - return w; - } - - @Override - public W setValue(W value) { - throw new UnsupportedOperationException(); - } - }); - } - - // this is used for expiry - private final Queue>> queue = new ConcurrentLinkedQueue>>(); - - java.util.Collection values() { - return map.values(); - } - - void expireEntries(long timeOlderThan) { - for (; ; ) { - final Map.Entry> e = this.queue.peek(); - - if (e == null) - break; - - if (e.getValue().timestamp < timeOlderThan) { - // only remote it if it has not changed - map.remove(e.getKey(), e.getValue().v); - } - - this.queue.poll(); - } - } - - public static void main(String... args) { - String ip; - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface iface = interfaces.nextElement(); - // filters out 127.0.0.1 and inactive interfaces - if (iface.isLoopback() || !iface.isUp()) - continue; - - Enumeration addresses = iface.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - ip = addr.getHostAddress(); - System.out.println(iface.getDisplayName() + " " + ip); - } - } - } catch (SocketException e) { - throw new RuntimeException(e); - } - } - - /** - * private NetworkInterface defaultNetworkInterface() throws SocketException { NetworkInterface - * networkInterface = null - * - * for (String suggestedName : new String[]{"en0", "eth0"}) { networkInterface = - * NetworkInterface.getByName(suggestedName); if (networkInterface != null) break; } return - * networkInterface; } - * - * /** - * - * @return the default network interface, or - * @throws SocketException - */ - public static NetworkInterface defaultNetworkInterface() throws SocketException { - NetworkInterface networkInterface = null; - - for (String suggestedName : new String[]{"en0", "eth0"}) { - networkInterface = NetworkInterface.getByName(suggestedName); - if (networkInterface != null) - break; - } - - if (networkInterface != null) - return networkInterface; - - Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); - if (networkInterfaces == null || !networkInterfaces.hasMoreElements()) - return null; - - return networkInterfaces.nextElement(); - } - - public static InetAddress getDefaultAddress() throws SocketException { - NetworkInterface networkInterface = ConcurrentExpiryMap.defaultNetworkInterface(); - Enumeration inetAddresses = networkInterface.getInetAddresses(); - - // we will take the last one as this is likely to be an ipv address which is easier to work with - InetAddress inetAddress = null; - for (; inetAddresses.hasMoreElements(); ) { - inetAddress = inetAddresses.nextElement(); - } - - if (inetAddress == null) - throw new IllegalStateException(); - - return inetAddress; - } -} diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java index 944c2a524..a243c76fd 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java @@ -32,7 +32,7 @@ import java.util.function.Predicate; public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate { private static final Logger LOG = LoggerFactory.getLogger(OldDeletedEntriesCleanup.class); - private final ReplicatedChronicleMap map; + private final ReplicatedChronicleMap map; private final int[] segmentsPermutation; private final int[] inverseSegmentsPermutation; private volatile boolean shutdown; @@ -40,7 +40,7 @@ public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate< private long prevSegment0ScanStart = -1; private long removedCompletely; - public OldDeletedEntriesCleanup(ReplicatedChronicleMap map) { + public OldDeletedEntriesCleanup(ReplicatedChronicleMap map) { this.map = map; segmentsPermutation = randomPermutation(map.segments()); inverseSegmentsPermutation = inversePermutation(segmentsPermutation); diff --git a/src/main/java/net/openhft/chronicle/map/Replica.java b/src/main/java/net/openhft/chronicle/map/Replica.java index 6a3970a0a..7a9f24f38 100644 --- a/src/main/java/net/openhft/chronicle/map/Replica.java +++ b/src/main/java/net/openhft/chronicle/map/Replica.java @@ -16,8 +16,8 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.replication.ReplicableEntry; -import net.openhft.lang.io.Bytes; import org.jetbrains.annotations.NotNull; import java.io.Closeable; @@ -192,14 +192,14 @@ public interface Replica extends Closeable { final Bytes entry, final int chronicleId, long bootstrapTime); /** - * Called just after {@link #onEntry(net.openhft.lang.io.Bytes, int, long)}. + * Called just after {@link #onEntry(Bytes, int, long)}. * No-op by default. */ public void onAfterEntry() { } /** - * Called just before {@link #onEntry(net.openhft.lang.io.Bytes, int, long)}. + * Called just before {@link #onEntry(Bytes, int, long)}. * No-op by default. */ public void onBeforeEntry() { diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index 22d01ee1e..71716d7e0 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.map; -import net.openhft.chronicle.algo.bitset.BitSetFrame; -import net.openhft.chronicle.algo.bitset.ConcurrentFlatBitSetFrame; -import net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame; +import net.openhft.chronicle.algo.bitset.*; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.core.Maths; import net.openhft.chronicle.hash.VanillaGlobalMutableState; import net.openhft.chronicle.hash.impl.TierCountersArea; import net.openhft.chronicle.hash.impl.VanillaChronicleHash; @@ -26,14 +26,10 @@ import net.openhft.chronicle.hash.impl.stage.hash.ChainingInterface; import net.openhft.chronicle.hash.replication.AbstractReplication; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.TimeProvider; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.impl.CompiledReplicatedMapIterationContext; import net.openhft.chronicle.map.impl.CompiledReplicatedMapQueryContext; import net.openhft.chronicle.map.replication.MapRemoteOperations; -import net.openhft.lang.Maths; -import net.openhft.lang.collection.ATSDirectBitSet; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.model.DataValueClasses; +import net.openhft.chronicle.values.Values; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,9 +43,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; +import static net.openhft.chronicle.algo.MemoryUnit.*; +import static net.openhft.chronicle.algo.bitset.BitSetFrame.NOT_FOUND; +import static net.openhft.chronicle.algo.bytes.Access.checkedBytesStoreAccess; import static net.openhft.chronicle.algo.bytes.Access.nativeAccess; -import static net.openhft.lang.MemoryUnit.*; -import static net.openhft.lang.collection.DirectBitSet.NOT_FOUND; /** *

A Replicating Multi Master HashMap

Each remote hash map, mirrors its changes over to @@ -89,9 +86,7 @@ import static net.openhft.lang.collection.DirectBitSet.NOT_FOUND; * @param the entries key type * @param the entries value type */ -public class ReplicatedChronicleMap, - V, VI, MVI extends MetaBytesInterop, R> - extends VanillaChronicleMap +public class ReplicatedChronicleMap extends VanillaChronicleMap implements Replica, Replica.EntryExternalizable { // for file, jdbc and UDP replication public static final int RESERVED_MOD_ITER = 8; @@ -107,9 +102,9 @@ public class ReplicatedChronicleMap closeables; - private transient Bytes identifierUpdatedBytes; + private transient long identifierUpdatedBytesOffset; - private transient ATSDirectBitSet modIterSet; + private transient BitSet modIterSet; private transient AtomicReferenceArray modificationIterators; private transient long startOfModificationIterators; private transient boolean bootstrapOnlyLocalEntries; @@ -118,8 +113,8 @@ public class ReplicatedChronicleMap remoteOperations; - transient CompiledReplicatedMapQueryContext remoteOpContext; - transient CompiledReplicatedMapIterationContext remoteItContext; + transient CompiledReplicatedMapQueryContext remoteOpContext; + transient CompiledReplicatedMapIterationContext remoteItContext; transient BitSetFrame mainSegmentsModIterFrameForUpdates; transient BitSetFrame mainSegmentsModIterFrameForIteration; @@ -135,7 +130,7 @@ public class ReplicatedChronicleMap mapContext() { + public CompiledReplicatedMapQueryContext mapContext() { return q().getContext(CompiledReplicatedMapQueryContext.class, ci -> new CompiledReplicatedMapQueryContext<>(ci, this)); } @@ -492,19 +486,18 @@ public class ReplicatedChronicleMap remoteOpContext() { + private CompiledReplicatedMapQueryContext remoteOpContext() { if (remoteOpContext == null) { - remoteOpContext = (CompiledReplicatedMapQueryContext) q(); + remoteOpContext = (CompiledReplicatedMapQueryContext) q(); } assert !remoteOpContext.usedInit(); remoteOpContext.initUsed(true); return remoteOpContext; } - private CompiledReplicatedMapIterationContext remoteItContext() { + private CompiledReplicatedMapIterationContext remoteItContext() { if (remoteItContext == null) { - remoteItContext = - (CompiledReplicatedMapIterationContext) i(); + remoteItContext = (CompiledReplicatedMapIterationContext) i(); } assert !remoteItContext.usedInit(); remoteItContext.initUsed(true); @@ -517,8 +510,7 @@ public class ReplicatedChronicleMap remoteOpContext = - mapContext()) { + try (CompiledReplicatedMapQueryContext remoteOpContext = mapContext()) { remoteOpContext.initReplicationInput(source); remoteOpContext.processReplicatedEvent(); } @@ -534,7 +526,7 @@ public class ReplicatedChronicleMap iterationContext() { + public CompiledReplicatedMapIterationContext iterationContext() { return i().getContext(CompiledReplicatedMapIterationContext.class, ci -> new CompiledReplicatedMapIterationContext<>(ci, this)); } @@ -579,7 +571,7 @@ public class ReplicatedChronicleMap> log2TiersInBulk; TierBulkData tierBulkData = tierBulkOffsets.get((int) bulkIndex); - long bitSetAddr = tierBulkData.langBytes.address() + tierBulkData.offset + - offsetToBitSetWithinATierBulk; + long bitSetAddr = bitSetAddr(tierBulkData); tierBulkModIterFrameForUpdates.set(nativeAccess(), null, bitSetAddr, bitIndex); } @@ -659,12 +650,16 @@ public class ReplicatedChronicleMap> log2TiersInBulk; TierBulkData tierBulkData = tierBulkOffsets.get((int) bulkIndex); - long bitSetAddr = tierBulkData.langBytes.address() + tierBulkData.offset + - offsetToBitSetWithinATierBulk; + long bitSetAddr = bitSetAddr(tierBulkData); return tierBulkModIterFrameForUpdates.clearIfSet(nativeAccess(), null, bitSetAddr, bitIndex); } + private long bitSetAddr(TierBulkData tierBulkData) { + return tierBulkData.bytesStore.address(tierBulkData.offset) + + offsetToBitSetWithinATierBulk; + } + boolean isChanged(long tierIndex, long pos) { long bitIndex = combine(tierIndex, pos); if (tierIndex <= actualSegments) { @@ -679,8 +674,7 @@ public class ReplicatedChronicleMap> log2TiersInBulk; TierBulkData tierBulkData = tierBulkOffsets.get((int) bulkIndex); - long bitSetAddr = tierBulkData.langBytes.address() + tierBulkData.offset + - offsetToBitSetWithinATierBulk; + long bitSetAddr = bitSetAddr(tierBulkData); return tierBulkModIterFrameForUpdates.isSet(nativeAccess(), null, bitSetAddr, bitIndex); } @@ -718,8 +712,7 @@ public class ReplicatedChronicleMap>> segmentIndexShift); - try (CompiledReplicatedMapIterationContext context = + try (CompiledReplicatedMapIterationContext context = iterationContext()) { if (iterationMainSegmentsAreaOrTierBulk < 0) { // if main area @@ -793,8 +786,9 @@ public class ReplicatedChronicleMap c = - iterationContext()) { + try (CompiledReplicatedMapIterationContext c = iterationContext()) { // iterate over all the segments and mark bit in the modification iterator // that correspond to entries with an older timestamp boolean debugEnabled = LOG.isDebugEnabled(); diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedGlobalMutableState.java b/src/main/java/net/openhft/chronicle/map/ReplicatedGlobalMutableState.java index 25d64a716..b86f76d11 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedGlobalMutableState.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedGlobalMutableState.java @@ -17,10 +17,11 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.VanillaGlobalMutableState; +import net.openhft.chronicle.values.Group; interface ReplicatedGlobalMutableState extends VanillaGlobalMutableState { + @Group(5) int getCurrentCleanupSegmentIndex(); - void setCurrentCleanupSegmentIndex(int currentCleanupSegmentIndex); } diff --git a/src/main/java/net/openhft/chronicle/map/ReplicationHubFindByName.java b/src/main/java/net/openhft/chronicle/map/ReplicationHubFindByName.java deleted file mode 100644 index 7ec57cd96..000000000 --- a/src/main/java/net/openhft/chronicle/map/ReplicationHubFindByName.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.chronicle.hash.ChronicleHash; -import net.openhft.chronicle.hash.ChronicleHashBuilder; -import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder; -import net.openhft.chronicle.hash.replication.ReplicationChannel; -import net.openhft.chronicle.hash.replication.ReplicationHub; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Rob Austin. - */ -class ReplicationHubFindByName implements FindByName { - public static final Logger LOG = LoggerFactory.getLogger(ReplicationHubFindByName.class.getName()); - - public static final int MAP_BY_NAME_CHANNEL = 1; - - private final AtomicInteger nextFreeChannel = new AtomicInteger(2); - private final ChronicleMap map; - private final ReplicationHub replicationHub; - - /** - * @throws IOException - */ - public ReplicationHubFindByName(ReplicationHub replicationHub) throws IOException { - - LOG.info("connecting to replicationHub=" + replicationHub); - - this.replicationHub = replicationHub; - ReplicationChannel channel = replicationHub.createChannel((short) MAP_BY_NAME_CHANNEL); - - this.map = ChronicleMapBuilder - .of(CharSequence.class, MapInstanceBuilder.class) - .averageKeySize(10) - .averageValueSize(4000) - .entries(128) - .instance() - .replicatedViaChannel(channel) - .create(); - if (LOG.isDebugEnabled()) - LOG.debug("map=" + map); - } - - public T create( - MapInstanceBuilder config) - throws IOException, TimeoutException, InterruptedException { - - int withChannelId = nextFreeChannel.incrementAndGet(); - - try (ExternalMapQueryContext c = - map.queryContext(config.name)) { - c.updateLock().lock(); - MapInstanceBuilder value = - config.replicatedViaChannel(replicationHub.createChannel(withChannelId)); - boolean added; - MapEntry entry = c.entry(); - if (entry != null) { - c.replaceValue(entry, c.wrapValueAsData(value)); - added = false; - } else { - c.insert(c.absentEntry(), c.wrapValueAsData(value)); - added = true; - } - - if (added) { - // establish the new map based on this channel ID - LOG.info("create new map for name=" + value.name - + ",channelId=" + value.channel.channelId()); - - try { - toReplicatedViaChannel(value.mapBuilder, value.channel.channelId()).create(); - } catch (IllegalStateException e) { - // channel is already created - LOG.debug("while creating channel for name=" + value.name - + ",channelId=" + value.channel.channelId(), e); - } catch (IOException e) { - LOG.error("", e); - } - } - } - - return (T) get(config.name).mapBuilder.create(); - } - - public T from(String name) throws IllegalArgumentException, - IOException, TimeoutException, InterruptedException { - return (T) get(name).create(); - } - - MapInstanceBuilder get(String name) throws IllegalArgumentException, - TimeoutException, - InterruptedException { - - MapInstanceBuilder config = waitTillEntryReceived(5000, name); - if (config == null) - throw new IllegalArgumentException("A map name=" + name + " can not be found."); - - return config; - } - - /** - * * waits until map1 and map2 show the same value - * - * @param timeOutMs timeout in milliseconds - * @throws InterruptedException - */ - private MapInstanceBuilder waitTillEntryReceived(final int timeOutMs, String name) - throws TimeoutException, InterruptedException { - int t = 0; - for (; t < timeOutMs; t++) { - MapInstanceBuilder config = map.get(name); - - if (config != null) - return config; - Thread.sleep(1); - } - throw new TimeoutException("timed out wait for map name=" + name); - } - - /** - * similar to {@link ChronicleMapBuilder#createPersistedTo(File file) } - * - * @param name the name of the map to be created - * @param file the file which will be used as shared off heap storage - * @param - * @return a new instance of ChronicleMap - * @throws IllegalArgumentException - * @throws IOException - * @see ChronicleMapBuilder#createPersistedTo(File file) - */ - public T createPersistedTo(String name, File file) - throws IllegalArgumentException, - IOException, TimeoutException, InterruptedException { - return (T) get(name).persistedTo(file).create(); - } - - private ChronicleHashInstanceBuilder toReplicatedViaChannel(ChronicleMapBuilder builder) { - int channelId = nextFreeChannel.incrementAndGet(); - if (channelId > replicationHub.maxNumberOfChannels()) - throw new IllegalStateException("There are no more free channels, you can increase the number " + - "of changes in the replicationHub by calling replicationHub.maxNumberOfChannels(..);"); - return builder.instance().replicatedViaChannel(replicationHub.createChannel((short) channelId)); - } - - private ChronicleHashInstanceBuilder toReplicatedViaChannel(ChronicleHashBuilder builder, int - withChannelId) { - return builder.instance().replicatedViaChannel(replicationHub.createChannel((short) withChannelId)); - } - -} diff --git a/src/main/java/net/openhft/chronicle/map/Replicator.java b/src/main/java/net/openhft/chronicle/map/Replicator.java index cdb9c4133..45b49c32b 100644 --- a/src/main/java/net/openhft/chronicle/map/Replicator.java +++ b/src/main/java/net/openhft/chronicle/map/Replicator.java @@ -16,15 +16,32 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.replication.AbstractReplication; +import net.openhft.chronicle.hash.replication.UdpTransportConfig; + import java.io.Closeable; import java.io.IOException; -abstract class Replicator { +interface Replicator { - /** - * A constructor for use in subclasses. - */ - protected Replicator() { + String ONLY_UDP_WARN_MESSAGE = + "MISSING TCP REPLICATION : The UdpReplicator only attempts to read data " + + "(it does not enforce or guarantee delivery), you should use" + + "the UdpReplicator if you have a large number of nodes, and you wish" + + "to receive the data before it becomes available on TCP/IP. Since data" + + "delivery is not guaranteed, it is recommended that you only use" + + "the UDP Replicator in conjunction with a TCP Replicator"; + + static Replicator tcp(final AbstractReplication replication) { + return (builder, replica, entryExternalizable, replicatedMap) -> + new TcpReplicator(replica, entryExternalizable, + replication.tcpTransportAndNetwork(), replication.remoteNodeValidator(), + replication.name(), replication.connectionListener()); + } + + static Replicator udp(final UdpTransportConfig replicationConfig) { + return (builder, map, entryExternalizable, replicatedMap) -> + new UdpReplicator(map, entryExternalizable, replicationConfig); } /** @@ -32,14 +49,12 @@ abstract class Replicator { * associated with the replication.

This method isn't intended to be called from the client * code. * - * @param chronicleMap to wrap. * @param builder the builder from which the map was constructed. The replicator may * obtain some map configurations, not accessible via the map * instance. * @param map a replicated map instance. Provides basic tools for replication * implementation. * @param entryExternalizable the callback for ser/deser implementation in the replicator - * @param replicatedMap * @return a {@code Closeable} token to control replication resources. It should be closed on * closing the replicated map. * @throws java.io.IOException if an io error occurred during the replicator setup @@ -48,7 +63,8 @@ abstract class Replicator { * already been applied to a map (or the specified number of * maps) */ - protected abstract Closeable applyTo(ChronicleMapBuilder builder, - Replica map, Replica.EntryExternalizable entryExternalizable, - final ReplicatedChronicleMap replicatedMap) throws IOException; + Closeable applyTo( + ChronicleMapBuilder builder, Replica map, + Replica.EntryExternalizable entryExternalizable, ReplicatedChronicleMap replicatedMap) + throws IOException; } diff --git a/src/main/java/net/openhft/chronicle/map/Replicators.java b/src/main/java/net/openhft/chronicle/map/Replicators.java deleted file mode 100644 index 72d02fad1..000000000 --- a/src/main/java/net/openhft/chronicle/map/Replicators.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.chronicle.hash.replication.AbstractReplication; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.hash.replication.UdpTransportConfig; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import org.jetbrains.annotations.NotNull; - -import java.io.Closeable; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -final class Replicators { - - static final String ONLY_UDP_WARN_MESSAGE = - "MISSING TCP REPLICATION : The UdpReplicator only attempts to read data " + - "(it does not enforce or guarantee delivery), you should use" + - "the UdpReplicator if you have a large number of nodes, and you wish" + - "to receive the data before it becomes available on TCP/IP. Since data" + - "delivery is not guaranteed, it is recommended that you only use" + - "the UDP Replicator in conjunction with a TCP Replicator"; - - private Replicators() { - } - - - static class OutBuffer implements BufferResizer { - - @NotNull - private ByteBufferBytes in; - - @NotNull - private ByteBuffer out; - - @NotNull - public ByteBufferBytes in() { - return in; - } - - @NotNull - public ByteBuffer out() { - return out; - } - - - OutBuffer(final int tcpBufferSize) { - out = ByteBuffer.allocateDirect(tcpBufferSize); - in = new ByteBufferBytes(out); - } - - @Override - public Bytes resizeBuffer(int newCapacity) { - - - if (newCapacity < out.capacity()) - throw new IllegalStateException("it not possible to resize the buffer smaller"); - - assert newCapacity < Integer.MAX_VALUE; - - final ByteBuffer result = ByteBuffer.allocate(newCapacity).order(ByteOrder.nativeOrder()); - final long bytesPosition = in.position(); - - in = new ByteBufferBytes(result.slice()); - - out.position(0); - out.limit((int) bytesPosition); - - int numberOfLongs = (int) bytesPosition / 8; - - // chunk in longs first - for (int i = 0; i < numberOfLongs; i++) { - in.writeLong(out.getLong()); - } - - for (int i = numberOfLongs * 8; i < bytesPosition; i++) { - in.writeByte(out.get()); - } - - out = result; - - assert out.capacity() == in.capacity(); - - assert out.capacity() == newCapacity; - assert out.capacity() == in.capacity(); - assert in.limit() == in.capacity(); - return in; - - } - } - - static Replicator tcp(final AbstractReplication replication) { - return new Replicator() { - - - @Override - protected Closeable applyTo(@NotNull final ChronicleMapBuilder builder, - @NotNull final Replica replica, - @NotNull final Replica.EntryExternalizable entryExternalizable, - final ReplicatedChronicleMap replicatedMap) throws IOException { - - TcpTransportAndNetworkConfig tcpConfig = replication.tcpTransportAndNetwork(); - - return new TcpReplicator(replica, entryExternalizable, - tcpConfig, - replication.remoteNodeValidator(), - replication.name(), - replication.connectionListener()); - } - }; - } - - static Replicator udp( - final UdpTransportConfig replicationConfig) { - return new Replicator() { - @Override - protected Closeable applyTo(@NotNull final ChronicleMapBuilder builder, - @NotNull final Replica map, - @NotNull final Replica.EntryExternalizable entryExternalizable, - final ReplicatedChronicleMap replicatedMap) - throws IOException { - return new UdpReplicator(map, entryExternalizable, replicationConfig - ); - } - }; - } -} diff --git a/src/main/java/net/openhft/chronicle/map/ServiceDescriptor.java b/src/main/java/net/openhft/chronicle/map/ServiceDescriptor.java deleted file mode 100644 index d3bc803c9..000000000 --- a/src/main/java/net/openhft/chronicle/map/ServiceDescriptor.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.chronicle.wire.Marshallable; -import net.openhft.chronicle.wire.WireIn; -import net.openhft.chronicle.wire.WireOut; - -public class ServiceDescriptor implements Marshallable { - - public Class keyClass; - public Class valueClass; - public short channelID; - - public ServiceDescriptor() { - } - - public ServiceDescriptor(Class keyClass, Class valueClass, short channelID) { - this.keyClass = keyClass; - this.valueClass = valueClass; - this.channelID = channelID; - } - - - @Override - public void writeMarshallable(WireOut wire) { - wire.write(() -> "keyClass").text(keyClass.getName()); - wire.write(() -> "valueClass").text(valueClass.getName()); - wire.write(() -> "channelID").int16(channelID); - } - - @Override - public void readMarshallable(WireIn wire) throws IllegalStateException { - try { - keyClass = (Class) Class.forName(wire.read(() -> "keyClass").text()); - valueClass = (Class) Class.forName(wire.read(() -> "valueClass").text()); - channelID = wire.read(() -> "channelID").int16(); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ServiceDescriptor serviceDescriptor = (ServiceDescriptor) o; - - if (channelID != serviceDescriptor.channelID) return false; - if (!keyClass.equals(serviceDescriptor.keyClass)) return false; - if (!valueClass.equals(serviceDescriptor.valueClass)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = keyClass.hashCode(); - result = 31 * result + valueClass.hashCode(); - result = 31 * result + (int) channelID; - return result; - } - } \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java index da6726da8..d4559e452 100644 --- a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java @@ -16,16 +16,15 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.algo.bitset.ConcurrentFlatBitSetFrame; +import net.openhft.chronicle.algo.bitset.ReusableBitSet; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.hash.impl.util.BuildVersion; import net.openhft.chronicle.hash.replication.ConnectionListener; import net.openhft.chronicle.hash.replication.RemoteNodeValidator; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.ThrottlingConfig; -import net.openhft.lang.collection.ATSDirectBitSet; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.DirectStore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -37,7 +36,9 @@ import java.net.*; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.CharBuffer; import java.nio.channels.*; +import java.nio.charset.StandardCharsets; import java.util.BitSet; import java.util.Map; import java.util.Set; @@ -46,8 +47,9 @@ import java.util.concurrent.TimeUnit; import static java.nio.channels.SelectionKey.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static net.openhft.chronicle.algo.MemoryUnit.*; +import static net.openhft.chronicle.algo.bytes.Access.checkedBytesStoreAccess; import static net.openhft.chronicle.hash.impl.util.BuildVersion.version; -import static net.openhft.lang.MemoryUnit.*; interface Work { @@ -564,7 +566,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme return true; } - private void checkVersions(final Attached attached) { + private void checkVersions(final Attached attached) { final String localVersion = BuildVersion.version(); final String remoteVersion = attached.serverVersion; @@ -876,7 +878,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme private static class KeyInterestUpdater { @NotNull - private final DirectBitSet changeOfOpWriteRequired; + private final net.openhft.chronicle.algo.bitset.BitSet changeOfOpWriteRequired; @NotNull private final SelectionKey[] selectionKeys; private final int op; @@ -884,8 +886,11 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme KeyInterestUpdater(int op, @NotNull final SelectionKey[] selectionKeys) { this.op = op; this.selectionKeys = selectionKeys; - long bitSetSize = LONGS.align(BYTES.alignAndConvert(selectionKeys.length, BITS), BYTES); - changeOfOpWriteRequired = new ATSDirectBitSet(DirectStore.allocate(bitSetSize).bytes()); + int bitSetSizeInBytes = + (int) LONGS.align(BYTES.alignAndConvert(selectionKeys.length, BITS), BYTES); + ConcurrentFlatBitSetFrame frame = new ConcurrentFlatBitSetFrame(selectionKeys.length); + changeOfOpWriteRequired = new ReusableBitSet(frame, checkedBytesStoreAccess(), + BytesStore.wrap(new byte[bitSetSizeInBytes]), 0); } public void applyUpdates() { @@ -1055,7 +1060,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme /** * Attached to the NIO selection key via methods such as {@link SelectionKey#attach(Object)} */ - class Attached implements Replica.ModificationNotifier { + class Attached implements Replica.ModificationNotifier { public TcpSocketChannelEntryReader entryReader; public TcpSocketChannelEntryWriter entryWriter; @@ -1092,7 +1097,6 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme */ public class TcpSocketChannelEntryWriter { - @NotNull private final EntryCallback entryCallback; // if uncompletedWork is set ( not null ) , this must be completed before any further work @@ -1119,41 +1123,15 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme * @param localIdentifier the current nodes identifier */ void identifierToBuffer(final byte localIdentifier) { - in().writeByte(localIdentifier); + entryIn().writeByte(localIdentifier); } - public void ensureBufferSize(long size) { - if (in().remaining() < size) { - size += entryCallback.in().position(); - if (size > Integer.MAX_VALUE) - throw new UnsupportedOperationException(); - entryCallback.resizeBuffer((int) size); - } + public Bytes entryIn() { + return entryCallback.entryIn(); } - void resizeToMessage(@NotNull IllegalStateException e) { - - String message = e.getMessage(); - if (message.startsWith("java.io.IOException: Not enough available space for writing ")) { - String substring = message.substring("java.io.IOException: Not enough available space for writing ".length(), message.length()); - int i = substring.indexOf(' '); - if (i != -1) { - int size = Integer.parseInt(substring.substring(0, i)); - - long requiresExtra = size - in().remaining(); - ensureBufferSize((int) (in().capacity() + requiresExtra)); - } else - throw e; - } else - throw e; - } - - public Bytes in() { - return entryCallback.in(); - } - - private ByteBuffer out() { - return entryCallback.out(); + private ByteBuffer socketOut() { + return entryCallback.socketOut(); } /** @@ -1162,11 +1140,15 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme * @param timeStampOfLastMessage the last timestamp we received a message from that node */ void writeRemoteBootstrapTimestamp(final long timeStampOfLastMessage) { - in().writeLong(timeStampOfLastMessage); + entryIn().writeLong(timeStampOfLastMessage); } void writeServerVersion() { - in().write(String.format("%1$" + 64 + "s", version()).toCharArray()); + String version = String.format("%1$" + 64 + "s", version()); + ByteBuffer codedVersion = StandardCharsets.US_ASCII.encode(version); + if (codedVersion.remaining() != 64) + throw new AssertionError(); + entryIn().write(codedVersion); } /** @@ -1181,7 +1163,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme try { for (; ; entriesWritten++) { - long start = in().position(); + long start = entryIn().writePosition(); boolean success = modificationIterator.nextEntry(entryCallback, 0); @@ -1192,15 +1174,15 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme if (!success) return; - long entrySize = in().position() - start; + long entrySize = entryIn().writePosition() - start; if (entrySize > largestEntrySoFar) largestEntrySoFar = entrySize; // we've filled up the buffer lets give another channel a chance to send // some data - if (in().remaining() <= largestEntrySoFar || in().position() > - replicationConfig.tcpBufferSize()) + if (entryIn().writeRemaining() <= largestEntrySoFar || + entryIn().writePosition() > replicationConfig.tcpBufferSize()) return; // if we have space in the buffer to write more data and we just wrote data @@ -1222,35 +1204,34 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme private int writeBufferToSocket(@NotNull final SocketChannel socketChannel, final long approxTime) throws IOException { - final Bytes in = in(); - final ByteBuffer out = out(); + final Bytes in = entryIn(); + final ByteBuffer out = socketOut(); - if (in.position() == 0) + int bytesToWrite = (int) in.readRemaining(); + if (bytesToWrite == 0) return 0; // if we still have some unwritten writer from last time lastSentTime = approxTime; - assert in.position() <= Integer.MAX_VALUE; - int size = (int) in.position(); - out.limit(size); + out.position(0); + out.limit(bytesToWrite); - final int len = socketChannel.write(out); + final int bytesWritten = socketChannel.write(out); if (LOG.isDebugEnabled()) - LOG.debug("bytes-written=" + len); + LOG.debug("bytes-written=" + bytesWritten); - if (len == size) { + if (bytesWritten == bytesToWrite) { out.clear(); in.clear(); } else { out.compact(); - in.position(out.position()); - in.limit(in.capacity()); + in.writePosition(out.position()); out.clear(); } - return len; + return bytesWritten; } @@ -1260,23 +1241,22 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme */ private void writeHeartbeatToBuffer() { // denotes the state - 0 for a heartbeat - in().writeByte(HEARTBEAT); + entryIn().writeByte(HEARTBEAT); // denotes the size in bytes - in().writeInt(0); + entryIn().writeInt(0); } private void writeRemoteHeartbeatInterval(long localHeartbeatInterval) { - in().writeLong(localHeartbeatInterval); + entryIn().writeLong(localHeartbeatInterval); } - public boolean doWork() { - return uncompletedWork != null && uncompletedWork.doWork(in()); + return uncompletedWork != null && uncompletedWork.doWork(entryIn()); } public boolean hasBytesToWrite() { - return in().position() > 0; + return entryIn().readRemaining() > 0; } } @@ -1287,46 +1267,43 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme public static final int HEADROOM = 1024; public static final int SIZE_OF_BOOTSTRAP_TIMESTAMP = 8; public long lastHeartBeatReceived = System.currentTimeMillis(); - ByteBuffer in; - ByteBufferBytes out; + ByteBuffer socketIn; + Bytes entryOut; private long sizeInBytes; private byte state; private TcpSocketChannelEntryReader() { - in = ByteBuffer.allocateDirect(replicationConfig.tcpBufferSize()); - out = new ByteBufferBytes(in.slice()); - out.limit(0); - in.clear(); + socketIn = ByteBuffer.allocateDirect(replicationConfig.tcpBufferSize()); + // TODO why here (and in UDP) bytes created through slice? + entryOut = Bytes.wrapForRead(socketIn.slice()); + entryOut.readLimit(0); + socketIn.clear(); } void resizeBuffer(long size) { assert size < Integer.MAX_VALUE; - if (size < in.capacity()) + if (size < socketIn.capacity()) throw new IllegalStateException("it not possible to resize the buffer smaller"); final ByteBuffer buffer = ByteBuffer.allocateDirect((int) size) .order(ByteOrder.nativeOrder()); - final int inPosition = in.position(); + final int inPosition = socketIn.position(); - long outPosition = out.position(); - long outLimit = out.limit(); + long outPosition = entryOut.readPosition(); + long outLimit = entryOut.readLimit(); - out = new ByteBufferBytes(buffer.slice()); + entryOut = Bytes.wrapForRead(buffer.slice()); - // TODO why copy byte by byte?! - in.position(0); - for (int i = 0; i < inPosition; i++) { - buffer.put(in.get()); - } + socketIn.flip(); + buffer.put(socketIn); + buffer.clear(); + buffer.position(inPosition); + socketIn = buffer; - in = buffer; - in.limit(in.capacity()); - in.position(inPosition); - - out.limit(outLimit); - out.position(outPosition); + entryOut.readLimit(outLimit); + entryOut.readPosition(outPosition); } /** @@ -1340,32 +1317,28 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme throws IOException { compactBuffer(); - final int len = socketChannel.read(in); - out.limit(in.position()); - return len; + final int bytesRead = socketChannel.read(socketIn); + entryOut.readLimit(socketIn.position()); + return bytesRead; } /** * reads entries from the buffer till empty - * - * @param attached - * @param key - * @throws InterruptedException */ void entriesFromBuffer(@NotNull Attached attached, @NotNull SelectionKey key) { int entriesRead = 0; try { for (; ; entriesRead++) { - out.limit(in.position()); + entryOut.readLimit(socketIn.position()); // its set to MIN_VALUE when it should be read again if (state == NOT_SET) { - if (out.remaining() < SIZE_OF_SIZE + 1) + if (entryOut.readRemaining() < SIZE_OF_SIZE + 1) return; // state is used for heartbeat - state = out.readByte(); - sizeInBytes = out.readInt(); + state = entryOut.readByte(); + sizeInBytes = entryOut.readInt(); assert sizeInBytes >= 0; @@ -1373,7 +1346,7 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme // size of the buffer long requiredSize = sizeInBytes + SIZE_OF_SIZE + 1 + SIZE_OF_BOOTSTRAP_TIMESTAMP; - if (out.capacity() < requiredSize) { + if (entryOut.capacity() < requiredSize) { attached.entryReader.resizeBuffer(requiredSize + HEADROOM); } @@ -1384,21 +1357,21 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme } } - if (out.remaining() < sizeInBytes) { + if (entryOut.readRemaining() < sizeInBytes) { return; } - final long nextEntryPos = out.position() + sizeInBytes; + final long nextEntryPos = entryOut.readPosition() + sizeInBytes; assert nextEntryPos > 0; - final long limit = out.limit(); - out.limit(nextEntryPos); + final long limit = entryOut.readLimit(); + entryOut.readLimit(nextEntryPos); - externalizable.readExternalEntry(out); + externalizable.readExternalEntry(entryOut); - out.limit(limit); + entryOut.readLimit(limit); // skip onto the next entry - out.position(nextEntryPos); + entryOut.readPosition(nextEntryPos); state = NOT_SET; sizeInBytes = 0; @@ -1410,36 +1383,36 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme } /** - * compacts the buffer and updates the {@code in} and {@code out} accordingly + * compacts the buffer and updates the {@code socketIn} and {@code entryOut} accordingly */ private void compactBuffer() { // the maxEntrySizeBytes used here may not be the maximum size of the entry in its // serialized form however, its only use as an indication that the buffer is becoming // full and should be compacted the buffer can be compacted at any time - if (in.position() == 0 || in.remaining() > largestEntrySoFar) + if (socketIn.position() == 0 || socketIn.remaining() > largestEntrySoFar) return; - in.limit(in.position()); - assert out.position() < Integer.MAX_VALUE; - in.position((int) out.position()); + socketIn.limit(socketIn.position()); + assert entryOut.readPosition() < Integer.MAX_VALUE; + socketIn.position((int) entryOut.readPosition()); - in.compact(); - out.position(0); + socketIn.compact(); + entryOut.readPosition(0); } /** * @return the identifier or -1 if unsuccessful */ byte identifierFromBuffer() { - return (out.remaining() >= 1) ? out.readByte() : Byte.MIN_VALUE; + return (entryOut.readRemaining() >= 1) ? entryOut.readByte() : Byte.MIN_VALUE; } /** * @return the timestamp or -1 if unsuccessful */ long remoteBootstrapTimestamp() { - if (out.remaining() >= 8) - return out.readLong(); + if (entryOut.readRemaining() >= 8) + return entryOut.readLong(); else return Long.MIN_VALUE; } @@ -1448,17 +1421,20 @@ public final class TcpReplicator extends AbstractChannelReplicator impleme * @return the timestamp or -1 if unsuccessful */ String readRemoteServerVersion() { - if (out.remaining() >= 64) { - char[] chars = new char[64]; - out.readFully(chars, 0, chars.length); - return new String(chars).trim(); + if (entryOut.readRemaining() >= 64) { + ByteBuffer bytes = ByteBuffer.allocate(64); + entryOut.read(bytes); + if (bytes.flip().remaining() != 64) + throw new AssertionError(); + CharBuffer version = StandardCharsets.US_ASCII.decode(bytes); + return version.toString().trim(); } else return null; } public long readRemoteHeartbeatIntervalFromBuffer() { - return (out.remaining() >= 8) ? out.readLong() : Long.MIN_VALUE; + return (entryOut.readRemaining() >= 8) ? entryOut.readLong() : Long.MIN_VALUE; } } } diff --git a/src/main/java/net/openhft/chronicle/map/UdpReplicator.java b/src/main/java/net/openhft/chronicle/map/UdpReplicator.java index 7a0d6b87e..c22067ef0 100644 --- a/src/main/java/net/openhft/chronicle/map/UdpReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/UdpReplicator.java @@ -16,8 +16,8 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.replication.UdpTransportConfig; -import net.openhft.lang.io.ByteBufferBytes; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,8 +52,7 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi setReader(new UdpSocketChannelEntryReader(replicationConfig.udpBufferSize(), entryExternalizable)); setWriter(new UdpSocketChannelEntryWriter(replicationConfig.udpBufferSize(), - entryExternalizable, - modificationIterator, this, new Replicators.OutBuffer(UPD_BUFFER_SIZE))); + entryExternalizable, modificationIterator, this, UPD_BUFFER_SIZE)); start(); } @@ -61,8 +60,8 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi private class UdpSocketChannelEntryReader implements EntryReader { private final Replica.EntryExternalizable externalizable; - private final ByteBuffer in; - private final ByteBufferBytes out; + private final ByteBuffer socketIn; + private final Bytes entryOut; /** * @param serializedEntrySize the maximum size of an entry include the meta data @@ -71,11 +70,11 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi UdpSocketChannelEntryReader(final int serializedEntrySize, @NotNull final Replica.EntryExternalizable externalizable) { // we make the buffer twice as large just to give ourselves headroom - in = ByteBuffer.allocateDirect(serializedEntrySize * 2); + socketIn = ByteBuffer.allocateDirect(serializedEntrySize * 2); this.externalizable = externalizable; - out = new ByteBufferBytes(in); - out.limit(0); - in.clear(); + entryOut = Bytes.wrapForRead(socketIn.slice()); + entryOut.readLimit(0); + socketIn.clear(); } /** @@ -88,30 +87,30 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi public void readAll(@NotNull final DatagramChannel socketChannel) throws IOException, InterruptedException { - out.clear(); - in.clear(); + entryOut.clear(); + socketIn.clear(); - socketChannel.receive(in); + socketChannel.receive(socketIn); - final int bytesRead = in.position(); + final int bytesRead = socketIn.position(); if (bytesRead < SIZE_OF_SIZE + SIZE_OF_SIZE) return; - out.limit(in.position()); + entryOut.readLimit(socketIn.position()); - final int invertedSize = out.readInt(); - final int size = out.readInt(); + final int invertedSize = entryOut.readInt(); + final int size = entryOut.readInt(); // check the the first 4 bytes are the inverted len followed by the len // we do this to check that this is a valid start of entry, otherwise we throw it away if (~size != invertedSize) return; - if (out.remaining() != size) + if (entryOut.readRemaining() != size) return; - externalizable.readExternalEntry(out); + externalizable.readExternalEntry(entryOut); } } @@ -120,16 +119,16 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi private final EntryCallback entryCallback; private final UdpChannelReplicator udpReplicator; - private final Replicators.OutBuffer outBuffer; + private final Bytes entryIn; private Replica.ModificationIterator modificationIterator; UdpSocketChannelEntryWriter(final int updBufferSize, @NotNull final Replica.EntryExternalizable externalizable, @NotNull final Replica.ModificationIterator modificationIterator, - UdpChannelReplicator udpReplicator, Replicators.OutBuffer outBuffer) { + UdpChannelReplicator udpReplicator, int udpBufferSize) { this.udpReplicator = udpReplicator; - this.outBuffer = outBuffer; + this.entryIn = Bytes.elasticByteBuffer(udpBufferSize); // we make the buffer twice as large just to give ourselves headroom entryCallback = new EntryCallback(externalizable, updBufferSize); @@ -155,12 +154,12 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi public int writeAll(@NotNull final DatagramChannel socketChannel) throws InterruptedException, IOException { - final ByteBufferBytes in = outBuffer.in(); - final ByteBuffer out = outBuffer.out(); + final Bytes in = entryIn; + final ByteBuffer out = entryIn.underlyingObject(); out.clear(); in.clear(); - in.skip(SIZE_OF_SIZE); + in.writeSkip(SIZE_OF_SIZE); final boolean wasDataRead = modificationIterator.nextEntry(entryCallback, 0); @@ -170,8 +169,8 @@ final class UdpReplicator extends UdpChannelReplicator implements Replica.Modifi } // we'll write the size inverted at the start - in.writeShort(0, ~(in.readUnsignedShort(SIZE_OF_SIZE))); - out.limit((int) in.position()); + in.writeShort(0, (short) ~(in.readUnsignedShort(SIZE_OF_SIZE))); + out.limit((int) in.writePosition()); return socketChannel.write(out); } diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 870eca3d8..43423f0af 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -16,26 +16,21 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.VanillaChronicleHash; import net.openhft.chronicle.hash.impl.stage.hash.ChainingInterface; -import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.hash.serialization.internal.MetaProvider; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.hash.serialization.SizedReader; +import net.openhft.chronicle.hash.serialization.impl.SerializationBuilder; import net.openhft.chronicle.map.impl.*; import net.openhft.chronicle.map.impl.CompiledMapIterationContext; import net.openhft.chronicle.map.impl.CompiledMapQueryContext; import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; +import net.openhft.chronicle.values.Values; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.ObjectInputStream; @@ -44,37 +39,28 @@ import java.util.function.BiFunction; import java.util.function.Function; import static net.openhft.chronicle.map.ChronicleMapBuilder.greatestCommonDivisor; +import static net.openhft.chronicle.values.ValueModel.$$NATIVE; -public class VanillaChronicleMap, - V, VI, MVI extends MetaBytesInterop, R> - extends VanillaChronicleHash, MapSegmentContext, +public class VanillaChronicleMap + extends VanillaChronicleHash, MapSegmentContext, ExternalMapQueryContext> - implements AbstractChronicleMap { + implements AbstractChronicleMap { - private static final Logger LOG = LoggerFactory.getLogger(VanillaChronicleMap.class); - - private static final long serialVersionUID = 3L; + private static final long serialVersionUID = 4L; ///////////////////////////////////////////////// // Value Data model final Class vClass; final Class nativeValueClass; public final SizeMarshaller valueSizeMarshaller; - public final BytesReader originalValueReader; - public final VI originalValueInterop; - public final MVI originalMetaValueInterop; - public final MetaProvider metaValueInteropProvider; - - public final ConstantValueProvider constantValueProvider; + public final SizedReader originalValueReader; + public final DataAccess originalValueDataAccess; public final boolean constantlySizedEntry; - public transient Provider> valueReaderProvider; - public transient Provider valueInteropProvider; - ///////////////////////////////////////////////// // Memory management and dependent fields - public final Alignment alignment; + public final int alignment; public final int worstAlignment; public final boolean couldNotDetermineAlignmentBeforeAllocation; @@ -94,13 +80,13 @@ public class VanillaChronicleMap builder) throws IOException { super(builder); SerializationBuilder valueBuilder = builder.valueBuilder; - vClass = valueBuilder.eClass; - if (vClass.getName().endsWith("$$Native")) { + vClass = valueBuilder.tClass; + if (vClass.getName().endsWith($$NATIVE)) { nativeValueClass = vClass; } else if (vClass.isInterface()) { Class nativeValueClass = null; try { - nativeValueClass = DataValueClasses.directClassFor(vClass); + nativeValueClass = Values.nativeClassFor(vClass); } catch (Exception e) { // fall through } @@ -110,18 +96,13 @@ public class VanillaChronicleMap valueReader = valueReaderProvider.get(copies, originalValueReader); - constantValueProvider.initTransients(valueReader); - } cxt = new ThreadLocal<>(); } @@ -195,8 +168,7 @@ public class VanillaChronicleMap 0) + entry.readSkip(skip); + } + + public static long alignAddr(long addr, int alignment) { + return (addr + alignment - 1) & ~(alignment - 1); + } + private ChainingInterface q() { ChainingInterface queryContext; queryContext = cxt.get(); @@ -320,8 +303,7 @@ public class VanillaChronicleMap queryContext(Object key) { checkKey(key); QueryContextInterface q = mapContext(); - q.inputKeyInstanceValue().initKey((K) key); - q.initInputKey(q.inputKeyInstanceValue()); + q.initInputKey(q.inputKeyDataAccess().getData((K) key)); return q; } @@ -374,8 +356,7 @@ public class VanillaChronicleMap q = queryContext(key)) { - q.inputValueInstanceValue().initValue(value); - methods.putIfAbsent(q, q.inputValueInstanceValue(), q.defaultReturnValue()); + methods.putIfAbsent(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } } @@ -386,8 +367,7 @@ public class VanillaChronicleMap q = queryContext(key)) { - q.inputValueInstanceValue().initValue(v); - return methods.remove(q, q.inputValueInstanceValue()); + return methods.remove(q, q.inputValueDataAccess().getData(v)); } } @@ -396,8 +376,8 @@ public class VanillaChronicleMap q = queryContext(key)) { - q.inputValueInstanceValue().initValue(oldValue); - return methods.replace(q, q.inputValueInstanceValue(), q.wrapValueAsData(newValue)); + return methods.replace( + q, q.inputValueDataAccess().getData(oldValue), q.wrapValueAsData(newValue)); } } @@ -405,8 +385,7 @@ public class VanillaChronicleMap q = queryContext(key)) { - q.inputValueInstanceValue().initValue(value); - methods.replace(q, q.inputValueInstanceValue(), q.defaultReturnValue()); + methods.replace(q, q.inputValueDataAccess().getData(value), q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } } @@ -422,10 +401,10 @@ public class VanillaChronicleMap q = queryContext(key)) { - q.inputValueInstanceValue().initValue(value); + Data valueData = q.inputValueDataAccess().getData(value); InstanceReturnValue returnValue = putReturnsNull ? NullReturnValue.get() : q.defaultReturnValue(); - methods.put(q, q.inputValueInstanceValue(), returnValue); + methods.put(q, valueData, returnValue); return returnValue.returnValue(); } } @@ -444,8 +423,7 @@ public class VanillaChronicleMap remappingFunction) { try (QueryContextInterface q = queryContext(key)) { - q.inputValueInstanceValue().initValue(value); - methods.merge(q, q.inputValueInstanceValue(), remappingFunction, + methods.merge(q, q.inputValueDataAccess().getData(value), remappingFunction, q.defaultReturnValue()); return q.defaultReturnValue().returnValue(); } diff --git a/src/main/java/net/openhft/chronicle/map/WriterWithSize.java b/src/main/java/net/openhft/chronicle/map/WriterWithSize.java deleted file mode 100644 index 1d2b115ff..000000000 --- a/src/main/java/net/openhft/chronicle/map/WriterWithSize.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.chronicle.hash.serialization.internal.SerializationBuilder; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter; -import net.openhft.chronicle.hash.serialization.internal.MetaProvider; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.threadlocal.Provider; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.Nullable; - -import java.nio.BufferOverflowException; - -final class WriterWithSize { - private final SizeMarshaller sizeMarshaller; - private final Object originalWriter; - private final Provider writerProvider; - private final MetaBytesInterop originalMetaWriter; - private final MetaProvider metaWriterProvider; - private final BufferResizer bufferResizer; - - WriterWithSize(SerializationBuilder serializationBuilder, - @Nullable BufferResizer bufferResizer) { - this.bufferResizer = bufferResizer; - sizeMarshaller = serializationBuilder.sizeMarshaller(); - originalWriter = serializationBuilder.interop(); - writerProvider = Provider.of((Class) originalWriter.getClass()); - originalMetaWriter = serializationBuilder.metaInterop(); - metaWriterProvider = serializationBuilder.metaInteropProvider(); - } - - ThreadLocalCopies getCopies(ThreadLocalCopies copies) { - copies = writerProvider.getCopies(copies); - return metaWriterProvider.getCopies(copies); - } - - public ThreadLocalCopies write(Bytes out, T t, @Nullable ThreadLocalCopies copies) { - copies = writerProvider.getCopies(copies); - Object writer = writerProvider.get(copies, originalWriter); - copies = metaWriterProvider.getCopies(copies); - MetaBytesWriter metaWriter = metaWriterProvider.get( - copies, originalMetaWriter, writer, t, false); - long size = metaWriter.size(writer, t); - if (bufferResizer != null) - out = resizeIfRequired(out, size); - sizeMarshaller.writeSize(out, size); - metaWriter.write(writer, out, t); - return copies; - } - - private Bytes resizeIfRequired(Bytes out, long size) { - if (out.remaining() < size + 8) { - long newCapacity = out.capacity() + (size - out.remaining()) + 8; - if (newCapacity > Integer.MAX_VALUE) - throw new BufferOverflowException(); - return bufferResizer.resizeBuffer((int) newCapacity); - } - return out; - } - - - public ThreadLocalCopies writeNullable(Bytes out, T t, @Nullable ThreadLocalCopies copies) { - out.writeBoolean(t == null); - if (t == null) - return copies; - return write(out, t, copies); - } - - public Object writerForLoop(@Nullable ThreadLocalCopies copies) { - copies = writerProvider.getCopies(copies); - return writerProvider.get(copies, originalWriter); - } - - public ThreadLocalCopies writeInLoop(Bytes out, T t, Object writer, - @Nullable ThreadLocalCopies copies) { - copies = metaWriterProvider.getCopies(copies); - MetaBytesWriter metaWriter = metaWriterProvider.get( - copies, originalMetaWriter, writer, t, false); - long size = metaWriter.size(writer, t); - if (bufferResizer != null) - out = resizeIfRequired(out, size); - sizeMarshaller.writeSize(out, size); - metaWriter.write(writer, out, t); - return copies; - } - - public ThreadLocalCopies writeNullableInLoop(Bytes out, T t, Object writer, - @Nullable ThreadLocalCopies copies) { - out.writeBoolean(t == null); - if (t == null) - return copies; - return writeInLoop(out, t, writer, copies); - } -} - -interface BufferResizer { - - /** - * @param newCapacity - * @return the newly resize buffer - */ - public Bytes resizeBuffer(int newCapacity); -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java index dd03d40f1..8c73913e2 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java +++ b/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java @@ -21,13 +21,12 @@ import net.openhft.chronicle.hash.impl.stage.entry.*; import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; -import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; import net.openhft.chronicle.hash.impl.stage.iter.IterationAlloc; import net.openhft.chronicle.hash.impl.stage.iter.IterationKeyHashCode; import net.openhft.chronicle.hash.impl.stage.iter.IterationSegmentStages; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceDataHolder; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.chronicle.map.impl.stage.iter.IterationCheckOnEachPublicOperation; import net.openhft.chronicle.map.impl.stage.iter.MapSegmentIteration; @@ -42,7 +41,6 @@ import net.openhft.sg.Staged; @Context(topLevel = { CompilationAnchor.class, OwnerThreadHolder.class, - ThreadLocalCopiesHolder.class, VanillaChronicleMapHolderImpl.class, LogHolder.class, @@ -72,7 +70,7 @@ import net.openhft.sg.Staged; EntryKeyBytesData.class, EntryValueBytesData.class, - WrappedValueInstanceData.class, + WrappedValueInstanceDataHolder.class, HashKeyCrc32PayloadChecksumStrategy.class, }) diff --git a/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java index 63d110fcc..bf4756133 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java +++ b/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java @@ -17,21 +17,14 @@ package net.openhft.chronicle.map.impl; import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; -import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; -import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; import net.openhft.chronicle.hash.impl.stage.entry.*; import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; -import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; import net.openhft.chronicle.hash.impl.stage.query.*; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.bytes.InputFirstValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.bytes.InputSecondValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; -import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceDataHolder; import net.openhft.chronicle.map.impl.stage.map.*; import net.openhft.chronicle.map.impl.stage.query.*; import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; @@ -43,7 +36,6 @@ import net.openhft.sg.Staged; @Context(topLevel = { CompilationAnchor.class, OwnerThreadHolder.class, - ThreadLocalCopiesHolder.class, LogHolder.class, @@ -68,9 +60,6 @@ import net.openhft.sg.Staged; ValueBytesInterop.class, MapAbsentHolder.class, - HashInputBytes.class, - MapInputBytesValues.class, - QueryAlloc.class, }, nested = { @@ -81,19 +70,14 @@ nested = { EntryKeyBytesData.class, EntryValueBytesData.class, - InputKeyInstanceData.class, - InputValueInstanceData.class, - - InputKeyBytesData.class, - InputFirstValueBytesData.class, - InputSecondValueBytesData.class, - - WrappedValueInstanceData.class, + WrappedValueInstanceDataHolder.class, AcquireHandle.class, DefaultReturnValue.class, UsingReturnValue.class, HashKeyCrc32PayloadChecksumStrategy.class, + + DummyValueZeroData.class, }) public class MapQueryContext { } diff --git a/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java b/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java index 691944312..0d1a1a592 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java +++ b/src/main/java/net/openhft/chronicle/map/impl/QueryContextInterface.java @@ -18,9 +18,8 @@ package net.openhft.chronicle.map.impl; import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.map.ExternalMapQueryContext; -import net.openhft.chronicle.map.impl.data.instance.ValueInitializableData; import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; import net.openhft.chronicle.map.impl.ret.UsableReturnValue; @@ -28,13 +27,13 @@ public interface QueryContextInterface extends ExternalMapQueryContext< void initInputKey(Data inputKey); - KeyInitableData inputKeyInstanceValue(); + DataAccess inputKeyDataAccess(); InstanceReturnValue defaultReturnValue(); UsableReturnValue usingReturnValue(); - ValueInitializableData inputValueInstanceValue(); + DataAccess inputValueDataAccess(); Closeable acquireHandle(); diff --git a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedChronicleMapHolder.java b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedChronicleMapHolder.java index 30346e4fc..438e9bae2 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedChronicleMapHolder.java +++ b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedChronicleMapHolder.java @@ -16,13 +16,10 @@ package net.openhft.chronicle.map.impl; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.ReplicatedChronicleMap; -public interface ReplicatedChronicleMapHolder, - V, VI, MVI extends MetaBytesInterop, R> - extends VanillaChronicleMapHolder { +public interface ReplicatedChronicleMapHolder extends VanillaChronicleMapHolder { @Override - ReplicatedChronicleMap m(); + ReplicatedChronicleMap m(); } diff --git a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java index 5f53b05a0..7345c05bd 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java +++ b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java @@ -21,14 +21,13 @@ import net.openhft.chronicle.hash.impl.stage.entry.*; import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; -import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; import net.openhft.chronicle.hash.impl.stage.iter.IterationAlloc; import net.openhft.chronicle.hash.impl.stage.iter.IterationKeyHashCode; import net.openhft.chronicle.hash.impl.stage.iter.IterationSegmentStages; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceDataHolder; import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; import net.openhft.chronicle.map.impl.stage.iter.IterationCheckOnEachPublicOperation; import net.openhft.chronicle.map.impl.stage.iter.ReplicatedMapAbsentDelegatingForIteration; @@ -43,7 +42,6 @@ import net.openhft.sg.Staged; @Context(topLevel = { CompilationAnchor.class, OwnerThreadHolder.class, - ThreadLocalCopiesHolder.class, ReplicatedChronicleMapHolderImpl.class, LogHolder.class, @@ -76,7 +74,7 @@ import net.openhft.sg.Staged; EntryKeyBytesData.class, EntryValueBytesData.class, - WrappedValueInstanceData.class, + WrappedValueInstanceDataHolder.class, DummyValueZeroData.class, diff --git a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java index 3e6457c8d..9be94aba6 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java +++ b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java @@ -17,27 +17,25 @@ package net.openhft.chronicle.map.impl; import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; -import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; -import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; import net.openhft.chronicle.hash.impl.stage.entry.*; import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; -import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; -import net.openhft.chronicle.hash.impl.stage.query.*; +import net.openhft.chronicle.hash.impl.stage.query.KeySearch; +import net.openhft.chronicle.hash.impl.stage.query.QueryHashLookupSearch; +import net.openhft.chronicle.hash.impl.stage.query.QuerySegmentStages; +import net.openhft.chronicle.hash.impl.stage.query.SearchAllocatedChunks; import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; -import net.openhft.chronicle.map.impl.stage.data.bytes.*; -import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.ReplicatedInputKeyBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.ReplicatedInputValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceDataHolder; import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; -import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; import net.openhft.chronicle.map.impl.stage.map.*; import net.openhft.chronicle.map.impl.stage.query.*; import net.openhft.chronicle.map.impl.stage.replication.ReplicatedQueryAlloc; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; -import net.openhft.chronicle.map.impl.stage.ret.BytesReturnValue; import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; import net.openhft.sg.Context; @@ -47,7 +45,6 @@ import net.openhft.sg.Staged; @Context(topLevel = { CompilationAnchor.class, OwnerThreadHolder.class, - ThreadLocalCopiesHolder.class, LogHolder.class, @@ -74,9 +71,6 @@ import net.openhft.sg.Staged; ReplicationUpdate.class, ReplicatedInput.class, - HashInputBytes.class, - MapInputBytesValues.class, - ReplicatedQueryAlloc.class, }, nested = { @@ -87,15 +81,7 @@ nested = { EntryKeyBytesData.class, EntryValueBytesData.class, - InputKeyInstanceData.class, - InputValueInstanceData.class, - BytesReturnValue.class, - - InputKeyBytesData.class, - InputFirstValueBytesData.class, - InputSecondValueBytesData.class, - - WrappedValueInstanceData.class, + WrappedValueInstanceDataHolder.class, AcquireHandle.class, DefaultReturnValue.class, UsingReturnValue.class, diff --git a/src/main/java/net/openhft/chronicle/map/impl/VanillaChronicleMapHolder.java b/src/main/java/net/openhft/chronicle/map/impl/VanillaChronicleMapHolder.java index 9484ee13a..539cc429e 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/VanillaChronicleMapHolder.java +++ b/src/main/java/net/openhft/chronicle/map/impl/VanillaChronicleMapHolder.java @@ -18,18 +18,15 @@ package net.openhft.chronicle.map.impl; import net.openhft.chronicle.hash.impl.VanillaChronicleHash; import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.VanillaChronicleMap; -public interface VanillaChronicleMapHolder, - V, VI, MVI extends MetaBytesInterop, R> - extends VanillaChronicleHashHolder { +public interface VanillaChronicleMapHolder extends VanillaChronicleHashHolder { - VanillaChronicleMap m(); + VanillaChronicleMap m(); @Override - default VanillaChronicleHash h() { + default VanillaChronicleHash h() { return m(); } diff --git a/src/main/java/net/openhft/chronicle/map/impl/data/instance/ValueInitializableData.java b/src/main/java/net/openhft/chronicle/map/impl/data/instance/ValueInitializableData.java deleted file mode 100644 index 706e2f685..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/data/instance/ValueInitializableData.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.impl.data.instance; - -import net.openhft.chronicle.hash.Data; - -public interface ValueInitializableData extends Data { - - void initValue(V value); -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/ret/UsableReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/ret/UsableReturnValue.java index 5d74ac34e..9dceb048e 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/ret/UsableReturnValue.java +++ b/src/main/java/net/openhft/chronicle/map/impl/ret/UsableReturnValue.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map.impl.ret; public interface UsableReturnValue extends InstanceReturnValue { - Object USING_RETURN_VALUE_UNINT = new Object(); + Object USING_RETURN_VALUE_UNINIT = new Object(); void initUsingReturnValue(V usingValue); } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java index 0b74db8cc..1db9db5c6 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java @@ -16,39 +16,69 @@ package net.openhft.chronicle.map.impl.stage.data; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @Staged public class DummyValueZeroData extends AbstractData { - @StageRef - VanillaChronicleMapHolder mh; + + @StageRef VanillaChronicleMapHolder mh; + @StageRef ValueBytesInterop vi; + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + + private final Bytes zeroBytes = ZeroBytesStore.INSTANCE.bytesForRead(); @Override public RandomDataInput bytes() { - return ZeroRandomDataInput.INSTANCE; + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return ZeroBytesStore.INSTANCE; } @Override public long offset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); return 0; } @Override public long size() { - return mh.m().valueSizeMarshaller.minEncodableSize(); + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return Math.max(0, mh.m().valueSizeMarshaller.minStorableSize()); } @Override public V get() { - throw new UnsupportedOperationException(); + checkOnEachPublicOperation.checkOnEachPublicOperation(); + // Not optimized and creates garbage, because this isn't the primary + // use case. Zero data should only be used in bytes form + try { + return getUsing(null); + } catch (Exception e) { + throw zeroReadException(e); + } } @Override - public V getUsing(V usingInstance) { - throw new UnsupportedOperationException(); + public V getUsing(V using) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + zeroBytes.readPosition(0); + try { + return vi.valueReader.read(zeroBytes, size(), using); + } catch (Exception e) { + throw zeroReadException(e); + } + } + + private IllegalStateException zeroReadException(Exception cause) { + return new IllegalStateException("Most probable cause of this exception - zero bytes of\n" + + "the minimum positive encoding length, supported by the specified or default\n" + + "valueSizeMarshaller() is not correct serialized form of any value. You should\n" + + "configure defaultValueProvider() in ChronicleMapBuilder"); } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroRandomDataInput.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java similarity index 52% rename from src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroRandomDataInput.java rename to src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java index 011693fb6..54311f394 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroRandomDataInput.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/ZeroBytesStore.java @@ -16,14 +16,16 @@ package net.openhft.chronicle.map.impl.stage.data; -import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesStore; import net.openhft.chronicle.bytes.IORuntimeException; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.core.OS; +import org.jetbrains.annotations.Nullable; import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; -public enum ZeroRandomDataInput implements RandomDataInput { +public enum ZeroBytesStore implements BytesStore { INSTANCE; @Override @@ -62,8 +64,8 @@ public enum ZeroRandomDataInput implements RandomDataInput { } @Override - public long realCapacity() { - return Long.MAX_VALUE; + public ZeroBytesStore copy() { + throw new UnsupportedOperationException(); } @Override @@ -71,21 +73,17 @@ public enum ZeroRandomDataInput implements RandomDataInput { return Long.MAX_VALUE; } + @Nullable + @Override + public Void underlyingObject() { + throw new UnsupportedOperationException(); + } + @Override public long address(long offset) throws UnsupportedOperationException { return offset; } - @Override - public Bytes bytesForRead() { - throw new UnsupportedOperationException(); - } - - @Override - public Bytes bytesForWrite() { - throw new UnsupportedOperationException(); - } - @Override public boolean compareAndSwapInt(long offset, int expected, int value) throws BufferOverflowException, IllegalArgumentException, IORuntimeException { @@ -110,4 +108,84 @@ public enum ZeroRandomDataInput implements RandomDataInput { public long refCount() { return 0; } + + @Override + public ZeroBytesStore writeByte(long l, byte b) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeShort(long l, short i) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeInt(long l, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeOrderedInt(long l, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeLong(long l, long l1) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeOrderedLong(long l, long l1) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeFloat(long l, float v) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeDouble(long l, double v) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeVolatileByte(long l, byte b) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeVolatileShort(long l, short i) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeVolatileInt(long l, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore writeVolatileLong(long l, long l1) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore write(long l, byte[] bytes, int i, int i1) { + throw new UnsupportedOperationException(); + } + + @Override + public void write(long l, ByteBuffer byteBuffer, int i, int i1) { + throw new UnsupportedOperationException(); + } + + @Override + public ZeroBytesStore write(long l, RandomDataInput randomDataInput, long l1, long l2) { + throw new UnsupportedOperationException(); + } + + @Override + public void nativeWrite(long l, long l1, long l2) { + throw new UnsupportedOperationException(); + } } \ No newline at end of file diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java index 8ab2ed483..ff9d7a7d5 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java @@ -16,10 +16,13 @@ package net.openhft.chronicle.map.impl.stage.data.bytes; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.impl.util.CharSequences; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; import net.openhft.sg.Stage; @@ -28,13 +31,15 @@ import net.openhft.sg.Staged; @Staged public class EntryValueBytesData extends AbstractData { - - @StageRef ValueBytesInterop vi; + + @StageRef VanillaChronicleMapHolder mh; + @StageRef ValueBytesInterop vi; @StageRef SegmentStages s; @StageRef MapEntryStages entry; @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; - @Stage("CachedEntryValue") private V cachedEntryValue; + @Stage("CachedEntryValue") private V cachedEntryValue = + mh.m().valueClass() == CharSequence.class ? (V) new StringBuilder() : null; @Stage("CachedEntryValue") private boolean cachedEntryValueRead = false; private void initCachedEntryValue() { @@ -42,6 +47,14 @@ public class EntryValueBytesData extends AbstractData { cachedEntryValueRead = true; } + public boolean cachedEntryValueInit() { + return cachedEntryValueRead; + } + + public void closeCachedEntryValue() { + cachedEntryValueRead = false; + } + @Override public RandomDataInput bytes() { checkOnEachPublicOperation.checkOnEachPublicOperation(); @@ -67,13 +80,14 @@ public class EntryValueBytesData extends AbstractData { } @Override - public V getUsing(V usingValue) { + public V getUsing(V using) { checkOnEachPublicOperation.checkOnEachPublicOperation(); - return innerGetUsing(usingValue); + return innerGetUsing(using); } private V innerGetUsing(V usingValue) { - s.segmentBytes.position(entry.valueOffset); - return vi.valueReader.read(s.segmentBytes, size(), usingValue); + Bytes segmentBytes = s.segmentBytesForRead(); + segmentBytes.readPosition(entry.valueOffset); + return vi.valueReader.read(segmentBytes, size(), usingValue); } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java deleted file mode 100644 index b82721b1a..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.impl.stage.data.bytes; - -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; -import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; -import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public class InputFirstValueBytesData extends AbstractData { - - @StageRef HashInputBytes in; - @StageRef MapInputBytesValues values; - @StageRef ValueBytesInterop vi; - - @Stage("CachedBytesInputFirstValue") private V cachedBytesInputFirstValue; - @Stage("CachedBytesInputFirstValue") private boolean cachedBytesInputFirstValueRead = false; - - private void initCachedBytesInputFirstValue() { - cachedBytesInputFirstValue = getUsing(cachedBytesInputFirstValue); - cachedBytesInputFirstValueRead = true; - } - - @Override - public RandomDataInput bytes() { - return in.inputStore; - } - - @Override - public long offset() { - return values.firstInputValueOffset; - } - - @Override - public long size() { - return values.firstInputValueSize; - } - - @Override - public V get() { - return cachedBytesInputFirstValue; - } - - @Override - public V getUsing(V usingValue) { - in.inputBytes.position(values.firstInputValueOffset); - return vi.valueReader.read(in.inputBytes, size(), usingValue); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java deleted file mode 100644 index eade7c58f..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.impl.stage.data.bytes; - -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; -import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; -import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public class InputSecondValueBytesData extends AbstractData { - - @StageRef HashInputBytes in; - @StageRef MapInputBytesValues values; - @StageRef ValueBytesInterop vi; - - @Stage("CachedBytesInputSecondValue") private V cachedBytesInputSecondValue; - @Stage("CachedBytesInputSecondValue") private boolean cachedBytesInputSecondValueRead = false; - - private void initCachedBytesInputSecondValue() { - cachedBytesInputSecondValue = getUsing(cachedBytesInputSecondValue); - cachedBytesInputSecondValueRead = true; - } - - @Override - public RandomDataInput bytes() { - return in.inputStore; - } - - @Override - public long offset() { - return values.secondInputValueOffset; - } - - @Override - public long size() { - return values.secondInputValueSize; - } - - @Override - public V get() { - return cachedBytesInputSecondValue; - } - - @Override - public V getUsing(V usingValue) { - in.inputBytes.position(values.secondInputValueOffset); - return vi.valueReader.read(in.inputBytes, size(), usingValue); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java index 517d3230c..dab33ea18 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java @@ -16,11 +16,11 @@ package net.openhft.chronicle.map.impl.stage.data.bytes; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; -import net.openhft.lang.io.Bytes; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -29,7 +29,7 @@ import net.openhft.sg.Staged; @Staged public class ReplicatedInputKeyBytesData extends AbstractData { @StageRef ReplicatedInput in; - @StageRef KeyBytesInterop ki; + @StageRef KeyBytesInterop ki; @Stage("CachedBytesReplicatedInputKey") private K cachedBytesReplicatedInputKey; @Stage("CachedBytesReplicatedInputKey") private boolean cachedBytesReplicatedInputKeyRead = @@ -42,7 +42,7 @@ public class ReplicatedInputKeyBytesData extends AbstractData { @Override public RandomDataInput bytes() { - return in.replicatedInputStore; + return in.replicatedInputBytes; } @Override @@ -61,9 +61,9 @@ public class ReplicatedInputKeyBytesData extends AbstractData { } @Override - public K getUsing(K usingKey) { + public K getUsing(K using) { Bytes inputBytes = in.replicatedInputBytes; - inputBytes.position(in.riKeyOffset); - return ki.keyReader.read(inputBytes, size(), usingKey); + inputBytes.readPosition(in.riKeyOffset); + return ki.keyReader.read(inputBytes, size(), using); } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java index 15bab525d..9158d9651 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java @@ -16,11 +16,11 @@ package net.openhft.chronicle.map.impl.stage.data.bytes; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.AbstractData; import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; -import net.openhft.lang.io.Bytes; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -29,7 +29,7 @@ import net.openhft.sg.Staged; @Staged public class ReplicatedInputValueBytesData extends AbstractData { @StageRef ReplicatedInput in; - @StageRef ValueBytesInterop ki; + @StageRef ValueBytesInterop vi; @Stage("CachedBytesReplicatedInputValue") private V cachedBytesReplicatedInputValue; @Stage("CachedBytesReplicatedInputValue") private boolean cachedBytesReplicatedInputValueRead = @@ -42,7 +42,7 @@ public class ReplicatedInputValueBytesData extends AbstractData { @Override public RandomDataInput bytes() { - return in.replicatedInputStore; + return in.replicatedInputBytes; } @Override @@ -61,9 +61,9 @@ public class ReplicatedInputValueBytesData extends AbstractData { } @Override - public V getUsing(V usingValue) { + public V getUsing(V using) { Bytes inputBytes = in.replicatedInputBytes; - inputBytes.position(in.riValueOffset); - return ki.valueReader.read(inputBytes, size(), usingValue); + inputBytes.readPosition(in.riValueOffset); + return vi.valueReader.read(inputBytes, size(), using); } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java deleted file mode 100644 index 6e58f24cf..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.impl.stage.data.instance; - -import net.openhft.chronicle.hash.impl.CopyingInstanceData; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.impl.data.instance.ValueInitializableData; -import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; -import net.openhft.lang.io.DirectBytes; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public abstract class InputValueInstanceData> - extends CopyingInstanceData implements ValueInitializableData { - - @StageRef ValueBytesInterop vi; - - private V value = null; - - @Override - public void initValue(V value) { - this.value = value; - } - - @Override - public V instance() { - return value; - } - - @Stage("Buffer") private DirectBytes buffer; - @Stage("Buffer") private boolean marshalled = false; - - private void initBuffer() { - MVI mvi = vi.valueMetaInterop(value); - long size = mvi.size(vi.valueInterop, value); - buffer = getBuffer(this.buffer, size); - mvi.write(vi.valueInterop, buffer, value); - buffer.flip(); - marshalled = true; - } - - @Override - public V getUsing(V usingValue) { - buffer.position(0); - return vi.valueReader.read(buffer, buffer.limit(), usingValue); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java similarity index 53% rename from src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java rename to src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java index 0541f5bfd..f6eea0a65 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceDataHolder.java @@ -16,24 +16,21 @@ package net.openhft.chronicle.map.impl.stage.data.instance; -import net.openhft.chronicle.hash.impl.CopyingInstanceData; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; -import net.openhft.lang.io.DirectBytes; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @Staged -public class WrappedValueInstanceData< - V, VI, MVI extends MetaBytesInterop> - extends CopyingInstanceData { +public class WrappedValueInstanceDataHolder { - @StageRef VanillaChronicleMapHolder mh; - @StageRef ValueBytesInterop vi; + @StageRef VanillaChronicleMapHolder mh; + + private final DataAccess wrappedValueDataAccess = mh.m().originalValueDataAccess.copy(); - private WrappedValueInstanceData next; + private WrappedValueInstanceDataHolder next; boolean nextInit() { return true; @@ -44,12 +41,12 @@ public class WrappedValueInstanceData< } @Stage("Next") - public WrappedValueInstanceData getUnusedWrappedValue() { + public WrappedValueInstanceDataHolder getUnusedWrappedValueHolder() { if (!valueInit()) return this; if (next == null) - next = new WrappedValueInstanceData<>(); - return next.getUnusedWrappedValue(); + next = new WrappedValueInstanceDataHolder<>(); + return next.getUnusedWrappedValueHolder(); } private V value; @@ -69,31 +66,14 @@ public class WrappedValueInstanceData< next.closeValue(); } - @Override - public V instance() { - return value; - } - - @Stage("Buffer") private DirectBytes buf; - @Stage("Buffer") private boolean marshalled = false; + public Data wrappedData = null; - private void initBuffer() { - MVI mvi = vi.valueMetaInterop(value); - long size = mvi.size(vi.valueInterop, value); - buf = getBuffer(this.buf, size); - mvi.write(vi.valueInterop, buf, value); - buf.flip(); - marshalled = true; + private void initWrappedData() { + wrappedData = wrappedValueDataAccess.getData(value); } - @Override - public DirectBytes buffer() { - return buf; - } - - @Override - public V getUsing(V usingValue) { - buf.position(0); - return vi.valueReader.read(buf, buf.limit(), usingValue); + private void closeWrappedData() { + wrappedData = null; + wrappedValueDataAccess.uninit(); } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java index 3a900bffb..b14c6d2a7 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java @@ -16,6 +16,9 @@ package net.openhft.chronicle.map.impl.stage.entry; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.NativeBytesStore; +import net.openhft.chronicle.bytes.RandomDataInput; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.CompactOffHeapLinearHashTable; import net.openhft.chronicle.hash.impl.stage.entry.AllocatedChunks; @@ -30,11 +33,13 @@ import net.openhft.sg.StageRef; import net.openhft.sg.Staged; import org.jetbrains.annotations.NotNull; +import static net.openhft.chronicle.map.VanillaChronicleMap.alignAddr; + @Staged public abstract class MapEntryStages extends HashEntryStages implements MapEntry { - @StageRef public VanillaChronicleMapHolder mh; + @StageRef public VanillaChronicleMapHolder mh; @StageRef public AllocatedChunks allocatedChunks; @StageRef KeySearch ks; @@ -51,23 +56,29 @@ public abstract class MapEntryStages extends HashEntryStages @Stage("ValueSize") public long valueSize = -1; @Stage("ValueSize") public long valueOffset; - @Stage("ValueSize") - private void countValueOffset() { - mh.m().alignment.alignPositionAddr(s.segmentBytes); - valueOffset = s.segmentBytes.position(); - } - void initValueSize(long valueSize) { this.valueSize = valueSize; - s.segmentBytes.position(valueSizeOffset); - mh.m().valueSizeMarshaller.writeSize(s.segmentBytes, valueSize); - countValueOffset(); + Bytes segmentBytes = s.segmentBytesForWrite(); + segmentBytes.writePosition(valueSizeOffset); + mh.m().valueSizeMarshaller.writeSize(segmentBytes, valueSize); + long currentPosition = segmentBytes.writePosition(); + long currentAddr = segmentBytes.address(currentPosition); + long skip = alignAddr(currentAddr, mh.m().alignment) - currentAddr; + if (skip > 0) + segmentBytes.writeSkip(skip); + valueOffset = segmentBytes.writePosition(); } void initValueSize() { - s.segmentBytes.position(valueSizeOffset); - valueSize = mh.m().readValueSize(s.segmentBytes); - countValueOffset(); + Bytes segmentBytes = s.segmentBytesForRead(); + segmentBytes.readPosition(valueSizeOffset); + valueSize = mh.m().readValueSize(segmentBytes); + long currentPosition = segmentBytes.readPosition(); + long currentAddr = segmentBytes.address(currentPosition); + long skip = alignAddr(currentAddr, mh.m().alignment) - currentAddr; + if (skip > 0) + segmentBytes.readSkip(skip); + valueOffset = segmentBytes.readPosition(); } void initValueSize_EqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { @@ -76,12 +87,24 @@ public abstract class MapEntryStages extends HashEntryStages } public void initValue(Data value) { - s.segmentBytes.position(valueSizeOffset); initValueSize(value.size()); writeValue(value); } public void writeValue(Data value) { + // In acquireContext(), replaceValue() is called for + // 1) executing custom replaceValue() logic, if defined, from configured MapEntryOperations + // 2) Update replication status (bits, timestamp) + // 3) update entry checksum + // but the actual entry replacement is not needed, if the value object is a flyweight over + // the off-heap bytes. This condition avoids in-place data copy. + // TODO would be nice to reduce scope of this check, i. e. check only when it could be + // true, and avoid when it surely false (fresh value put, relocating put etc.) + RandomDataInput valueBytes = value.bytes(); + if (valueBytes instanceof NativeBytesStore && + valueBytes.address(value.offset()) == s.segmentBS.address(valueOffset)) { + return; + } value.writeTo(s.segmentBS, valueOffset); } @@ -118,7 +141,7 @@ public abstract class MapEntryStages extends HashEntryStages } public long newSizeOfEverythingBeforeValue(Data newValue) { - return valueSizeOffset + mh.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()) - + return valueSizeOffset + mh.m().valueSizeMarshaller.storingLength(newValue.size()) - keySizeOffset; } @@ -129,9 +152,9 @@ public abstract class MapEntryStages extends HashEntryStages if (newValueSizeIsDifferent) { long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); long entryStartOffset = keySizeOffset; - VanillaChronicleMap m = mh.m(); - long newValueOffset = m.alignment.alignAddr( - entryStartOffset + newSizeOfEverythingBeforeValue); + VanillaChronicleMap m = mh.m(); + long newValueOffset = + alignAddr(entryStartOffset + newSizeOfEverythingBeforeValue, mh.m().alignment); long newEntrySize = newValueOffset + newValue.size() - entryStartOffset; int newSizeInChunks = m.inChunks(newEntrySize); newValueDoesNotFit: @@ -224,17 +247,17 @@ public abstract class MapEntryStages extends HashEntryStages public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { if (mh.m().constantlySizedEntry) { - return mh.m().alignment.alignAddr(sizeOfEverythingBeforeValue + valueSize); + return alignAddr(sizeOfEverythingBeforeValue + valueSize, mh.m().alignment); } else if (mh.m().couldNotDetermineAlignmentBeforeAllocation) { return sizeOfEverythingBeforeValue + mh.m().worstAlignment + valueSize; } else { - return mh.m().alignment.alignAddr(sizeOfEverythingBeforeValue) + valueSize; + return alignAddr(sizeOfEverythingBeforeValue, mh.m().alignment) + valueSize; } } long sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return mh.m().keySizeMarshaller.sizeEncodingSize(keySize) + keySize + - mh.m().valueSizeMarshaller.sizeEncodingSize(valueSize); + return mh.m().keySizeMarshaller.storingLength(keySize) + keySize + + mh.m().valueSizeMarshaller.storingLength(valueSize); } public final void freeExtraAllocatedChunks() { diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java index d8207ef07..7910abf41 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java @@ -16,8 +16,8 @@ package net.openhft.chronicle.map.impl.stage.entry; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.replication.TimeProvider; import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; @@ -33,7 +33,7 @@ import static net.openhft.chronicle.map.ReplicatedChronicleMap.ADDITIONAL_ENTRY_ public abstract class ReplicatedMapEntryStages extends MapEntryStages implements MapReplicableEntry, MapAbsentEntry { - @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicatedChronicleMapHolder mh; @StageRef ReplicationUpdate ru; @Stage("ReplicationState") long replicationBytesOffset = -1; @@ -43,9 +43,10 @@ public abstract class ReplicatedMapEntryStages extends MapEntryStages. - */ - -package net.openhft.chronicle.map.impl.stage.input; - -import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; -import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; - -@Staged -public class MapInputBytesValues { - - @StageRef HashInputBytes in; - @StageRef VanillaChronicleMapHolder mh; - - @Stage("FirstInputValueOffsets") public long firstInputValueSize = -1; - @Stage("FirstInputValueOffsets") public long firstInputValueOffset; - - private void initFirstInputValueOffsets() { - in.inputBytes.position(in.inputKeyOffset + in.inputKeySize); - firstInputValueSize = mh.m().valueSizeMarshaller.readSize(in.inputBytes); - firstInputValueOffset = in.inputBytes.position(); - } - - @Stage("SecondInputValueOffsets") public long secondInputValueSize = -1; - @Stage("SecondInputValueOffsets") public long secondInputValueOffset; - - private void initSecondInputValueOffsets() { - in.inputBytes.position(firstInputValueOffset + firstInputValueSize); - secondInputValueSize = mh.m().valueSizeMarshaller.readSize(in.inputBytes); - secondInputValueOffset = in.inputBytes.position(); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java b/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java index c40d56f0b..6ac780ea2 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java @@ -16,8 +16,8 @@ package net.openhft.chronicle.map.impl.stage.input; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; @@ -30,7 +30,6 @@ import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; import net.openhft.chronicle.map.impl.stage.query.ReplicatedMapQuery; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; import net.openhft.chronicle.map.replication.MapRemoteQueryContext; -import net.openhft.lang.io.Bytes; import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -40,7 +39,7 @@ import net.openhft.sg.Staged; public abstract class ReplicatedInput implements RemoteOperationContext, MapRemoteQueryContext { - @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicatedChronicleMapHolder mh; @StageRef ReplicationUpdate ru; @StageRef LogHolder lh; @StageRef ReplicatedInputKeyBytesData replicatedInputKeyBytesValue; @@ -57,12 +56,9 @@ public abstract class ReplicatedInput } public Bytes replicatedInputBytes = null; - public final JavaLangBytesReusableBytesStore replicatedInputStore = - new JavaLangBytesReusableBytesStore(); public void initReplicatedInputBytes(Bytes replicatedInputBytes) { this.replicatedInputBytes = replicatedInputBytes; - replicatedInputStore.setBytes(replicatedInputBytes); } // ri for "replication input" @@ -90,7 +86,7 @@ public abstract class ReplicatedInput isDeleted = replicatedInputBytes.readBoolean(); - riKeyOffset = replicatedInputBytes.position(); + riKeyOffset = replicatedInputBytes.readPosition(); riValueOffset = riKeyOffset + riKeySize; } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java index 976d1c5f7..f27d61db6 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java @@ -38,7 +38,7 @@ public abstract class ReplicatedMapSegmentIteration extends MapSegmentI implements ReplicatedIterationContext, ReplicableEntry, ReplicatedHashSegmentContext>, MapAbsentEntry { - @StageRef VanillaChronicleHashHolder hh; + @StageRef VanillaChronicleHashHolder hh; @StageRef ReplicatedMapEntryStages e; @StageRef ReplicationUpdate ru; @StageRef DummyValueZeroData dummyValue; diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/DefaultValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/DefaultValue.java index 02a676de2..5eee6cab9 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/DefaultValue.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/DefaultValue.java @@ -20,6 +20,7 @@ import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; import org.jetbrains.annotations.NotNull; @@ -28,18 +29,13 @@ import org.jetbrains.annotations.NotNull; public abstract class DefaultValue implements MapAbsentEntry { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; - @StageRef VanillaChronicleMapHolder mh; + @StageRef VanillaChronicleMapHolder mh; + @StageRef DummyValueZeroData zeroValueData; @NotNull @Override public Data defaultValue() { checkOnEachPublicOperation.checkOnEachPublicOperation(); - if (mh.m().constantValueProvider == null) { - throw new IllegalStateException("to call acquireUsing(), " + - "or defaultValue() on AbsentEntry, you should configure " + - "ChronicleMapBuilder.defaultValue(), or use one of the 'known' value types: " + - "boxed primitives, or so-called data-value-generated interface as a value"); - } - return context().wrapValueAsData(mh.m().constantValueProvider.defaultValue()); + return zeroValueData; } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java index ae35c9957..f04d66b06 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java @@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull; public abstract class MapEntryOperationsDelegation implements MapContext { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; - @StageRef VanillaChronicleMapHolder mh; + @StageRef VanillaChronicleMapHolder mh; @Override diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java index 083772418..0a9dd4ec2 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java @@ -18,35 +18,30 @@ package net.openhft.chronicle.map.impl.stage.map; import net.openhft.chronicle.hash.impl.stage.hash.Chaining; import net.openhft.chronicle.hash.impl.stage.hash.ChainingInterface; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ReplicatedChronicleMap; import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; import net.openhft.sg.Staged; @Staged -public class ReplicatedChronicleMapHolderImpl< - K, KI, MKI extends MetaBytesInterop, - V, VI, MVI extends MetaBytesInterop, R - > - extends Chaining - implements ReplicatedChronicleMapHolder { +public class ReplicatedChronicleMapHolderImpl extends Chaining + implements ReplicatedChronicleMapHolder { - private final ReplicatedChronicleMap m; + private final ReplicatedChronicleMap m; - public ReplicatedChronicleMapHolderImpl(ReplicatedChronicleMap m) { + public ReplicatedChronicleMapHolderImpl(ReplicatedChronicleMap m) { super(); this.m = m; } public ReplicatedChronicleMapHolderImpl( - ChainingInterface c, ReplicatedChronicleMap m) { + ChainingInterface c, ReplicatedChronicleMap m) { super(c); this.m = m; } @Override - public ReplicatedChronicleMap m() { + public ReplicatedChronicleMap m() { return m; } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java index 251cb6ed2..352ef6eca 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java @@ -16,25 +16,18 @@ package net.openhft.chronicle.map.impl.stage.map; -import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.hash.serialization.SizedReader; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; +import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded; + @Staged -public class ValueBytesInterop> { - @StageRef VanillaChronicleMapHolder mh; - @StageRef ThreadLocalCopiesHolder ch; - - public final BytesReader valueReader = - mh.m().valueReaderProvider.get(ch.copies, mh.m().originalValueReader); - public final VI valueInterop = - mh.m().valueInteropProvider.get(ch.copies, mh.m().originalValueInterop); - - public MVI valueMetaInterop(V value) { - return mh.m().metaValueInteropProvider.get( - ch.copies, mh.m().originalMetaValueInterop, valueInterop, value, false); - } +public class ValueBytesInterop { + + @StageRef VanillaChronicleMapHolder mh; + + public final SizedReader valueReader = copyIfNeeded(mh.m().originalValueReader); + } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java index 4a637f295..7360eecac 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java @@ -18,35 +18,30 @@ package net.openhft.chronicle.map.impl.stage.map; import net.openhft.chronicle.hash.impl.stage.hash.Chaining; import net.openhft.chronicle.hash.impl.stage.hash.ChainingInterface; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.VanillaChronicleMap; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; import net.openhft.sg.Staged; @Staged -public class VanillaChronicleMapHolderImpl< - K, KI, MKI extends MetaBytesInterop, - V, VI, MVI extends MetaBytesInterop, R - > - extends Chaining - implements VanillaChronicleMapHolder { +public class VanillaChronicleMapHolderImpl extends Chaining + implements VanillaChronicleMapHolder { - private final VanillaChronicleMap m; + private final VanillaChronicleMap m; - public VanillaChronicleMapHolderImpl(VanillaChronicleMap m) { + public VanillaChronicleMapHolderImpl(VanillaChronicleMap m) { super(); this.m = m; } public VanillaChronicleMapHolderImpl( - ChainingInterface c, VanillaChronicleMap m) { + ChainingInterface c, VanillaChronicleMap m) { super(c); this.m = m; } @Override - public VanillaChronicleMap m() { + public VanillaChronicleMap m() { return m; } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java index c9e8ddd50..d198032c4 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java @@ -19,7 +19,7 @@ package net.openhft.chronicle.map.impl.stage.map; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.map.MapContext; -import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceDataHolder; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -27,15 +27,15 @@ import net.openhft.sg.Staged; public abstract class WrappedValueInstanceValueHolder implements MapContext { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; - @StageRef WrappedValueInstanceData wrappedValueInstanceValue; - + @StageRef + WrappedValueInstanceDataHolder wrappedValueInstanceValueHolder; @Override public Data wrapValueAsData(V value) { checkOnEachPublicOperation.checkOnEachPublicOperation(); - WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; - wrapped = wrapped.getUnusedWrappedValue(); + WrappedValueInstanceDataHolder wrapped = this.wrappedValueInstanceValueHolder; + wrapped = wrapped.getUnusedWrappedValueHolder(); wrapped.initValue(value); - return wrapped; + return wrapped.wrappedData; } } diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java index 8ce3fdbe0..e7256bad5 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/AcquireHandle.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map.impl.stage.query; import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; -import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -27,7 +26,6 @@ import net.openhft.sg.Staged; public class AcquireHandle implements Closeable { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; - @StageRef MapEntryStages e; @StageRef MapQuery q; @StageRef UsingReturnValue usingReturn; diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java index aff54cb33..68fb59676 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java @@ -17,14 +17,13 @@ package net.openhft.chronicle.map.impl.stage.query; import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; -import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; import net.openhft.chronicle.hash.impl.stage.query.HashQuery.EntryPresence; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.MapContext; -import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @@ -41,7 +40,6 @@ public abstract class MapAbsent implements MapAbsentEntry { @StageRef public HashLookupSearch hashLookupSearch; @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; @StageRef public SegmentStages s; - @StageRef VanillaChronicleMapHolder mh; void putEntry(Data value) { assert ks.searchStateAbsent(); diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java index bd39bf507..df3f3fef0 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java @@ -20,6 +20,7 @@ import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.stage.query.HashQuery; import net.openhft.chronicle.hash.impl.stage.query.KeySearch; import net.openhft.chronicle.hash.impl.stage.query.SearchAllocatedChunks; +import net.openhft.chronicle.hash.serialization.DataAccess; import net.openhft.chronicle.map.ExternalMapQueryContext; import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.MapContext; @@ -27,12 +28,10 @@ import net.openhft.chronicle.map.MapEntry; import net.openhft.chronicle.map.impl.MapAbsentEntryHolder; import net.openhft.chronicle.map.impl.QueryContextInterface; import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; -import net.openhft.chronicle.map.impl.stage.data.bytes.InputFirstValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.bytes.InputSecondValueBytesData; -import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; +import net.openhft.sg.Stage; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; import org.jetbrains.annotations.NotNull; @@ -45,22 +44,37 @@ public abstract class MapQuery extends HashQuery implements MapEntry, ExternalMapQueryContext, QueryContextInterface { - @StageRef VanillaChronicleMapHolder mh; + @StageRef VanillaChronicleMapHolder mh; @StageRef MapEntryStages e; @StageRef SearchAllocatedChunks allocatedChunks; @StageRef KeySearch ks; @StageRef public AcquireHandle acquireHandle; - @StageRef public InputValueInstanceData inputValueInstanceValue; - - @StageRef public InputFirstValueBytesData inputFirstValueBytesValue; - @StageRef public InputSecondValueBytesData inputSecondValueBytesValue; - @StageRef public DefaultReturnValue defaultReturnValue; @StageRef public UsingReturnValue usingReturnValue; @StageRef public MapAbsentEntryHolder absent; + final DataAccess innerInputValueDataAccess = mh.m().originalValueDataAccess.copy(); + + /** Same as {@link #inputKeyDataAccessInitialized} */ + @Stage("InputValueDataAccess") private boolean inputValueDataAccessInitialized = false; + + void initInputValueDataAccess() { + inputValueDataAccessInitialized = true; + } + + void closeInputValueDataAccess() { + innerInputValueDataAccess.uninit(); + inputValueDataAccessInitialized = false; + } + + @Override + public DataAccess inputValueDataAccess() { + initInputValueDataAccess(); + return innerInputValueDataAccess; + } + @Override public MapEntry entry() { checkOnEachPublicOperation.checkOnEachPublicOperation(); diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryMapEntryStages.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryMapEntryStages.java index 26602d582..767894569 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryMapEntryStages.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryMapEntryStages.java @@ -18,10 +18,13 @@ package net.openhft.chronicle.map.impl.stage.query; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.stage.entry.HashLookupSearch; +import net.openhft.chronicle.map.VanillaChronicleMap; import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; +import static net.openhft.chronicle.map.VanillaChronicleMap.alignAddr; + @Staged public abstract class QueryMapEntryStages extends MapEntryStages { @@ -37,8 +40,8 @@ public abstract class QueryMapEntryStages extends MapEntryStages { boolean newValueSizeIsDifferent = newValue.size() != valueSize; if (newValueSizeIsDifferent) { newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long newValueOffset = mh.m().alignment.alignAddr( - entryStartOffset + newSizeOfEverythingBeforeValue); + long newValueOffset = + alignAddr(entryStartOffset + newSizeOfEverythingBeforeValue, mh.m().alignment); long newEntrySize = newValueOffset + newValue.size() - entryStartOffset; newSizeInChunks = mh.m().inChunks(newEntrySize); } else { diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java index 4f20b379a..4aff702b9 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java @@ -22,7 +22,6 @@ import net.openhft.chronicle.map.MapAbsentEntry; import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; -import net.openhft.chronicle.map.impl.stage.ret.BytesReturnValue; import net.openhft.chronicle.map.replication.MapRemoteQueryContext; import net.openhft.chronicle.map.replication.MapReplicableEntry; import net.openhft.sg.StageRef; @@ -36,8 +35,6 @@ public abstract class ReplicatedMapQuery extends MapQuery @StageRef ReplicatedMapEntryStages e; @StageRef ReplicationUpdate ru; - @StageRef BytesReturnValue bytesReturnValue; - @StageRef ReplicatedMapAbsentDelegating absentDelegating; @Nullable diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicatedQueryAlloc.java b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicatedQueryAlloc.java index 73ae1bea5..4a9ac9a91 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicatedQueryAlloc.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicatedQueryAlloc.java @@ -32,7 +32,7 @@ import java.util.function.Consumer; @Staged public class ReplicatedQueryAlloc extends QueryAlloc { - @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicatedChronicleMapHolder mh; @StageRef SegmentStages s; final CleanupAction cleanupAction = new CleanupAction(); @@ -41,7 +41,7 @@ public class ReplicatedQueryAlloc extends QueryAlloc { * Returns {@code true} if at least one old deleted entry was removed. */ public boolean forcedOldDeletedEntriesCleanup() { - ReplicatedChronicleMap map = mh.m(); + ReplicatedChronicleMap map = mh.m(); try (MapSegmentContext sc = map.segmentContext(s.segmentIndex)) { cleanupAction.removedCompletely = 0; ((ReplicatedHashSegmentContext) sc) @@ -55,7 +55,7 @@ public class ReplicatedQueryAlloc extends QueryAlloc { @Override public void accept(ReplicableEntry e) { - ReplicatedChronicleMap map = mh.m(); + ReplicatedChronicleMap map = mh.m(); if (e instanceof MapAbsentEntry) { long deleteTimeout = map.timeProvider.currentTime() - e.originTimestamp(); map.timeProvider.systemTimeIntervalBetween(e.originTimestamp(), diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java index 2c998a539..9252f2b97 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java @@ -29,7 +29,7 @@ import net.openhft.sg.Staged; public abstract class ReplicationUpdate implements RemoteOperationContext { @StageRef SegmentStages s; @StageRef ReplicatedMapEntryStages e; - @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicatedChronicleMapHolder mh; @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; @Stage("ReplicationUpdate") public long innerRemoteTimestamp; diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java deleted file mode 100644 index d3a49113a..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.impl.stage.ret; - -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; -import net.openhft.chronicle.map.ReturnValue; -import net.openhft.chronicle.map.TcpReplicator.TcpSocketChannelEntryWriter; -import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; -import net.openhft.lang.io.Bytes; -import net.openhft.sg.Stage; -import net.openhft.sg.StageRef; -import net.openhft.sg.Staged; -import org.jetbrains.annotations.NotNull; - -@Staged -public class BytesReturnValue implements ReturnValue, AutoCloseable { - - @StageRef - VanillaChronicleMapHolder mh; - - private final JavaLangBytesReusableBytesStore outputStore = - new JavaLangBytesReusableBytesStore(); - - @Stage("Output") TcpSocketChannelEntryWriter output = null; - @Stage("Output") long startOutputPos; - - public void initOutput(TcpSocketChannelEntryWriter output) { - this.output = output; - startOutputPos = output.in().position(); - } - - @Override - public void returnValue(@NotNull Data value) { - long valueSize = value.size(); - long totalSize = 1L + mh.m().valueSizeMarshaller.sizeEncodingSize(valueSize) + valueSize; - output.ensureBufferSize(totalSize); - Bytes out = output.in(); - out.writeBoolean(false); - mh.m().valueSizeMarshaller.writeSize(out, valueSize); - long outPosition = out.position(); - out.skip(valueSize); - outputStore.setBytes(out); - value.writeTo(outputStore, outPosition); - } - - @Override - public void close() { - if (output.in().position() == startOutputPos) { - output.ensureBufferSize(1L); - output.in().writeBoolean(true); - } - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java index 9d4d4cf92..6b4d5bc05 100644 --- a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; @Staged public abstract class UsingReturnValue implements UsableReturnValue { - private V usingReturnValue = (V) USING_RETURN_VALUE_UNINT; + private V usingReturnValue = (V) USING_RETURN_VALUE_UNINIT; @Override public void initUsingReturnValue(V usingReturnValue) { diff --git a/src/main/java/net/openhft/chronicle/map/replication/MapRemoteQueryContext.java b/src/main/java/net/openhft/chronicle/map/replication/MapRemoteQueryContext.java index b849d161e..974e21832 100644 --- a/src/main/java/net/openhft/chronicle/map/replication/MapRemoteQueryContext.java +++ b/src/main/java/net/openhft/chronicle/map/replication/MapRemoteQueryContext.java @@ -18,7 +18,6 @@ package net.openhft.chronicle.map.replication; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.replication.RemoteOperationContext; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.map.MapEntryOperations; diff --git a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java index 286a68e71..ef6b6cf2b 100755 --- a/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java +++ b/src/main/java/net/openhft/chronicle/set/ChronicleSetBuilder.java @@ -22,17 +22,9 @@ import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.TimeProvider; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.chronicle.hash.serialization.SizeMarshaller; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; -import net.openhft.chronicle.hash.serialization.internal.DummyValueMarshaller; +import net.openhft.chronicle.hash.serialization.*; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.io.serialization.BytesMarshaller; -import net.openhft.lang.io.serialization.BytesMarshallerFactory; -import net.openhft.lang.io.serialization.ObjectFactory; -import net.openhft.lang.io.serialization.ObjectSerializer; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -57,8 +49,9 @@ public final class ChronicleSetBuilder ChronicleSetBuilder(Class keyClass) { chronicleMapBuilder = ChronicleMapBuilder.of(keyClass, DummyValue.class) - .valueMarshallers(DummyValueMarshaller.INSTANCE, DummyValueMarshaller.INSTANCE) - .valueSizeMarshaller(DummyValueMarshaller.INSTANCE); + .valueReaderAndDataAccess( + DummyValueMarshaller.INSTANCE, DummyValueMarshaller.INSTANCE) + .valueSizeMarshaller(SizeMarshaller.constant(0)); } public static ChronicleSetBuilder of(Class keyClass) { @@ -222,38 +215,37 @@ public final class ChronicleSetBuilder } @Override - public ChronicleSetBuilder bytesMarshallerFactory( - BytesMarshallerFactory bytesMarshallerFactory) { - chronicleMapBuilder.bytesMarshallerFactory(bytesMarshallerFactory); - return this; - } - - /** - * {@inheritDoc} - * - *

Example:

{@code Set set = ChronicleSetBuilder.of(Key.class)
-     *     .entries(1_000_000)
-     *     .keySize(100)
-     *     // this class hasn't implemented yet, just for example
-     *     .objectSerializer(new KryoObjectSerializer())
-     *     .create();}
- */ - @Override - public ChronicleSetBuilder objectSerializer(ObjectSerializer objectSerializer) { - chronicleMapBuilder.objectSerializer(objectSerializer); - return this; - } - - @Override - public ChronicleSetBuilder keyMarshaller(@NotNull BytesMarshaller keyMarshaller) { - chronicleMapBuilder.keyMarshaller(keyMarshaller); + public ChronicleSetBuilder keyReaderAndDataAccess( + SizedReader keyReader, @NotNull DataAccess keyDataAccess) { + chronicleMapBuilder.keyReaderAndDataAccess(keyReader, keyDataAccess); return this; } @Override public ChronicleSetBuilder keyMarshallers( - @NotNull BytesWriter keyWriter, @NotNull BytesReader keyReader) { - chronicleMapBuilder.keyMarshallers(keyWriter, keyReader); + @NotNull BytesReader keyReader, @NotNull BytesWriter keyWriter) { + chronicleMapBuilder.keyMarshallers(keyReader, keyWriter); + return this; + } + + @Override + public & BytesWriter> + ChronicleSetBuilder keyMarshaller(@NotNull M marshaller) { + chronicleMapBuilder.keyMarshaller(marshaller); + return this; + } + + @Override + public ChronicleSetBuilder keyMarshallers( + @NotNull SizedReader keyReader, @NotNull SizedWriter keyWriter) { + chronicleMapBuilder.keyMarshallers(keyReader, keyWriter); + return this; + } + + @Override + public & SizedWriter> + ChronicleSetBuilder keyMarshaller(@NotNull M sizedMarshaller) { + chronicleMapBuilder.keyMarshaller(sizedMarshaller); return this; } @@ -263,29 +255,6 @@ public final class ChronicleSetBuilder return this; } - /** - * {@inheritDoc} - * - *

Actually this is just a convenience method supporting key marshaller configurations, made - * initially during {@link #of(Class)} call. Because if you {@linkplain - * #keyMarshaller(BytesMarshaller) configure} own custom key marshaller, this method doesn't - * take any effect on the maps constructed by this builder. - * - * @see #of(Class) - */ - @Override - public ChronicleSetBuilder keyDeserializationFactory( - @NotNull ObjectFactory keyDeserializationFactory) { - chronicleMapBuilder.keyDeserializationFactory(keyDeserializationFactory); - return this; - } - - @Override - public ChronicleSetBuilder immutableKeys() { - chronicleMapBuilder.immutableKeys(); - return this; - } - @Override public ChronicleSetBuilder aligned64BitMemoryOperationsAtomic( boolean aligned64BitMemoryOperationsAtomic) { diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValue.java b/src/main/java/net/openhft/chronicle/set/DummyValue.java similarity index 89% rename from src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValue.java rename to src/main/java/net/openhft/chronicle/set/DummyValue.java index 8826914c0..0aca54bc5 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DummyValue.java +++ b/src/main/java/net/openhft/chronicle/set/DummyValue.java @@ -14,8 +14,8 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.hash.serialization.internal; +package net.openhft.chronicle.set; -public enum DummyValue { +enum DummyValue { DUMMY_VALUE } diff --git a/src/main/java/net/openhft/chronicle/set/DummyValueData.java b/src/main/java/net/openhft/chronicle/set/DummyValueData.java new file mode 100644 index 000000000..505308f83 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/set/DummyValueData.java @@ -0,0 +1,54 @@ +/* + * 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.set; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.map.impl.stage.data.ZeroBytesStore; +import org.jetbrains.annotations.Nullable; + +class DummyValueData extends AbstractData { + + static final DummyValueData INSTANCE = new DummyValueData(); + + private DummyValueData() {} + + @Override + public RandomDataInput bytes() { + return ZeroBytesStore.INSTANCE; + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return 0; + } + + @Override + public DummyValue get() { + return DummyValue.DUMMY_VALUE; + } + + @Override + public DummyValue getUsing(@Nullable DummyValue using) { + return DummyValue.DUMMY_VALUE; + } +} diff --git a/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java b/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java new file mode 100644 index 000000000..0abed5364 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/set/DummyValueMarshaller.java @@ -0,0 +1,50 @@ +/* + * 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.set; + +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.SizedReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +enum DummyValueMarshaller implements DataAccess, SizedReader { + INSTANCE; + + @Override + public Data getData(@NotNull DummyValue instance) { + return DummyValueData.INSTANCE; + } + + @Override + public void uninit() { + // no op + } + + @Override + public DataAccess copy() { + return this; + } + + @NotNull + @Override + public DummyValue read(@NotNull Bytes in, long size, @Nullable DummyValue using) { + return DummyValue.DUMMY_VALUE; + } +} + diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java index dd66104e2..21e39a434 100644 --- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java +++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java @@ -17,7 +17,6 @@ package net.openhft.chronicle.set; import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; import net.openhft.chronicle.map.ChronicleMap; import org.jetbrains.annotations.NotNull; @@ -31,7 +30,7 @@ import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; -import static net.openhft.chronicle.hash.serialization.internal.DummyValue.DUMMY_VALUE; +import static net.openhft.chronicle.set.DummyValue.DUMMY_VALUE; class SetFromMap extends AbstractSet implements ChronicleSet, Serializable { diff --git a/src/main/java/net/openhft/chronicle/set/SetInstanceBuilder.java b/src/main/java/net/openhft/chronicle/set/SetInstanceBuilder.java index f474f2ae6..a23911722 100644 --- a/src/main/java/net/openhft/chronicle/set/SetInstanceBuilder.java +++ b/src/main/java/net/openhft/chronicle/set/SetInstanceBuilder.java @@ -20,7 +20,6 @@ import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder; import net.openhft.chronicle.hash.replication.ReplicationChannel; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; import net.openhft.chronicle.map.ChronicleMap; import java.io.File; diff --git a/src/main/java/net/openhft/chronicle/set/SetQueryContext.java b/src/main/java/net/openhft/chronicle/set/SetQueryContext.java index 7bda75c60..8d26041aa 100644 --- a/src/main/java/net/openhft/chronicle/set/SetQueryContext.java +++ b/src/main/java/net/openhft/chronicle/set/SetQueryContext.java @@ -17,11 +17,6 @@ package net.openhft.chronicle.set; import net.openhft.chronicle.hash.HashQueryContext; -import net.openhft.chronicle.map.ChronicleMap; -import net.openhft.chronicle.map.MapEntryOperations; -import net.openhft.chronicle.map.MapMethods; -import net.openhft.chronicle.map.replication.MapRemoteOperations; -import net.openhft.chronicle.set.replication.SetRemoteOperations; import org.jetbrains.annotations.Nullable; /** diff --git a/src/main/java/net/openhft/xstream/converters/AbstractChronicleMapConverter.java b/src/main/java/net/openhft/xstream/converters/AbstractChronicleMapConverter.java index 0c93f2f08..76ff66f08 100644 --- a/src/main/java/net/openhft/xstream/converters/AbstractChronicleMapConverter.java +++ b/src/main/java/net/openhft/xstream/converters/AbstractChronicleMapConverter.java @@ -21,12 +21,16 @@ import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.NotNull; +import net.openhft.chronicle.values.ValueModel; +import net.openhft.chronicle.values.Values; +import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.Map; +import static net.openhft.chronicle.values.ValueModel.$$HEAP; +import static net.openhft.chronicle.values.ValueModel.$$NATIVE; + /** * @author Rob Austin. */ @@ -135,17 +139,17 @@ class AbstractChronicleMapConverter implements Converter { return Class.forName(clazz); } catch (ClassNotFoundException e) { - boolean isNative = clazz.endsWith("$$Native"); - boolean isHeap = clazz.endsWith("$$Heap"); + boolean isNative = clazz.endsWith($$NATIVE); + boolean isHeap = clazz.endsWith($$HEAP); if (!isNative && !isHeap) throw new ConversionException("class=" + clazz, e); - final String nativeInterface = isNative ? clazz.substring(0, clazz.length() - - "$$Native".length()) : clazz.substring(0, clazz.length() - - "$$Heap".length()); + final String nativeInterface = isNative ? + clazz.substring(0, clazz.length() - $$NATIVE.length()) : + clazz.substring(0, clazz.length() - $$HEAP.length()); try { - DataValueClasses.newDirectInstance(Class.forName(clazz)); + Values.newNativeReference(Class.forName(clazz)); return Class.forName(nativeInterface); } catch (Exception e1) { throw new ConversionException("class=" + clazz, e1); diff --git a/src/main/java/net/openhft/xstream/converters/DataValueConverter.java b/src/main/java/net/openhft/xstream/converters/DataValueConverter.java deleted file mode 100644 index 4068afbdc..000000000 --- a/src/main/java/net/openhft/xstream/converters/DataValueConverter.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * 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.xstream.converters; - -import com.thoughtworks.xstream.converters.ConversionException; -import com.thoughtworks.xstream.converters.Converter; -import com.thoughtworks.xstream.converters.MarshallingContext; -import com.thoughtworks.xstream.converters.UnmarshallingContext; -import com.thoughtworks.xstream.io.HierarchicalStreamReader; -import com.thoughtworks.xstream.io.HierarchicalStreamWriter; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.DataValueModel; -import net.openhft.lang.model.DataValueModels; -import net.openhft.lang.model.FieldModel; -import net.openhft.lang.values.StringValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.beans.BeanInfo; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; - - -/** - * @author Rob Austin. - */ -public class DataValueConverter implements Converter { - - private static final Logger LOG = LoggerFactory.getLogger(DataValueConverter.class); - - @Override - public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) { - - final String canonicalName = o.getClass().getCanonicalName(); - - boolean isNative = canonicalName.endsWith("$$Native"); - boolean isHeap = canonicalName.endsWith("$$Heap"); - - if (!isNative && !isHeap) - return; - - if (canonicalName.startsWith("net.openhft.lang.values")) { - - Method[] methods = o.getClass().getMethods(); - - for (Method method : methods) { - - if (!method.getName().equals("getValue") || - method.getParameterTypes().length != 0) { - continue; - } - - try { - context.convertAnother(method.invoke(o)); - return; - } catch (Exception e) { - throw new ConversionException("class=" + canonicalName, e); - } - } - - throw new ConversionException("class=" + canonicalName); - } - - - try { - DataValueModel dataValueModel = DataValueModels.acquireModel(interfaceClass(o.getClass())); - - for (Map.Entry p : dataValueModel.fieldMap().entrySet()) { - - final FieldModel fileModel = p.getValue(); - - if (fileModel.indexedGetter() != null) { - try { - - final Method indexedReadMethod = fileModel.indexedGetter(); - - if (indexedReadMethod == null) - continue; - - final Class returnType = indexedReadMethod.getReturnType(); - - if (returnType == null) - continue; - - final String fieldName = "_" + fileModel.name(); - - Field field; - - try { - field = o.getClass().getDeclaredField(fieldName); - } catch (NoSuchFieldException e1) { - - throw new ConversionException("JSON conversion of Classes containing " + - "arrays is not " + - "currently supported" + - ", the following field could not be found=" + fileModel.name(), e1); - } - - field.setAccessible(true); - - final Object[] o1 = (Object[]) field.get(o); - - if (o1 == null) - continue; - writer.startNode(fileModel.name()); - int i = 0; - for (Object f : o1) { - if (f == null) { - continue; - } - writer.startNode(Integer.toString(i++)); - context.convertAnother(f); - writer.endNode(); - } - writer.endNode(); - - } catch (IllegalAccessException e) { - throw new ConversionException("", e); - } - - continue; - } - - - try { - - final Method readMethod = fileModel.getter(); - - if (readMethod == null) - continue; - - readMethod.setAccessible(true); - - final Object value = readMethod.invoke(o); - - if (value == null) - return; - - writer.startNode(fileModel.name()); - context.convertAnother(value); - writer.endNode(); - - } catch (Exception e) { - LOG.error("class=" + fileModel.name(), e); - } - - - } - - } catch (ClassNotFoundException e) { - throw new ConversionException("class=" + canonicalName, e); - } - } - - private Class interfaceClass(Class clazz) throws ClassNotFoundException { - String className = clazz.getName(); - boolean isNative = className.endsWith("$$Native"); - boolean isHeap = className.endsWith("$$Heap"); - - if (!isNative && !isHeap) - throw new ClassNotFoundException(); - - final String nodeName = isNative ? - - className.substring(0, className.length() - - "$$Native".length()) : - - className.substring(0, className.length() - - "$$Heap".length()); - - return Class.forName(nodeName); - } - - - @Override - public Object unmarshal(HierarchicalStreamReader reader, - UnmarshallingContext context) { - - final String canonicalName = context.getRequiredType().getName(); - - boolean isNative = canonicalName.endsWith("$$Native"); - boolean isHeap = canonicalName.endsWith("$$Heap"); - - if (!isNative && !isHeap) - return null; - - if (context.getRequiredType().getName().startsWith - ("net.openhft.lang.values")) - return toNativeValueObjects(reader, context.getRequiredType(), context); - - final String nodeName = isNative ? - - canonicalName.substring(0, canonicalName.length() - - "$$Native".length()) : - - canonicalName.substring(0, canonicalName.length() - - "$$Heap".length()); - - try { - - final Class interfaceClass = Class.forName(nodeName); - - final Object result = (isNative) ? - DataValueClasses.newDirectInstance(interfaceClass) : - DataValueClasses.newInstance(interfaceClass); - - fillInObject(reader, context, result); - - return result; - - } catch (Exception e) { - throw new ConversionException("class=" + canonicalName, e); - } - - } - - private void fillInObject(HierarchicalStreamReader reader, UnmarshallingContext context, Object using) throws ClassNotFoundException { - - while (reader.hasMoreChildren()) { - reader.moveDown(); - - final String name = reader.getNodeName(); - - DataValueModel dataValueModel = DataValueModels.acquireModel(interfaceClass(using.getClass())); - - FieldModel fieldModel = dataValueModel.fieldMap().get(name); - - if (fieldModel.indexedGetter() != null) { - - while (reader.hasMoreChildren()) { - - reader.moveDown(); - try { - String index = reader.getNodeName(); - int i = Integer.parseInt(index); - Method writeMethod = fieldModel.indexedSetter(); - Class[] parameterTypes = writeMethod.getParameterTypes(); - - if (parameterTypes.length == 2) { - final Method indexedReadMethod = fieldModel.indexedGetter(); - indexedReadMethod.setAccessible(true); - final Object instance = indexedReadMethod.invoke(using, i); - fillInObject(reader, context, instance); - } - } catch (IllegalAccessException | InvocationTargetException e) { - throw new ConversionException("", e); - } - - reader.moveUp(); - } - reader.moveUp(); - continue; - } - - Method setter = fieldModel.setter(); - setter.setAccessible(true); - - final Class[] parameterTypes = setter.getParameterTypes(); - - if (parameterTypes.length != 1) - continue; - - final Object object = context.convertAnother(null, parameterTypes[0]); - - try { - setter.invoke(using, object); - } catch (Exception e) { - throw new ConversionException("", e); - } - - reader.moveUp(); - } - } - - - private static Object toNativeValueObjects(HierarchicalStreamReader reader, - final Class aClass, - UnmarshallingContext context) { - - final Object o = DataValueClasses.newDirectInstance(aClass); - - try { - - final BeanInfo info = Introspector.getBeanInfo(o.getClass()); // new BeanGenerator - - for (PropertyDescriptor p : info.getPropertyDescriptors()) { - - if (!p.getName().equals("value")) - continue; - - final String value = reader.getValue(); - - if (StringValue.class.isAssignableFrom(o.getClass())) { - ((StringValue) o).setValue(value); - return o; - } - - final Class propertyType = p.getPropertyType(); - - final Object o1 = context.convertAnother(value, propertyType); - p.getWriteMethod().invoke(o, o1); - - return o; - - } - - } catch (Exception e) { - throw new ConversionException("class=" + aClass.getName(), e); - } - - throw new ConversionException("setValue(..) method not found in class=" + - aClass.getCanonicalName()); - } - - @Override - public boolean canConvert(Class clazz) { - final String canonicalName = clazz.getCanonicalName(); - - return canonicalName.startsWith("net.openhft.lang.values") || - canonicalName.endsWith("$$Native") || - canonicalName.endsWith("$$Heap"); - } -} diff --git a/src/main/java/net/openhft/xstream/converters/StringBuilderConverter.java b/src/main/java/net/openhft/xstream/converters/StringBuilderConverter.java new file mode 100644 index 000000000..4df6a7999 --- /dev/null +++ b/src/main/java/net/openhft/xstream/converters/StringBuilderConverter.java @@ -0,0 +1,42 @@ +/* + * 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.xstream.converters; + +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + +public class StringBuilderConverter implements Converter { + + @Override + public void marshal( + Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + writer.setValue(source.toString()); + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + return new StringBuilder(reader.getValue()); + } + + @Override + public boolean canConvert(Class type) { + return type == StringBuilder.class; + } +} diff --git a/src/main/java/net/openhft/xstream/converters/ValueConverter.java b/src/main/java/net/openhft/xstream/converters/ValueConverter.java new file mode 100644 index 000000000..eb0926dca --- /dev/null +++ b/src/main/java/net/openhft/xstream/converters/ValueConverter.java @@ -0,0 +1,155 @@ +/* + * 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.xstream.converters; + +import com.thoughtworks.xstream.converters.ConversionException; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import net.openhft.chronicle.values.ArrayFieldModel; +import net.openhft.chronicle.values.FieldModel; +import net.openhft.chronicle.values.ValueModel; +import net.openhft.chronicle.values.Values; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +/** + * @author Rob Austin. + */ +public class ValueConverter implements Converter { + + private static final Logger LOG = LoggerFactory.getLogger(ValueConverter.class); + + @Override + public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) { + + ValueModel valueModel = ValueModel.acquire(o.getClass()); + + valueModel.fields().forEach(fieldModel -> { + + if (fieldModel instanceof ArrayFieldModel) { + try { + + final Method indexedGet = fieldModel.getOrGetVolatile(); + indexedGet.setAccessible(true); + + writer.startNode(fieldModel.name()); + for (int i = 0; i < ((ArrayFieldModel) fieldModel).array().length(); i++) { + writer.startNode(Integer.toString(i)); + context.convertAnother(indexedGet.invoke(o, i)); + writer.endNode(); + } + writer.endNode(); + + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ConversionException("", e); + } + + return; + } + + + try { + + final Method get = fieldModel.getOrGetVolatile(); + get.setAccessible(true); + final Object value = get.invoke(o); + + writer.startNode(fieldModel.name()); + context.convertAnother(value); + writer.endNode(); + + } catch (Exception e) { + LOG.error("class=" + fieldModel.name(), e); + } + }); + + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + try { + ValueModel valueModel = ValueModel.acquire(context.getRequiredType()); + Object result = valueModel.heapClass().newInstance(); + fillInObject(reader, context, valueModel, result); + return result; + } catch (Exception e) { + throw new ConversionException( + "class=" + context.getRequiredType().getCanonicalName(), e); + } + } + + private void fillInObject(HierarchicalStreamReader reader, UnmarshallingContext context, + ValueModel valueModel, Object using) throws ClassNotFoundException { + + while (reader.hasMoreChildren()) { + reader.moveDown(); + + final String name = reader.getNodeName(); + + FieldModel fieldModel = + valueModel.fields().filter(f -> f.name().equals(name)).findAny().get(); + + if (fieldModel instanceof ArrayFieldModel) { + + while (reader.hasMoreChildren()) { + + reader.moveDown(); + try { + String index = reader.getNodeName(); + int i = Integer.parseInt(index); + Method indexedSet = fieldModel.setOrSetOrderedOrSetVolatile(); + indexedSet.setAccessible(true); + Class[] parameterTypes = indexedSet.getParameterTypes(); + Object value = context.convertAnother(null, parameterTypes[1]); + indexedSet.invoke(using, i, value); + } catch (Exception e) { + throw new ConversionException("", e); + } + + reader.moveUp(); + } + reader.moveUp(); + continue; + } + + Method set = fieldModel.setOrSetOrderedOrSetVolatile(); + set.setAccessible(true); + final Class[] parameterTypes = set.getParameterTypes(); + final Object value = context.convertAnother(null, parameterTypes[0]); + + try { + set.invoke(using, value); + } catch (Exception e) { + throw new ConversionException("", e); + } + + reader.moveUp(); + } + } + + + @Override + public boolean canConvert(Class clazz) { + return Values.isValueInterfaceOrImplClass(clazz); + } +} diff --git a/src/main/java/net/openhft/xstream/converters/VanillaChronicleMapConverter.java b/src/main/java/net/openhft/xstream/converters/VanillaChronicleMapConverter.java index 66c7849d3..ed6102640 100644 --- a/src/main/java/net/openhft/xstream/converters/VanillaChronicleMapConverter.java +++ b/src/main/java/net/openhft/xstream/converters/VanillaChronicleMapConverter.java @@ -18,7 +18,7 @@ package net.openhft.xstream.converters; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import net.openhft.chronicle.map.ChronicleMap; -import net.openhft.lang.model.constraints.NotNull; +import org.jetbrains.annotations.NotNull; import java.util.Map; diff --git a/src/test/java/eg/BigData.java b/src/test/java/eg/BigData.java index 54e0af190..7e09697ad 100644 --- a/src/test/java/eg/BigData.java +++ b/src/test/java/eg/BigData.java @@ -18,7 +18,6 @@ package eg; import net.openhft.affinity.AffinitySupport; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.io.Bytes; import java.io.*; import java.util.Map; @@ -208,17 +207,15 @@ class BigDataStuff implements Externalizable { @Override public void writeExternal(ObjectOutput out) throws IOException { - Bytes b = (Bytes) out; - b.writeStopBit(x); - b.writeUTFΔ(y); + out.writeLong(x); + out.writeUTF(y.toString()); } @Override public void readExternal(ObjectInput in) throws IOException { - Bytes b = (Bytes) in; - this.x = b.readStopBit(); + this.x = in.readLong(); if (this.y == null) this.y = new StringBuilder(); - b.readUTFΔ(this.y); + y.append(in.readUTF()); } } diff --git a/src/test/java/eg/OffHeapByteArrayExampleTest.java b/src/test/java/eg/OffHeapByteArrayExampleTest.java index ed38d7628..ff042e12c 100644 --- a/src/test/java/eg/OffHeapByteArrayExampleTest.java +++ b/src/test/java/eg/OffHeapByteArrayExampleTest.java @@ -16,12 +16,12 @@ package eg; +import net.openhft.chronicle.core.values.ByteValue; +import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.MaxSize; -import net.openhft.lang.values.ByteValue; -import net.openhft.lang.values.LongValue; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.Values; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -32,7 +32,8 @@ public class OffHeapByteArrayExampleTest { public static final char EXPECTED = 'b'; interface ByteArray { - void setByteValueAt(@MaxSize(7) int index, ByteValue value); + @Array(length = 7) + void setByteValueAt(int index, ByteValue value); ByteValue getByteValueAt(int index); } @@ -57,7 +58,7 @@ public class OffHeapByteArrayExampleTest { public void test() { // this objects will be reused - ByteValue byteValue = DataValueClasses.newDirectInstance(ByteValue.class); + ByteValue byteValue = Values.newHeapInstance(ByteValue.class); ByteArray value = chm.newValueInstance(); LongValue key = chm.newKeyInstance(); diff --git a/src/test/java/eg/TestInstrumentVOInterface.java b/src/test/java/eg/TestInstrumentVOInterface.java index 1b3289b9a..d30b21cdd 100644 --- a/src/test/java/eg/TestInstrumentVOInterface.java +++ b/src/test/java/eg/TestInstrumentVOInterface.java @@ -16,7 +16,8 @@ package eg; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.MaxUtf8Length; /** * Created by Vanitha on 12/5/2014. @@ -24,38 +25,38 @@ import net.openhft.lang.model.constraints.MaxSize; public interface TestInstrumentVOInterface { - public int getSizeOfInstrumentIDArray(); - - public void setSizeOfInstrumentIDArray(int sizeOfInstrumentIDArray); + int getSizeOfInstrumentIDArray(); + void setSizeOfInstrumentIDArray(int sizeOfInstrumentIDArray); - public String getSymbol(); + String getSymbol(); - public void setSymbol(@MaxSize(20) String symbol); + void setSymbol(@MaxUtf8Length(20) String symbol); - public String getCurrencyCode(); + String getCurrencyCode(); - public void setCurrencyCode(@MaxSize(4) String currencyCode); + void setCurrencyCode(@MaxUtf8Length(4) String currencyCode); - public void setInstrumentIDAt(@MaxSize(2) int location, TestInstrumentIDVOInterface instrumentID); + @Array(length = 2) + void setInstrumentIDAt(int location, TestInstrumentIDVOInterface instrumentID); - public TestInstrumentIDVOInterface getInstrumentIDAt(int location); + TestInstrumentIDVOInterface getInstrumentIDAt(int location); interface TestInstrumentIDVOInterface { - public String getIdSource(); + String getIdSource(); - public void setIdSource(@MaxSize(6) String idSource); + void setIdSource(@MaxUtf8Length(6) String idSource); - public String getSecurityId(); + String getSecurityId(); - public void setSecurityId(@MaxSize(100) String securityId); + void setSecurityId(@MaxUtf8Length(100) String securityId); } } diff --git a/src/test/java/eg/TestNesterInterfaceMarshal.java b/src/test/java/eg/TestNesterInterfaceMarshal.java index ac9b1b327..df0a40903 100644 --- a/src/test/java/eg/TestNesterInterfaceMarshal.java +++ b/src/test/java/eg/TestNesterInterfaceMarshal.java @@ -18,7 +18,7 @@ package eg; import net.openhft.chronicle.core.io.Closeable; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.map.Builder; +import net.openhft.chronicle.set.Builder; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; import org.junit.Assert; diff --git a/src/test/java/net/openhft/chronicle/map/AcquireGetUsingMain.java b/src/test/java/net/openhft/chronicle/map/AcquireGetUsingMain.java index 846ab8db0..1774a81c1 100644 --- a/src/test/java/net/openhft/chronicle/map/AcquireGetUsingMain.java +++ b/src/test/java/net/openhft/chronicle/map/AcquireGetUsingMain.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.map; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.Values; import java.io.File; import java.io.IOException; @@ -31,7 +31,7 @@ public class AcquireGetUsingMain { ChronicleMap theSharedMap = ChronicleMapBuilder.of(String.class, Data.class) .createPersistedTo(file); - Data data = DataValueClasses.newDirectReference(Data.class); + Data data = Values.newNativeReference(Data.class); String processType = "testkey"; if (theSharedMap.getUsing(processType, data) == null) { System.out.println("Key " + processType + " does not exist, " + data); @@ -41,7 +41,7 @@ public class AcquireGetUsingMain { // you can't have off heap objects, but you can an on heap object which proxy references off heap data. // this reference is not usable until it references something concrete. - Data data2 = DataValueClasses.newDirectReference(Data.class); + Data data2 = Values.newNativeReference(Data.class); String processType2 = "testkey2"; if (theSharedMap.getUsing(processType2, data2) == null) { // should be unset given we don't set it. @@ -68,14 +68,14 @@ public class AcquireGetUsingMain { Data data3 = theSharedMap.acquireUsing(processType, data); assert data3 == data; - System.out.println("getting " + ((Byteable) data).bytes()); + System.out.println("getting " + ((Byteable) data).bytesStore()); data.setMaxNumberOfProcessesAllowed(3); data.setTimeAt(0, 100); data.setTimeAt(1, 111); data.setTimeAt(2, 222); // an on heap object exists when created as it doesn't use indirection to where the data is actually held. - Data data4 = DataValueClasses.newInstance(Data.class); + Data data4 = Values.newHeapInstance(Data.class); // put is not needed as we created something already. // theSharedMap.put(processType, data); @@ -84,7 +84,8 @@ public class AcquireGetUsingMain { } public static interface Data { - void setTimeAt(@MaxSize(8) int index, long time); + @Array(length = 8) + void setTimeAt(int index, long time); long getTimeAt(int index); diff --git a/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java b/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java index ae719b840..f169d9bac 100755 --- a/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java +++ b/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java @@ -17,8 +17,8 @@ package net.openhft.chronicle.map; import net.openhft.affinity.AffinityLock; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.LongValue; +import net.openhft.chronicle.core.values.LongValue; +import net.openhft.chronicle.values.Values; import java.io.File; import java.io.IOException; @@ -79,8 +79,8 @@ public class CHMLatencyTestMain { .createPersistedTo(file); // add keys - LongValue key = DataValueClasses.newInstance(LongValue.class); - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue key = Values.newHeapInstance(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); for (long i = 0; i < KEYS; i++) { key.setValue(i); countersMap.acquireUsing(key, value); @@ -88,7 +88,7 @@ public class CHMLatencyTestMain { } System.out.println("Keys created"); // Monitor monitor = new Monitor(); - LongValue value2 = DataValueClasses.newDirectReference(LongValue.class); + LongValue value2 = Values.newNativeReference(LongValue.class); for (int t = 0; t < 5; t++) { for (int rate : new int[]{2 * 1000 * 1000, 1000 * 1000, 500 * 1000/*, 250 * 1000, 100 * 1000, 50 * 1000*/}) { Histogram times = new Histogram(); diff --git a/src/test/java/net/openhft/chronicle/map/CHMTest5.java b/src/test/java/net/openhft/chronicle/map/CHMTest5.java index 5fee7b7bd..58f377c1f 100644 --- a/src/test/java/net/openhft/chronicle/map/CHMTest5.java +++ b/src/test/java/net/openhft/chronicle/map/CHMTest5.java @@ -16,12 +16,21 @@ package net.openhft.chronicle.map; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.algo.locks.AcquisitionStrategies; +import net.openhft.chronicle.algo.locks.ReadWriteLockingStrategy; +import net.openhft.chronicle.algo.locks.TryAcquireOperations; +import net.openhft.chronicle.algo.locks.VanillaReadWriteWithWaitsLockingStrategy; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.Group; +import net.openhft.chronicle.values.Values; import java.io.File; import java.io.IOException; +import java.util.concurrent.TimeUnit; +import static net.openhft.chronicle.algo.bytes.Access.checkedBytesStoreAccess; import static org.junit.Assert.assertEquals; /** @@ -47,7 +56,7 @@ public class CHMTest5 { builder.createPersistedTo(new File(chmPath)); //Now get the shared data object, auto-creating if it's not there - CHMTest5Data data = DataValueClasses.newDirectReference(CHMTest5Data.class); + CHMTest5Data data = Values.newNativeReference(CHMTest5Data.class); theSharedMap.acquireUsing(TEST_KEY, data); //if this was newly created, we need to set the max allowed //Note, the object is pointing at shared memory and writes @@ -230,27 +239,37 @@ public class CHMTest5 { } } - public static interface CHMTest5Data { - public int getMaxNumberOfProcessesAllowed(); + public interface CHMTest5Data { - public void setMaxNumberOfProcessesAllowed(int max); - - public void setTimeAt(@MaxSize(4) int index, long time); - - public long getTimeAt(int index); + @Group(0) + long getEntryLockState(); + void setEntryLockState(long entryLockState); + @Group(1) + int getMaxNumberOfProcessesAllowed(); + void setMaxNumberOfProcessesAllowed(int max); boolean compareAndSwapMaxNumberOfProcessesAllowed(int expected, int value); - @Deprecated() - void busyLockEntry() throws InterruptedException, IllegalStateException; + @Group(1) + @Array(length = 4) + void setTimeAt(int index, long time); + long getTimeAt(int index); @Deprecated() - boolean tryLockNanosEntry(long nanos); + default boolean tryLockNanosEntry(long nanos) { + return AcquisitionStrategies + .spinLoop(nanos, TimeUnit.NANOSECONDS).acquire( + TryAcquireOperations.writeLock(), + VanillaReadWriteWithWaitsLockingStrategy.instance(), + checkedBytesStoreAccess(), ((Byteable) this).bytesStore(), + ((Byteable) this).offset()); + } @Deprecated() - boolean tryLockEntry(); - - @Deprecated() - void unlockEntry() throws IllegalMonitorStateException; + default void unlockEntry() throws IllegalMonitorStateException { + VanillaReadWriteWithWaitsLockingStrategy.instance() + .writeUnlock(checkedBytesStoreAccess(), + ((Byteable) this).bytesStore(), ((Byteable) this).offset()); + } } } \ No newline at end of file diff --git a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java index 3b1a7b8d4..2f1a2a625 100644 --- a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java @@ -17,17 +17,22 @@ package net.openhft.chronicle.map; import com.google.common.primitives.Chars; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; import net.openhft.chronicle.core.util.SerializableFunction; +import net.openhft.chronicle.core.values.*; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.ListMarshaller; +import net.openhft.chronicle.hash.serialization.MapMarshaller; +import net.openhft.chronicle.hash.serialization.SetMarshaller; +import net.openhft.chronicle.hash.serialization.impl.*; import net.openhft.chronicle.map.fromdocs.BondVOInterface; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.io.serialization.impl.*; -import net.openhft.lang.model.constraints.MaxSize; -import net.openhft.lang.model.constraints.NotNull; -import net.openhft.lang.values.*; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.MaxUtf8Length; +import net.openhft.chronicle.values.Range; +import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Assert; import org.junit.Ignore; @@ -344,8 +349,9 @@ public class CHMUseCasesTest { interface I1 { - String getStrAt( @MaxSize(10) int i); - void setStrAt(@MaxSize(10) int i, @MaxSize(10) String str); + @Array(length = 10) + String getStrAt(int i); + void setStrAt(int i, @MaxUtf8Length(10) String str); } @Test @@ -623,9 +629,6 @@ public class CHMUseCasesTest { * CharSequence is more efficient when object creation is avoided. * * The key can only be on heap and variable length serialised. */ - @Ignore("This test fails because assumes StringBuilder is fed to lambdas, but actually " + - "because interned in CharSequenceReader. Defer fixing this until Chronicle Map " + - "serialization framework is moved from Lang Bytes to Chronicle Bytes") @Test public void testCharSequenceCharSequenceMap() throws ExecutionException, InterruptedException, IOException { @@ -661,9 +664,9 @@ public class CHMUseCasesTest { assertEquals("New World !!", map.get("Hello").toString()); - assertEquals("New !!", map.computeIfPresent("no-key", (k, s) -> { - ((StringBuilder) s).append("!!"); - return "New " + s; + assertEquals("New !!", map.compute("no-key", (k, s) -> { + assertNull(s); + return "New !!"; })); mapChecks(); @@ -783,30 +786,12 @@ public class CHMUseCasesTest { } } - @Test - public void testAcquireUsingWithByteBufferBytesValue() throws IOException { - ChronicleMapBuilder builder = ChronicleMapBuilder - .of(IntValue.class, CharSequence.class); - - try (ChronicleMap map = newInstance(builder)) { - - IntValue key = map.newKeyInstance(); - key.setValue(1); - - ByteBufferBytes value = new ByteBufferBytes(ByteBuffer.allocate(10)); - value.limit(0); - - try (net.openhft.chronicle.core.io.Closeable c = map.acquireContext(key, value)) { - assertTrue(key instanceof IntValue); - assertTrue(value instanceof CharSequence); - } - - assertTrue(map.get(key).length() == 0); - mapChecks(); - } + interface StringValue { + CharSequence getValue(); + void getUsingValue(StringBuilder using); + void setValue(@net.openhft.chronicle.values.NotNull @MaxUtf8Length(64) CharSequence value); } - /** * StringValue represents any bean which contains a String Value */ @@ -901,7 +886,7 @@ public class CHMUseCasesTest { try (net.openhft.chronicle.core.io.Closeable c = map.acquireContext(key1, value2)) { assertEquals("123", value2.getValue()); - value2.setValue(value2.getValue() + '4'); + value2.setValue(value2.getValue().toString() + '4'); assertEquals("1234", value2.getValue()); } @@ -929,7 +914,7 @@ public class CHMUseCasesTest { try (net.openhft.chronicle.core.io.Closeable c = map.acquireContext(key2, value1)) { assertEquals("123", value1.getValue()); - value1.setValue(value1.getValue() + '4'); + value1.setValue(value1.getValue().toString() + '4'); assertEquals("1234", value1.getValue()); } @@ -1433,6 +1418,12 @@ public class CHMUseCasesTest { } } + interface UnsignedIntValue { + long getValue(); + void setValue(@Range(min = 0, max = (1L << 32) - 1) long value); + long addValue(long addition); + } + /** * For unsigned int -> unsigned int entries, the key can be on heap or off heap. */ @@ -1655,6 +1646,12 @@ public class CHMUseCasesTest { } } + interface UnsignedShortValue { + int getValue(); + void setValue(@Range(min = 0, max = Character.MAX_VALUE) int value); + int addValue(int addition); + } + /** * For int -> unsigned short values, the key can be on heap or off heap. */ @@ -1858,6 +1855,12 @@ public class CHMUseCasesTest { } } + interface UnsignedByteValue { + int getValue(); + void setValue(@Range(min = 0, max = 255) int value); + int addValue(int addition); + } + /** * For int-> byte entries, the key can be on heap or off heap. */ @@ -2197,7 +2200,8 @@ public class CHMUseCasesTest { assertEquals(null, map.get(key1)); map.put(key1, value1); - assertEquals(value1, map.get(key1)); + DoubleValue v2 = map.get(key1); + assertEquals(value1, v2); key2.setValue(2); value2.setValue(22); @@ -2390,9 +2394,11 @@ public class CHMUseCasesTest { @Test public void testListValue() throws IOException { + ListMarshaller valueMarshaller = new ListMarshaller<>( + new StringBytesReader(), CharSequenceBytesWriter.INSTANCE); ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) List.class) - .valueMarshaller(ListMarshaller.of(new StringMarshaller(8))); + .valueMarshaller(valueMarshaller); try (ChronicleMap> map = newInstance(builder)) { @@ -2435,20 +2441,21 @@ public class CHMUseCasesTest { @Test public void testSetValue() throws IOException { - + SetMarshaller valueMarshaller = new SetMarshaller<>( + new StringBytesReader(), CharSequenceBytesWriter.INSTANCE); ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Set.class) - .valueMarshaller(SetMarshaller.of(new StringMarshaller(8))); + .valueMarshaller(valueMarshaller); try (ChronicleMap> map = newInstance(builder)) { map.put("1", Collections.emptySet()); - map.put("2", new LinkedHashSet(asList("one"))); + map.put("2", new LinkedHashSet<>(asList("one"))); Set list1 = new LinkedHashSet<>(); try (net.openhft.chronicle.core.io.Closeable c = map.acquireContext("1", list1)) { list1.add("two"); - assertEquals(new LinkedHashSet(asList("two")), list1); + assertEquals(new LinkedHashSet<>(asList("two")), list1); } Set list2 = new LinkedHashSet<>(); try (ExternalMapQueryContext, ?> c = map.queryContext("1")) { @@ -2482,10 +2489,11 @@ public class CHMUseCasesTest { @Test public void testMapStringStringValue() throws IOException { + MapMarshaller valueMarshaller = new MapMarshaller<>(new StringBytesReader(), CharSequenceBytesWriter.INSTANCE, + new StringBytesReader(), CharSequenceBytesWriter.INSTANCE); ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Map.class) - .valueMarshaller(MapMarshaller.of(new StringMarshaller(16), new StringMarshaller - (16))); + .valueMarshaller(valueMarshaller); try (ChronicleMap> map = newInstance(builder)) { @@ -2522,10 +2530,12 @@ public class CHMUseCasesTest { @Test public void testMapStringIntegerValue() throws IOException { + MapMarshaller valueMarshaller = new MapMarshaller<>( + new StringBytesReader(), CharSequenceBytesWriter.INSTANCE, + IntegerMarshaller.INSTANCE, IntegerMarshaller.INSTANCE); ChronicleMapBuilder> builder = ChronicleMapBuilder .of(String.class, (Class>) (Class) Map.class) - .valueMarshaller(MapMarshaller.of(new StringMarshaller(16), new - GenericEnumMarshaller(Integer.class, 16))); + .valueMarshaller(valueMarshaller); try (ChronicleMap> map = newInstance(builder)) { map.put("1", Collections.emptyMap()); @@ -2628,9 +2638,16 @@ public class CHMUseCasesTest { @Test public void testBytesMarshallable2() throws IOException { + BytesMarshallableReader dataReader = new BytesMarshallableReader(Data.class) { + @Override + protected Data createInstance() { + return new Data(); + } + }; ChronicleMapBuilder builder = ChronicleMapBuilder .of(Data.class, Data.class) - .keyMarshaller(new BytesMarshallableMarshaller<>(Data.class)) + .keyReaderAndDataAccess(dataReader, new DataDataAccess()) + .valueReaderAndDataAccess(dataReader, new DataDataAccess()) .actualChunkSize(64) .entries(1000); try (ChronicleMap map = newInstance(builder)) { @@ -2647,10 +2664,26 @@ public class CHMUseCasesTest { } } } + + private static class DataDataAccess extends BytesMarshallableDataAccess { + public DataDataAccess() { + super(Data.class); + } + + @Override + protected Data createInstance() { + return new Data(); + } + + @Override + public DataAccess copy() { + return new DataDataAccess(); + } + } } interface IData extends BytesMarshallable { - void setText(@MaxSize String text); + void setText(@MaxUtf8Length(64) String text); void setNumber(int number); @@ -2730,7 +2763,8 @@ interface IBean { void setInt(int i); - void setInnerAt(@MaxSize(7) int index, Inner inner); + @Array(length = 7) + void setInnerAt(int index, Inner inner); Inner getInnerAt(int index); @@ -2740,7 +2774,7 @@ interface IBean { String getMessage(); - void setMessage(@MaxSize(20) String px); + void setMessage(@MaxUtf8Length(20) String px); } } diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java index 74253174f..301300245 100644 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapImportExportTest.java @@ -19,8 +19,8 @@ package net.openhft.chronicle.map; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import net.openhft.chronicle.core.io.Closeable; +import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.map.fromdocs.BondVOInterface; -import net.openhft.lang.values.LongValue; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java index 49a9782d9..5e000a220 100755 --- a/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/ChronicleMapTest.java @@ -19,12 +19,10 @@ package net.openhft.chronicle.map; import com.google.common.collect.HashBiMap; import com.google.common.primitives.Ints; import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.hash.Data; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.DataValueGenerator; -import net.openhft.lang.values.IntValue; -import net.openhft.lang.values.LongValue; -import net.openhft.lang.values.LongValue$$Native; +import net.openhft.chronicle.core.values.IntValue; +import net.openhft.chronicle.core.values.LongValue; +import net.openhft.chronicle.set.Builder; +import net.openhft.chronicle.values.Values; import org.junit.Ignore; import org.junit.Test; @@ -36,7 +34,6 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; -import static net.openhft.chronicle.map.Alignment.*; import static org.junit.Assert.*; @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"}) @@ -87,12 +84,11 @@ public class ChronicleMapTest { } public static LongValue nativeLongValue() { - return new LongValue$$Native(); + return Values.newNativeReference(LongValue.class); } public static IntValue nativeIntValue() { - return DataValueClasses.newDirectReference(IntValue.class); -// return new LongValue$$Native(); + return Values.newNativeReference(IntValue.class); } static File getPersistenceFile() { @@ -519,9 +515,9 @@ public class ChronicleMapTest { ChronicleMapBuilder.of(CharSequence.class, LongValue.class) .averageKey("key") .entries(1000) - .entryAndValueAlignment(OF_4_BYTES) + .entryAndValueOffsetAlignment(4) .create()) { - map.acquireUsing("key", new LongValue$$Native()); + map.acquireUsing("key", Values.newNativeReference(LongValue.class)); assertEquals(0, map.acquireUsing("key", null).getValue()); } } @@ -563,9 +559,9 @@ public class ChronicleMapTest { ChronicleMapBuilder.of(CharSequence.class, LongValue.class) .averageKey("key") .entries(10) - .entryAndValueAlignment(OF_4_BYTES) + .entryAndValueOffsetAlignment(4) .create()) { - map.acquireUsing("key", new LongValue$$Native()); + map.acquireUsing("key", Values.newNativeReference(LongValue.class)); assertEquals(0, map.getUsing("key", null).getValue()); } @@ -577,9 +573,9 @@ public class ChronicleMapTest { ChronicleMapBuilder.of(CharSequence.class, LongValue.class) .averageKey("key") .entries(10) - .entryAndValueAlignment(OF_4_BYTES) + .entryAndValueOffsetAlignment(4) .create()) { - assertNull(map.getUsing("key", DataValueClasses.newDirectReference(LongValue.class))); + assertNull(map.getUsing("key", Values.newNativeReference(LongValue.class))); } } @@ -605,11 +601,11 @@ public class ChronicleMapTest { .entries((long) entries) .minSegments(1) .averageKeySize(10) - .entryAndValueAlignment(OF_4_BYTES) + .entryAndValueOffsetAlignment(4) .create()) { - LongValue value4 = new LongValue$$Native(); - LongValue value22 = new LongValue$$Native(); - LongValue value32 = new LongValue$$Native(); + LongValue value4 = Values.newNativeReference(LongValue.class); + LongValue value22 = Values.newNativeReference(LongValue.class); + LongValue value32 = Values.newNativeReference(LongValue.class); for (int j2 = 1; j2 <= 3; j2++) { for (int i2 = 0; i2 < entries; i2++) { @@ -639,11 +635,11 @@ public class ChronicleMapTest { .entries((long) entries) .minSegments(1) .averageKeySize(10) - .entryAndValueAlignment(NO_ALIGNMENT) + .entryAndValueOffsetAlignment(1) .create()) { - LongValue value1 = new LongValue$$Native(); - LongValue value21 = new LongValue$$Native(); - LongValue value31 = new LongValue$$Native(); + LongValue value1 = Values.newNativeReference(LongValue.class); + LongValue value21 = Values.newNativeReference(LongValue.class); + LongValue value31 = Values.newNativeReference(LongValue.class); for (int j1 = 1; j1 <= 3; j1++) { for (int i1 = 0; i1 < entries; i1++) { @@ -673,11 +669,11 @@ public class ChronicleMapTest { .entries((long) entries) .minSegments(1) .averageKeySize(10) - .entryAndValueAlignment(OF_8_BYTES) + .entryAndValueOffsetAlignment(8) .create()) { - LongValue value = new LongValue$$Native(); - LongValue value2 = new LongValue$$Native(); - LongValue value3 = new LongValue$$Native(); + LongValue value = Values.newNativeReference(LongValue.class); + LongValue value2 = Values.newNativeReference(LongValue.class); + LongValue value3 = Values.newNativeReference(LongValue.class); for (int j = 1; j <= 3; j++) { for (int i = 0; i < entries; i++) { @@ -715,11 +711,11 @@ public class ChronicleMapTest { .entries((long) entries) .minSegments(128) .averageKeySize(10) - .entryAndValueAlignment(NO_ALIGNMENT) + .entryAndValueOffsetAlignment(1) .create()) { CharSequence key2 = getUserCharSequence(0); - map2.acquireUsing(key2, new LongValue$$Native()); + map2.acquireUsing(key2, Values.newNativeReference(LongValue.class)); int iterations2 = 10000; int noOfThreads2 = 10; @@ -735,18 +731,18 @@ public class ChronicleMapTest { } assertEquals(noOfThreads2 * iterations2, - map2.acquireUsing(key2, new LongValue$$Native()).getValue()); + map2.acquireUsing(key2, Values.newNativeReference(LongValue.class)).getValue()); try (ChronicleMap map1 = ChronicleMapBuilder.of(CharSequence .class, LongValue.class) .entries((long) entries) .minSegments(128) .averageKeySize(10) - .entryAndValueAlignment(OF_4_BYTES) + .entryAndValueOffsetAlignment(4) .create()) { CharSequence key1 = getUserCharSequence(0); - map1.acquireUsing(key1, new LongValue$$Native()); + map1.acquireUsing(key1, Values.newNativeReference(LongValue.class)); int iterations1 = 10000; int noOfThreads1 = 10; @@ -762,18 +758,18 @@ public class ChronicleMapTest { } assertEquals(noOfThreads1 * iterations1, - map1.acquireUsing(key1, new LongValue$$Native()).getValue()); + map1.acquireUsing(key1, Values.newNativeReference(LongValue.class)).getValue()); try (ChronicleMap map = ChronicleMapBuilder.of(CharSequence .class, LongValue.class) .entries((long) entries) .minSegments(128) .averageKeySize(10) - .entryAndValueAlignment(OF_8_BYTES) + .entryAndValueOffsetAlignment(8) .create()) { CharSequence key = getUserCharSequence(0); - map.acquireUsing(key, new LongValue$$Native()); + map.acquireUsing(key, Values.newNativeReference(LongValue.class)); int iterations = 10000; int noOfThreads = 10; @@ -789,7 +785,7 @@ public class ChronicleMapTest { } assertEquals(noOfThreads * iterations, - map.acquireUsing(key, new LongValue$$Native()).getValue()); + map.acquireUsing(key, Values.newNativeReference(LongValue.class)).getValue()); } } @@ -797,14 +793,6 @@ public class ChronicleMapTest { } - @Test - public void testIntValue() { - DataValueGenerator dvg = new DataValueGenerator(); - dvg.setDumpCode(true); - dvg.acquireNativeClass(IntValue.class); - dvg.acquireNativeClass(LongValue.class); - } - @Test public void testLargerEntries() { for (int segments : new int[]{128, 256, 512, 1024}) { @@ -1001,7 +989,7 @@ public class ChronicleMapTest { } - static final LongValue ONE = DataValueClasses.newInstance(LongValue.class); + static final LongValue ONE = Values.newHeapInstance(LongValue.class); static { ONE.setValue(1); @@ -1023,7 +1011,7 @@ public class ChronicleMapTest { ChronicleMapBuilder builder = ChronicleMapBuilder .of(CharSequence.class, LongValue.class) .entries(entries) - .entryAndValueAlignment(OF_8_BYTES) + .entryAndValueOffsetAlignment(8) .actualSegments(256) .averageKeySize(13); @@ -1038,7 +1026,7 @@ public class ChronicleMapTest { for (int j = 0; j < count; j++) { long start = System.currentTimeMillis(); - List futures = new ArrayList(); + List futures = new ArrayList<>(); for (int i = 0; i < threads; i++) { final int t = i; futures.add(es.submit(new Runnable() { @@ -1064,7 +1052,8 @@ public class ChronicleMapTest { MapEntry entry = c.entry(); if (entry != null) { // Attempt to pass abstraction hierarchies - Data v = entry.value(); + net.openhft.chronicle.hash.Data v = + entry.value(); n = v.bytes().readVolatileLong(v.offset()) + 1; } else { n = 1; @@ -1076,7 +1065,7 @@ public class ChronicleMapTest { c.updateLock().lock(); MapEntry entry = c.entry(); if (entry != null) { - Data v = entry.value(); + net.openhft.chronicle.hash.Data v = entry.value(); n = ((BytesStore) v.bytes()).addAndGetLong( v.offset(), 1); } else { @@ -1137,7 +1126,7 @@ public class ChronicleMapTest { futures.add(es.submit(new Runnable() { @Override public void run() { - LongValue key = DataValueClasses.newDirectInstance(LongValue.class); + LongValue key = Values.newHeapInstance(LongValue.class); LongValue value = nativeLongValue(); long next = 50 * 1000 * 1000; // use a factor to give up to 10 digit numbers. @@ -1733,7 +1722,7 @@ public class ChronicleMapTest { @Override public void run() { try { - LongValue value = new LongValue$$Native(); + LongValue value = Values.newNativeReference(LongValue.class); barrier.await(); for (int i = 0; i < iterations; i++) { map.acquireUsing(key, value); @@ -1833,8 +1822,7 @@ public class ChronicleMapTest { ChronicleMapBuilder builder = ChronicleMapBuilder .of(CharSequence.class, String.class) .averageKey("one").averageValue("") - .entries(1000) - .defaultValue(""); + .entries(1000); try (final ChronicleMap map = builder.create()) { // this will add the entry @@ -1852,7 +1840,6 @@ public class ChronicleMapTest { .entries(1000) .averageKeySize("one".length()) .averageValueSize("Hello World".length()) - .defaultValue("") .create()) { StringBuilder value = new StringBuilder(); @@ -1874,7 +1861,7 @@ public class ChronicleMapTest { .entries(1000) .averageKeySize("one".length()).createPersistedTo(tmpFile)) { - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); try (ExternalMapQueryContext c = map.queryContext("one")) { assertNotNull(c.absentEntry()); diff --git a/src/test/java/net/openhft/chronicle/map/ConstantSizeBySampleTest.java b/src/test/java/net/openhft/chronicle/map/ConstantSizeBySampleTest.java index 6499bf3f2..684040f0a 100644 --- a/src/test/java/net/openhft/chronicle/map/ConstantSizeBySampleTest.java +++ b/src/test/java/net/openhft/chronicle/map/ConstantSizeBySampleTest.java @@ -16,6 +16,9 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.hash.serialization.impl.ExternalizableDataAccess; +import net.openhft.chronicle.hash.serialization.impl.ExternalizableReader; import org.junit.Assert; import org.junit.Test; @@ -31,7 +34,6 @@ public class ConstantSizeBySampleTest { public void testConstantKeys() throws IOException { ChronicleMap map = ChronicleMapBuilder.of(byte[].class, Long.class) .constantKeySizeBySample(new byte[8]) - .immutableKeys() .entries(100) .create(); @@ -87,6 +89,13 @@ public class ConstantSizeBySampleTest { public void testUnexpectedlyLongConstantExternalizableValues() throws IOException { try ( ChronicleMap map = ChronicleMapBuilder.of(Long.class, ExternalizableData.class) + .valueReaderAndDataAccess(new ExternalizableReader( + ExternalizableData.class) { + @Override + protected ExternalizableData createInstance() { + return new ExternalizableData(); + } + }, new ExternalizableDataDataAccess()) .constantValueSizeBySample(new ExternalizableData()) .entries(100) .actualSegments(1) @@ -123,4 +132,21 @@ public class ConstantSizeBySampleTest { Assert.assertEquals(map.get(1L), value); } } + + private static class ExternalizableDataDataAccess + extends ExternalizableDataAccess { + public ExternalizableDataDataAccess() { + super(ExternalizableData.class); + } + + @Override + protected ExternalizableData createInstance() { + return new ExternalizableData(); + } + + @Override + public DataAccess copy() { + return new ExternalizableDataDataAccess(); + } + } } diff --git a/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java b/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java index 569d3c685..f1721e764 100644 --- a/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java @@ -16,10 +16,9 @@ package net.openhft.chronicle.map; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; -import net.openhft.lang.values.LongValue; +import net.openhft.chronicle.core.values.IntValue; +import net.openhft.chronicle.core.values.LongValue; +import net.openhft.chronicle.values.Values; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -31,25 +30,23 @@ public class DataKeyValueTest { ChronicleMap map = ChronicleMapBuilder.of(IntValue.class, LongValue.class) .entries(1000).create(); - IntValue heapKey = DataValueClasses.newInstance(IntValue.class); - IntValue directKey = DataValueClasses.newDirectInstance(IntValue.class); - LongValue heapValue = DataValueClasses.newInstance(LongValue.class); - LongValue directValue = DataValueClasses.newDirectInstance(LongValue.class); + IntValue heapKey = Values.newHeapInstance(IntValue.class); + LongValue heapValue = Values.newHeapInstance(LongValue.class); + LongValue directValue = Values.newNativeReference(LongValue.class); heapKey.setValue(1); heapValue.setValue(1); map.put(heapKey, heapValue); assertEquals(1, map.get(heapKey).getValue()); - assertEquals(1, map.getUsing(heapKey, directValue).getValue()); + assertEquals(1, map.getUsing(heapKey, heapValue).getValue()); - ((Byteable) directValue).bytes(null, 0L); - directKey.setValue(1); - map.getUsing(directKey, directValue).addValue(1); - assertEquals(2, map.getUsing(directKey, heapValue).getValue()); + heapKey.setValue(1); + map.getUsing(heapKey, directValue).addValue(1); + assertEquals(2, map.getUsing(heapKey, heapValue).getValue()); - directKey.setValue(2); + heapKey.setValue(2); heapValue.setValue(3); - map.put(directKey, heapValue); - assertEquals(3, map.get(directKey).getValue()); + map.put(heapKey, heapValue); + assertEquals(3, map.get(heapKey).getValue()); } } diff --git a/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java b/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java index 397704473..a975d8364 100644 --- a/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java @@ -16,6 +16,12 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.hash.*; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.ListMarshaller; +import net.openhft.chronicle.hash.serialization.impl.IntegerMarshaller; +import net.openhft.chronicle.set.Builder; +import org.jetbrains.annotations.NotNull; import org.junit.Test; import java.io.File; @@ -35,10 +41,15 @@ public class DefaultValueTest { ArrayList defaultValue = new ArrayList(); defaultValue.add(42); + ListMarshaller valueMarshaller = + new ListMarshaller<>(IntegerMarshaller.INSTANCE, IntegerMarshaller.INSTANCE); try (ChronicleMap> map = ChronicleMapBuilder .of(String.class, (Class>) ((Class) List.class)) + .valueMarshaller(valueMarshaller) .averageKey("a").averageValue(Arrays.asList(1, 2)) - .defaultValue(defaultValue).createPersistedTo(file)) { + .defaultValueProvider(absentEntry -> + absentEntry.context().wrapValueAsData(defaultValue)) + .createPersistedTo(file)) { ArrayList using = new ArrayList(); assertEquals(defaultValue, map.acquireUsing("a", using)); assertEquals(1, map.size()); @@ -51,6 +62,8 @@ public class DefaultValueTest { try (ChronicleMap> map = ChronicleMapBuilder .of(String.class, (Class>) ((Class) List.class)) .averageKey("a").averageValue(Arrays.asList(1, 2)) + .defaultValueProvider(absentEntry -> + absentEntry.context().wrapValueAsData(defaultValue)) .createPersistedTo(file)) { assertEquals(defaultValue, map.acquireUsing("c", using)); } diff --git a/src/test/java/net/openhft/chronicle/map/DeflatorStringMarshaller.java b/src/test/java/net/openhft/chronicle/map/DeflatorStringMarshaller.java index c1ba0607b..96f9d8b89 100644 --- a/src/test/java/net/openhft/chronicle/map/DeflatorStringMarshaller.java +++ b/src/test/java/net/openhft/chronicle/map/DeflatorStringMarshaller.java @@ -16,22 +16,22 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.IORuntimeException; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.CompactBytesMarshaller; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.reflect.Constructor; -import java.nio.ByteBuffer; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; /** * Created by peter on 24/10/14. */ -public enum DeflatorStringMarshaller implements CompactBytesMarshaller { +public enum DeflatorStringMarshaller + implements BytesReader, BytesWriter { INSTANCE; private static final StringFactory STRING_FACTORY = getStringFactory(); @@ -54,27 +54,22 @@ public enum DeflatorStringMarshaller implements CompactBytesMarshaller map) { - LongValue longValue = newDirectReference(LongValue.class); + LongValue longValue = newNativeReference(LongValue.class); try { for (int j = 0; j < moreThanMaxSize(maxSize); j++) { String key = "key:" + counter; diff --git a/src/test/java/net/openhft/chronicle/map/EventListenerWithTCPSocketReplicationTest.java b/src/test/java/net/openhft/chronicle/map/EventListenerWithTCPSocketReplicationTest.java index c0383e375..536a308f0 100644 --- a/src/test/java/net/openhft/chronicle/map/EventListenerWithTCPSocketReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/EventListenerWithTCPSocketReplicationTest.java @@ -191,7 +191,7 @@ public class EventListenerWithTCPSocketReplicationTest { Assert.assertTrue("The eventListener.onPut should have been called", putWasCalled.get()); Assert.assertEquals(Integer.valueOf(5), keyRef.get()); Assert.assertEquals("EXAMPLE", valueRef.get()); - Assert.assertEquals("WILL_GET_OVER-WRITTEN", replacedValueRef.get()); + Assert.assertEquals("WILL_GET_OVER-WRITTEN", replacedValueRef.get().toString()); } @Test @@ -219,7 +219,7 @@ public class EventListenerWithTCPSocketReplicationTest { Assert.assertTrue("The eventListener.onPut should have been called", putWasCalled.get()); Assert.assertEquals(Integer.valueOf(5), keyRef.get()); - Assert.assertEquals("small", replacedValueRef.get()); + Assert.assertEquals("small", replacedValueRef.get().toString()); Assert.assertEquals("EXAMPLE", valueRef.get()); } @@ -256,7 +256,7 @@ public class EventListenerWithTCPSocketReplicationTest { Assert.assertTrue(!putWasCalled.get()); Assert.assertTrue(wasRemoved.get()); - Assert.assertEquals("WILL_GET_REMOVED", valueRemoved.get()); + Assert.assertEquals("WILL_GET_REMOVED", valueRemoved.get().toString()); Assert.assertEquals(null, map2.get(5)); } diff --git a/src/test/java/net/openhft/chronicle/map/FirstPrimitiveFieldTest.java b/src/test/java/net/openhft/chronicle/map/FirstPrimitiveFieldTest.java deleted file mode 100644 index 1d4b0a74c..000000000 --- a/src/test/java/net/openhft/chronicle/map/FirstPrimitiveFieldTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.chronicle.map.fromdocs.BondVOInterface; -import net.openhft.lang.model.DataValueGenerator; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; - -import static org.hamcrest.CoreMatchers.hasItem; - -public class FirstPrimitiveFieldTest { - @Test - public void firstPrimitiveFieldTest() { - Assert.assertThat(Arrays.asList(long.class, double.class), - hasItem(DataValueGenerator.firstPrimitiveFieldType(BondVOInterface.class))); - } -} diff --git a/src/test/java/net/openhft/chronicle/map/GlobalMutableStateTest.java b/src/test/java/net/openhft/chronicle/map/GlobalMutableStateTest.java index fd05cbd11..e8821217d 100644 --- a/src/test/java/net/openhft/chronicle/map/GlobalMutableStateTest.java +++ b/src/test/java/net/openhft/chronicle/map/GlobalMutableStateTest.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.VanillaGlobalMutableState; -import net.openhft.lang.model.DataValueClasses; +import net.openhft.chronicle.values.Values; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -42,7 +42,7 @@ public class GlobalMutableStateTest { @Test public void globalMutableStateTest() { - DataValueClasses.newDirectReference(ReplicatedGlobalMutableState.class); - DataValueClasses.newDirectReference(VanillaGlobalMutableState.class); + Values.newNativeReference(ReplicatedGlobalMutableState.class); + Values.newNativeReference(VanillaGlobalMutableState.class); } } diff --git a/src/test/java/net/openhft/chronicle/map/IntValueMapTest.java b/src/test/java/net/openhft/chronicle/map/IntValueMapTest.java index 337a3da8e..bca22c45b 100644 --- a/src/test/java/net/openhft/chronicle/map/IntValueMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/IntValueMapTest.java @@ -16,13 +16,13 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.values.IntValue; -import net.openhft.lang.values.IntValue$$Native; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.NativeBytesStore; +import net.openhft.chronicle.core.values.IntValue; +import net.openhft.chronicle.values.Values; import org.junit.Test; import java.io.IOException; -import java.nio.ByteBuffer; import static org.junit.Assert.assertEquals; @@ -38,8 +38,8 @@ public class IntValueMapTest { .of(IntValue.class, CharSequence.class) .averageValue("test") .entries(20000).create()) { - IntValue$$Native value = new IntValue$$Native(); - value.bytes(new ByteBufferBytes(ByteBuffer.allocateDirect(4)), 0); + IntValue value = Values.newNativeReference(IntValue.class); + ((Byteable) value).bytesStore(NativeBytesStore.nativeStoreWithFixedCapacity(4), 0, 4); value.setValue(1); final String expected = "test"; diff --git a/src/test/java/net/openhft/chronicle/map/Issue37Test.java b/src/test/java/net/openhft/chronicle/map/Issue37Test.java index 060f4ec18..bc720cc36 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue37Test.java +++ b/src/test/java/net/openhft/chronicle/map/Issue37Test.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.replication.ReplicationHub; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; +import net.openhft.chronicle.set.Builder; import org.junit.Test; import java.io.File; diff --git a/src/test/java/net/openhft/chronicle/map/Issue42Test.java b/src/test/java/net/openhft/chronicle/map/Issue42Test.java index b8de5cc0f..857f76946 100755 --- a/src/test/java/net/openhft/chronicle/map/Issue42Test.java +++ b/src/test/java/net/openhft/chronicle/map/Issue42Test.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.map; -import net.openhft.lang.Jvm; +import net.openhft.chronicle.core.OS; import org.junit.Assert; import org.junit.Test; @@ -27,7 +27,7 @@ public class Issue42Test { @Test public void crashJVMWindowsTest() throws IOException { - if (!Jvm.isWindows()) + if (!OS.isWindows()) return; try (final ChronicleMap map = ChronicleMapBuilder diff --git a/src/test/java/net/openhft/chronicle/map/Issue43Test.java b/src/test/java/net/openhft/chronicle/map/Issue43Test.java index e7c6a7233..18f1d5e83 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue43Test.java +++ b/src/test/java/net/openhft/chronicle/map/Issue43Test.java @@ -16,8 +16,10 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshaller; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.chronicle.set.Builder; import org.junit.Test; public class Issue43Test { @@ -50,7 +52,8 @@ public class Issue43Test { } } - private static class ArrayMarshaller implements BytesMarshaller { + private static class ArrayMarshaller + implements BytesReader, BytesWriter { @Override public void write(Bytes bytes, ValueWrapper vw) { @@ -62,14 +65,8 @@ public class Issue43Test { } @Override - public ValueWrapper read(Bytes bytes) { + public ValueWrapper read(Bytes in, ValueWrapper using) { throw new UnsupportedOperationException("Not supported yet."); } - - @Override - public ValueWrapper read(Bytes arg0, ValueWrapper arg1) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/src/test/java/net/openhft/chronicle/map/Issue58.java b/src/test/java/net/openhft/chronicle/map/Issue58.java index 80999d0b1..60c6dcc33 100644 --- a/src/test/java/net/openhft/chronicle/map/Issue58.java +++ b/src/test/java/net/openhft/chronicle/map/Issue58.java @@ -16,9 +16,11 @@ 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 net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -57,12 +59,12 @@ public class Issue58 { try ( ChronicleMap map = ChronicleMap.of(String.class, UUID.class) .averageKeySize(2) - .valueMarshaller(UuidMarshaller.INSTANCE) + .valueMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .constantValueSizeBySample(UUID.randomUUID()) .entries(data.size()) .createPersistedTo(mapFile); ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) - .keyMarshaller(UuidMarshaller.INSTANCE) + .keyMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .averageValueSize(2) .constantKeySizeBySample(UUID.randomUUID()) .entries(data.size()) @@ -81,12 +83,12 @@ public class Issue58 { try ( ChronicleMap map = ChronicleMap.of(String.class, UUID.class) .averageKeySize(2) - .valueMarshaller(UuidMarshaller.INSTANCE) + .valueMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .constantValueSizeBySample(UUID.randomUUID()) .entries(data.size()) .createPersistedTo(mapFile); ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) - .keyMarshaller(UuidMarshaller.INSTANCE) + .keyMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .constantKeySizeBySample(UUID.randomUUID()) .averageValueSize(2) .entries(data.size()) @@ -103,12 +105,12 @@ public class Issue58 { try ( ChronicleMap map = ChronicleMap.of(String.class, UUID.class) .averageKeySize(2) - .valueMarshaller(UuidMarshaller.INSTANCE) + .valueMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .constantValueSizeBySample(UUID.randomUUID()) .entries(data.size()) .createPersistedTo(mapFile); ChronicleMap reverseMap = ChronicleMap.of(UUID.class, String.class) - .keyMarshaller(UuidMarshaller.INSTANCE) + .keyMarshallers(UuidMarshaller.INSTANCE, UuidMarshaller.INSTANCE) .constantKeySizeBySample(UUID.randomUUID()) .averageValueSize(2) .entries(data.size()) @@ -126,23 +128,18 @@ public class Issue58 { } - enum UuidMarshaller implements BytesMarshaller { + enum UuidMarshaller implements BytesReader, BytesWriter { INSTANCE; @Override - public void write(Bytes bytes, UUID uuid) { + public void write(Bytes bytes, @NotNull UUID uuid) { bytes.writeLong(uuid.getMostSignificantBits()); bytes.writeLong(uuid.getLeastSignificantBits()); } @Override - public UUID read(Bytes bytes) { + public UUID read(Bytes bytes, @Nullable UUID using) { return new UUID(bytes.readLong(), bytes.readLong()); } - - @Override - public UUID read(Bytes bytes, @Nullable UUID uuid) { - return read(bytes); - } } } diff --git a/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java b/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java index 198dc4678..8851fdff0 100644 --- a/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java +++ b/src/test/java/net/openhft/chronicle/map/KeyValueInstanceTest.java @@ -21,6 +21,7 @@ import org.junit.Test; import java.util.HashMap; import java.util.Map; +import static net.openhft.chronicle.values.ValueModel.$$HEAP; import static org.junit.Assert.assertTrue; /** @@ -89,7 +90,7 @@ public class KeyValueInstanceTest { map.newKeyInstance(); Object value = map.newValueInstance(); - assertTrue(value.getClass().getCanonicalName().endsWith("$$Native")); + assertTrue(value.getClass().getCanonicalName().endsWith($$HEAP)); } diff --git a/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java b/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java index d509b5e80..3d7bfeaa9 100755 --- a/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java +++ b/src/test/java/net/openhft/chronicle/map/LargeEntriesTest.java @@ -16,9 +16,6 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.DirectBytes; -import net.openhft.lang.io.DirectStore; -import net.openhft.lang.io.serialization.impl.SnappyStringMarshaller; import org.junit.Ignore; import org.junit.Test; @@ -45,7 +42,7 @@ public class LargeEntriesTest { file.deleteOnExit(); try (final ChronicleMap map = ChronicleMapBuilder .of(String.class, String.class) - .valueMarshaller(SnappyStringMarshaller.INSTANCE) +// .valueReaderAndDataAccess(, SnappyStringMarshaller.INSTANCE, ) .actualSegments(1) // to force an error. .entries(ENTRIES) .averageKeySize(10) @@ -85,16 +82,16 @@ public class LargeEntriesTest { } private void warmUpCompression(int entrySize) { - String value = generateValue(entrySize); - DirectBytes bytes = DirectStore.allocate(entrySize / 6).bytes(); - for (int i = 0; i < 5; i++) { - // warmup to compression. - bytes.clear(); - SnappyStringMarshaller.INSTANCE.write(bytes, value); - bytes.flip(); - SnappyStringMarshaller.INSTANCE.read(bytes); - } - bytes.release(); +// String value = generateValue(entrySize); +// DirectBytes bytes = DirectStore.allocate(entrySize / 6).bytes(); +// for (int i = 0; i < 5; i++) { +// // warmup to compression. +// bytes.clear(); +// SnappyStringMarshaller.INSTANCE.write(bytes, value); +// bytes.flip(); +// SnappyStringMarshaller.INSTANCE.read(bytes); +// } +// bytes.release(); } @Test @@ -113,7 +110,7 @@ public class LargeEntriesTest { file.deleteOnExit(); final ChronicleMap map = ChronicleMapBuilder .of(String.class, String.class) - .valueMarshaller(SnappyStringMarshaller.INSTANCE) +// .valueReaderAndDataAccess(, SnappyStringMarshaller.INSTANCE, ) .entries(ENTRIES) .averageKeySize(10) .averageValueSize(ENTRY_SIZE) diff --git a/src/test/java/net/openhft/chronicle/map/LataTest.java b/src/test/java/net/openhft/chronicle/map/LataTest.java index 250eb8531..25f1a8880 100644 --- a/src/test/java/net/openhft/chronicle/map/LataTest.java +++ b/src/test/java/net/openhft/chronicle/map/LataTest.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map; -import net.openhft.lang.values.StringValue; +import net.openhft.chronicle.values.MaxUtf8Length; public class LataTest { @@ -67,4 +67,9 @@ public class LataTest { } map.close(); } + + interface StringValue { + CharSequence getValue(); + void setValue(@MaxUtf8Length(64) CharSequence value); + } } diff --git a/src/test/java/net/openhft/chronicle/map/MapByNameTest.java b/src/test/java/net/openhft/chronicle/map/MapByNameTest.java deleted file mode 100644 index b43124cd3..000000000 --- a/src/test/java/net/openhft/chronicle/map/MapByNameTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.chronicle.hash.replication.ReplicationHub; -import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import static junit.framework.Assert.assertEquals; - -/** - * @author Rob Austin. - */ -@Ignore -public class MapByNameTest { - - private ReplicationHubFindByName findMapByName; - - @Before - public void setUp() throws IOException { - final ReplicationHub replicationHub = ReplicationHub.builder() - .tcpTransportAndNetwork(TcpTransportAndNetworkConfig.of(8243)) - .createWithId((byte) 1); - - findMapByName = new ReplicationHubFindByName(replicationHub); - } - - @Test - public void testSerializingBuilder() throws TimeoutException, InterruptedException, IOException { - - final MapInstanceBuilder config = - (MapInstanceBuilder) - ChronicleMapBuilder.of(CharSequence.class, CharSequence.class) - .averageKeySize("hello".length()).averageValueSize("world".length()) - .entries(2) - .minSegments(2) - .replication((byte) 1, TcpTransportAndNetworkConfig.of(8244)) - .removeReturnsNull(true) - .instance().name("map1"); - - final ChronicleMap map = findMapByName.create(config); - map.put("hello", "world"); - - assertEquals(map.get("hello"), "world"); - } - - // @Test(expected = IllegalArgumentException.class) - // public void testSerializingBuilderUnknownMap() throws TimeoutException, InterruptedException { - // findMapByName.get("hello"); - // } - - @Test - @Ignore("currently work in progress") - public void testConnectByName() throws IOException, InterruptedException, TimeoutException { - - NodeDiscovery nodeDiscovery = new NodeDiscovery(); - - MapInstanceBuilder config = - (MapInstanceBuilder) - ChronicleMapBuilder.of(CharSequence.class, CharSequence.class) - .minSegments(2) - .removeReturnsNull(true) - .instance() - .name("myMap"); - - ReplicationHubFindByName mapByName = nodeDiscovery.mapByName(); - // mapByName.add(config); - - ChronicleMap myMap2 = mapByName.from("myMap"); - } - - @Ignore("causing issues on windows") - @Test - public void testReplicationHubSerialization() throws IOException, InterruptedException, - TimeoutException { - NodeDiscovery nodeDiscovery = new NodeDiscovery(); - - final ReplicationHubFindByName mapByName = nodeDiscovery.mapByName(); - Thread.sleep(2000); - - MapInstanceBuilder config = - (MapInstanceBuilder) - ChronicleMapBuilder.of(CharSequence.class, CharSequence.class) - .minSegments(2) - .entries(2) - .removeReturnsNull(true) - .instance() - .name("myMap6"); - - mapByName.create(config); - - } - - public static void main(String... args) throws IOException, InterruptedException, TimeoutException { - NodeDiscovery nodeDiscovery = new NodeDiscovery(); - - final ReplicationHubFindByName mapByName = nodeDiscovery.mapByName(); - Thread.sleep(2000); - - MapInstanceBuilder config = - (MapInstanceBuilder) - ChronicleMapBuilder.of(CharSequence.class, CharSequence.class) - .minSegments(2) - .entries(2) - .removeReturnsNull(true) - .instance() - .name("myMap6"); - - ChronicleMap map = mapByName.create(config); - map.put("hello", "world"); - - // final ChronicleMap map = mapByName.from("myMap5"); - - // allow time for replication - Thread.sleep(2000); - System.out.print(map); - - map.close(); - } - -} diff --git a/src/test/java/net/openhft/chronicle/map/MarkTest.java b/src/test/java/net/openhft/chronicle/map/MarkTest.java index 61714c44e..a2a5e6c4b 100644 --- a/src/test/java/net/openhft/chronicle/map/MarkTest.java +++ b/src/test/java/net/openhft/chronicle/map/MarkTest.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.map; -import net.openhft.lang.MemoryUnit; +import net.openhft.chronicle.algo.MemoryUnit; import org.junit.Test; import java.io.File; diff --git a/src/test/java/net/openhft/chronicle/map/NodeDiscoveryBroadcasterTest.java b/src/test/java/net/openhft/chronicle/map/NodeDiscoveryBroadcasterTest.java deleted file mode 100644 index 07f304ad0..000000000 --- a/src/test/java/net/openhft/chronicle/map/NodeDiscoveryBroadcasterTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 junit.framework.TestCase; -import net.openhft.lang.io.ByteBufferBytes; -import org.junit.Assert; -import org.junit.Test; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.concurrent.atomic.AtomicReference; - -import static java.nio.ByteBuffer.allocate; - -public class NodeDiscoveryBroadcasterTest extends TestCase { - - public static final int SERVER2_IDENTIFER = 10; - public static final int PROPOSED_IDENTIFIER = 5; - - @Test - public void testsTheSerializationOfTheNodeDiscovery() throws IOException, InterruptedException { - - AtomicReference ref = new AtomicReference(); - final AddressAndPort ourAddressAndPort1 = new AddressAndPort(InetAddress.getLocalHost() - .getAddress(), - (short) 1024); - - final AddressAndPort ourAddressAndPort2 = new AddressAndPort(InetAddress.getLocalHost() - .getAddress(), - (short) 1025); - - // write broadcast our address on the bootstrap method - byte[] server1Address = Inet4Address.getLocalHost().getAddress(); - AddressAndPort server1AddressAndPort = new AddressAndPort(server1Address, (short) 1234); - - // write broadcast our address on the bootstrap method - byte[] server2Address = Inet4Address.getByName("129.168.0.2").getAddress(); - AddressAndPort server2AddressAndPort = new AddressAndPort(server1Address, (short) 1234); - - KnownNodes server1KnownNodes = new KnownNodes(); - DiscoveryNodeBytesMarshallable server1BytesExternalizable = new DiscoveryNodeBytesMarshallable - (server1KnownNodes, ref, ourAddressAndPort1); - - // for the unit test we are using a ByteBufferBytes, but iltimately this data would have been send - // and received via UDP - ByteBufferBytes udpData = new ByteBufferBytes(allocate(1024)); - - // SERER1 - is the new node join the cluster - // we will first send the bootstrap along with our host and port - { - final DiscoveryNodeBytesMarshallable.ProposedNodes proposedNodes = new - DiscoveryNodeBytesMarshallable.ProposedNodes(server1AddressAndPort, (byte) -1); - server1BytesExternalizable.sendBootStrap(proposedNodes); - server1BytesExternalizable.writeMarshallable(udpData); - } - - KnownNodes server2KnownNodes = new KnownNodes(); - server2KnownNodes.add(server2AddressAndPort, (byte) SERVER2_IDENTIFER); - DiscoveryNodeBytesMarshallable server2BytesExternalizable = new DiscoveryNodeBytesMarshallable - (server2KnownNodes, ref, ourAddressAndPort2); - - // add our identifier and host:port to the list of known identifiers - - // SERVER 2 - is the node already in the cluster - // read the bootstrap along with the host and port it came from - { - udpData.flip(); - server2BytesExternalizable.readMarshallable(udpData); - - Assert.assertTrue(server2BytesExternalizable.proposedIdentifiersWithHost.values().contains - (new DiscoveryNodeBytesMarshallable.ProposedNodes(server1AddressAndPort, (byte) -1))); - } - - // SERVER 2 - // write/broadcast the the response to receiving a bootstrap message - - { - //ByteBufferBytes bitSetBytes = new ByteBufferBytes(allocate(128 / 8)); - // final DirectBitSet knownIdentifiers = new ATSDirectBitSet(bitSetBytes); - - // RemoteNodes remoteNodes = new RemoteNodes(bitSetBytes); - - udpData.clear(); - - // broadcasts in response to the bootstrap all the host:ports and identifiers that it knows about - // in this case given that there is only this node in the grid and one node joining, - // it will only be the node that has the bootstrap and this node, who's data will be sent - server2BytesExternalizable.writeMarshallable(udpData); - } - - // SERER1 - // receive - - // read the bootstrap along with the host and port it came from - { - udpData.flip(); - server1BytesExternalizable.readMarshallable(udpData); - - Assert.assertTrue(server1BytesExternalizable.getRemoteNodes().addressAndPorts().contains - (server2AddressAndPort)); - - Assert.assertTrue(server1BytesExternalizable.getRemoteNodes().identifiers().get - (SERVER2_IDENTIFER)); - } - - // SERVER 1 - // send/broadcast - propose an identifier to use, by choosing one that is not used already - // for the purpose of this test we wont choose one at random ( as the code does ) but just pick - // identifier=5 - - { - udpData.clear(); - - KnownNodes knownNodes = new KnownNodes(); - - DiscoveryNodeBytesMarshallable bytesExternalizable = new DiscoveryNodeBytesMarshallable - (knownNodes, ref, ourAddressAndPort1); - - DiscoveryNodeBytesMarshallable.ProposedNodes proposedNodes = new DiscoveryNodeBytesMarshallable.ProposedNodes(server1AddressAndPort, (byte) PROPOSED_IDENTIFIER); - - // send the bootstrap along with this newly proposed identifier - bytesExternalizable.sendBootStrap(proposedNodes); - - bytesExternalizable.writeMarshallable(udpData); - } - - // SERVER 2 - is the node already in the cluster - // read the bootstrap along with the proposed identifier and host:port it came from - { - udpData.flip(); - server2BytesExternalizable.readMarshallable(udpData); - - Assert.assertTrue(server2BytesExternalizable.proposedIdentifiersWithHost.values().contains - (new DiscoveryNodeBytesMarshallable.ProposedNodes(server1AddressAndPort, (byte) PROPOSED_IDENTIFIER))); - } - - // SERVER 2 - // write/broadcast the the response to receiving a bootstrap message - { - //ByteBufferBytes bitSetBytes = new ByteBufferBytes(allocate(128 / 8)); - // final DirectBitSet knownIdentifiers = new ATSDirectBitSet(bitSetBytes); - - // RemoteNodes remoteNodes = new RemoteNodes(bitSetBytes); - - udpData.clear(); - - // broadcasts in response to the bootstrap all the host:ports and identifiers that it knows about - // in this case given that there is only this node in the grid and one node joining, - // it will only be the node that has the bootstrap and this node, who's data will be sent - server2BytesExternalizable.writeMarshallable(udpData); - } - - // SERVER 1 - // read the bootstrap along with all the proposed identifiers ( this will include our - // PROPOSED_IDENTIFIER and any that come from other server - { - udpData.flip(); - server1BytesExternalizable.readMarshallable(udpData); - - Assert.assertTrue(server1BytesExternalizable.getRemoteNodes().addressAndPorts().contains - (server2AddressAndPort)); - - Assert.assertTrue(server1BytesExternalizable.getRemoteNodes().identifiers().get - (SERVER2_IDENTIFER)); - - Assert.assertTrue(server1BytesExternalizable.proposedIdentifiersWithHost.values().contains - (new DiscoveryNodeBytesMarshallable.ProposedNodes(server1AddressAndPort, (byte) PROPOSED_IDENTIFIER))); - } - } - -} diff --git a/src/test/java/net/openhft/chronicle/map/OSResizesMain.java b/src/test/java/net/openhft/chronicle/map/OSResizesMain.java index 330c15f1d..38ec520c4 100755 --- a/src/test/java/net/openhft/chronicle/map/OSResizesMain.java +++ b/src/test/java/net/openhft/chronicle/map/OSResizesMain.java @@ -16,7 +16,7 @@ package net.openhft.chronicle.map; -import net.openhft.lang.Jvm; +import net.openhft.chronicle.core.OS; import java.io.*; import java.util.Arrays; @@ -49,7 +49,7 @@ public class OSResizesMain { Double.parseDouble(run("head", "-1", "/proc/meminfo").split("\\s+")[1]) / 1e6, file.length() / 1e9, run("du", "-h", file.getAbsolutePath()).split("\\s")[0], - run("grep", "over-sized", "/proc/" + Jvm.getProcessId() + "/maps").split("\\s")[0]); + run("grep", "over-sized", "/proc/" + OS.getProcessId() + "/maps").split("\\s")[0]); // show up in top. long time = System.currentTimeMillis(); while (time + 30000 > System.currentTimeMillis()) diff --git a/src/test/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupTest.java b/src/test/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupTest.java index c58d757c5..8301c4bed 100644 --- a/src/test/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupTest.java +++ b/src/test/java/net/openhft/chronicle/map/OldDeletedEntriesCleanupTest.java @@ -17,12 +17,13 @@ package net.openhft.chronicle.map; import com.google.common.collect.Maps; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.core.values.IntValue; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; +import net.openhft.chronicle.set.Builder; +import net.openhft.chronicle.values.Values; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -44,8 +45,8 @@ public class OldDeletedEntriesCleanupTest { @Before public void setup() throws IOException { - IntValue value = DataValueClasses.newDirectReference(IntValue.class); - ((Byteable) value).bytes(new ByteBufferBytes(ByteBuffer.allocateDirect(4)), 0); + IntValue value = Values.newNativeReference(IntValue.class); + ((Byteable) value).bytesStore(BytesStore.wrap(ByteBuffer.allocateDirect(4)), 0, 4); final InetSocketAddress endpoint = new InetSocketAddress("localhost", s_port + 1); diff --git a/src/test/java/net/openhft/chronicle/map/RecursiveRefereneChMapTest.java b/src/test/java/net/openhft/chronicle/map/RecursiveRefereneChMapTest.java index 3c33f30db..d109d9541 100644 --- a/src/test/java/net/openhft/chronicle/map/RecursiveRefereneChMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/RecursiveRefereneChMapTest.java @@ -16,7 +16,6 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.serialization.JDKObjectSerializer; import org.junit.Test; import java.io.*; @@ -34,7 +33,7 @@ public class RecursiveRefereneChMapTest { Map map = ChronicleMapBuilder.of(String.class, StupidCycle.class) .averageKey("Test").averageValue(new StupidCycle()) .entries(64) - .objectSerializer(JDKObjectSerializer.INSTANCE).create(); + .create(); map.put("Test", new StupidCycle()); map.put("Test2", new StupidCycle2()); StupidCycle cycle = (StupidCycle) map.get("Test"); diff --git a/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java index 4c6e2c5b2..87bd04990 100644 --- a/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/ReplicatedChronicleMapTest.java @@ -186,7 +186,7 @@ public class ReplicatedChronicleMapTest extends JSR166TestCase { @Test public void testGet() throws IOException { ChronicleMap map = map5(); - assertEquals("A", (String) map.get(JSR166TestCase.one)); + assertEquals("A", map.get(JSR166TestCase.one)); ChronicleMap empty = newShmIntString(); assertNull(map.get(JSR166TestCase.notPresent)); } diff --git a/src/test/java/net/openhft/chronicle/map/SampleValues.java b/src/test/java/net/openhft/chronicle/map/SampleValues.java index dd6e79933..1623f884e 100755 --- a/src/test/java/net/openhft/chronicle/map/SampleValues.java +++ b/src/test/java/net/openhft/chronicle/map/SampleValues.java @@ -30,8 +30,8 @@ package net.openhft.chronicle.map;/* * limitations under the License. */ -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; import org.jetbrains.annotations.NotNull; enum BuySell { @@ -55,10 +55,10 @@ public class SampleValues implements BytesMarshallable { @Override public void readMarshallable(@NotNull Bytes in) throws IllegalStateException { - aa = in.readEnum(String.class); - bb = in.readEnum(String.class); - cc = in.readEnum(BuySell.class); - dd = in.readEnum(BuySell.class); + 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(); @@ -69,8 +69,8 @@ public class SampleValues implements BytesMarshallable { @Override public void writeMarshallable(@NotNull Bytes out) { - out.writeUTFΔ(aa); - out.writeUTFΔ(bb); + out.writeUtf8(aa); + out.writeUtf8(bb); out.writeEnum(cc); out.writeEnum(dd); out.writeInt(ee); diff --git a/src/test/java/net/openhft/chronicle/map/SerializerTest.java b/src/test/java/net/openhft/chronicle/map/SerializerTest.java deleted file mode 100644 index 773150925..000000000 --- a/src/test/java/net/openhft/chronicle/map/SerializerTest.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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.chronicle.hash.serialization.internal.ReaderWithSize; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.constraints.NotNull; -import org.junit.Assert; -import org.junit.Test; - -import java.io.*; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.concurrent.ExecutionException; - -import static org.junit.Assert.assertEquals; - -public class SerializerTest { - - @Test - public void testPrefixStringFunctionSerialization() { - - ByteBufferBytes b = new ByteBufferBytes(ByteBuffer.allocate(512)); - - CHMUseCasesTest.PrefixStringFunction expected = new CHMUseCasesTest.PrefixStringFunction("New "); - b.writeObject(expected); - - b.clear(); - CHMUseCasesTest.PrefixStringFunction actual = b.readObject(CHMUseCasesTest.PrefixStringFunction.class); - assertEquals(expected, actual); - - } - - @Test - public void testStringSerialization() throws ExecutionException, - InterruptedException, IOException { - - ByteBufferBytes b = new ByteBufferBytes(ByteBuffer.allocate(512)); - - String expected = "Hello"; - b.writeObject(expected); - - b.clear(); - - String actual = (String) b.readObject(); - assertEquals(expected, actual); - - } - - - @Test - public void testValueMarshallable() { - testReadWriteValue("Test"); - testReadWriteValue(1); - testReadWriteValue(1L); - testReadWriteValue(1.0); - testReadWriteValue(1.0f); - testReadWriteValue(Collections.singleton("Test")); - testReadWriteValue(Collections.EMPTY_MAP); - testReadWriteValue(new MyTestClass(3)); - testReadWriteValue(new MyTestClassMarshallable(3)); - - testReadWriteValue(new MyTestClassExternalizable(3)); - testReadWriteValue(new MyTestClassObjectGraph(3)); - } - - @Test - public void testKeyMarshallable() { - testReadWriteKey("Test"); - testReadWriteKey(1); - testReadWriteKey(1L); - testReadWriteKey(1.0); - testReadWriteKey(1.0f); - testReadWriteKey(Collections.singleton("Test")); - testReadWriteKey(Collections.EMPTY_MAP); - testReadWriteKey(new MyTestClass(3)); - testReadWriteKey(new MyTestClassMarshallable(3)); - - testReadWriteKey(new MyTestClassExternalizable(3)); - testReadWriteKey(new MyTestClassObjectGraph(3)); - } - - public void testReadWriteValue(Object value) { - - Class valueClass = value.getClass(); - - final ByteBufferBytes out = new ByteBufferBytes(ByteBuffer.allocateDirect(1024)); - ByteBufferBytes in = out.slice(); - - ChronicleMapBuilder builder = - ChronicleMapBuilder.of(Integer.class, valueClass); - if (!builder.constantlySizedValues()) - builder.averageValueSize(1000); - - builder.preMapConstruction(); - - WriterWithSize valueWriterWithSize = new WriterWithSize(builder.valueBuilder,null); - ReaderWithSize valueReaderWithSize = new ReaderWithSize(builder.valueBuilder); - - valueWriterWithSize.write(out, value, null); - - long position = out.position(); - in.limit(position); - - Object actual = valueReaderWithSize.read(in, null, null); - Assert.assertEquals(actual, value); - } - - public void testReadWriteKey(Object key) { - - Class clazz = key.getClass(); - - final ByteBufferBytes out = new ByteBufferBytes(ByteBuffer.allocateDirect(1024)); - ByteBufferBytes in = out.slice(); - - ChronicleMapBuilder builder = ChronicleMapBuilder.of(clazz, Integer.class); - - if (!builder.constantlySizedKeys()) - builder.averageKeySize(1000); - - builder.preMapConstruction(); - { - WriterWithSize keyWriterWithSize = new WriterWithSize(builder.keyBuilder, null); - ReaderWithSize keyReaderWithSize = new ReaderWithSize(builder.keyBuilder); - - keyWriterWithSize.write(out, key, null); - - long position = out.position(); - in.limit(position); - - Object actual = keyReaderWithSize.read(in, null, null); - Assert.assertEquals(actual, key); - } - } - - public static class MyTestClassExternalizable implements Externalizable { - int a; - - public MyTestClassExternalizable() { - } - - MyTestClassExternalizable(int a) { - this.a = a; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MyTestClassExternalizable that = (MyTestClassExternalizable) o; - - if (a != that.a) return false; - - return true; - } - - @Override - public int hashCode() { - return a; - } - - @Override - public void writeExternal(ObjectOutput out) throws IOException { - out.write(a); - } - - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - a = in.readInt(); - } - } - - public static class MyTestClass implements Serializable { - int a; - - MyTestClass(int a) { - this.a = a; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MyTestClass myTestClass = (MyTestClass) o; - - if (a != myTestClass.a) return false; - - return true; - } - - @Override - public int hashCode() { - return a; - } - } - - public static class MyTestClassMarshallable implements BytesMarshallable { - int a; - - public MyTestClassMarshallable() { - } - - public MyTestClassMarshallable(int a) { - this.a = a; - } - - public void setA(int a) { - this.a = a; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || MyTestClassMarshallable.class != o.getClass()) return false; - - MyTestClassMarshallable that = (MyTestClassMarshallable) o; - - if (a != that.a) return false; - - return true; - } - - @Override - public int hashCode() { - return a; - } - - public void readMarshallable(@NotNull Bytes in) throws IllegalStateException { - a = in.readInt(); - } - - /** - * write an object to bytes - * - * @param out to write to - */ - public void writeMarshallable(@NotNull Bytes out) { - out.writeInt(a); - } - } - - public static class MyTestClassObjectGraph implements Serializable { - - MyTestClass delegate; - - public MyTestClassObjectGraph() { - } - - MyTestClassObjectGraph(int a) { - delegate = new MyTestClass(a); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MyTestClassObjectGraph that = (MyTestClassObjectGraph) o; - - if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) - return false; - - return true; - } - - @Override - public int hashCode() { - return delegate != null ? delegate.hashCode() : 0; - } - } - -} \ No newline at end of file diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java index ac976a95a..e43da3fa5 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplication4WayMapTest.java @@ -25,7 +25,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.util.Set; -import static net.openhft.chronicle.map.Builder.newTcpSocketShmBuilder; +import static net.openhft.chronicle.set.Builder.newTcpSocketShmBuilder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java index 411ef5af3..bf9b473a7 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationBootStrapTest.java @@ -30,8 +30,8 @@ import java.util.Arrays; import java.util.Set; import java.util.concurrent.TimeUnit; -import static net.openhft.chronicle.map.Builder.getPersistenceFile; -import static net.openhft.chronicle.map.Builder.newTcpSocketShmBuilder; +import static net.openhft.chronicle.set.Builder.getPersistenceFile; +import static net.openhft.chronicle.set.Builder.newTcpSocketShmBuilder; import static net.openhft.chronicle.map.TCPSocketReplication4WayMapTest.newTcpSocketShmIntString; import static org.junit.Assert.assertEquals; @@ -42,7 +42,7 @@ import static org.junit.Assert.assertEquals; */ public class TCPSocketReplicationBootStrapTest { - private ReplicatedChronicleMap map1; + private ReplicatedChronicleMap map1; private ChronicleMap map2; @Test @@ -98,7 +98,7 @@ public class TCPSocketReplicationBootStrapTest { .heartBeatInterval(1L, TimeUnit.SECONDS) .autoReconnectedUponDroppedConnection(true); - map1 = (ReplicatedChronicleMap) + map1 = (ReplicatedChronicleMap) ChronicleMapBuilder.of(Integer.class, CharSequence.class) .averageValueSize(100) .replication(SingleChronicleHashReplication.builder() @@ -112,8 +112,8 @@ public class TCPSocketReplicationBootStrapTest { TcpTransportAndNetworkConfig map2Config = TcpTransportAndNetworkConfig.of(8067) .heartBeatInterval(1L, TimeUnit.SECONDS); - final ReplicatedChronicleMap map2a = - (ReplicatedChronicleMap) + final ReplicatedChronicleMap map2a = + (ReplicatedChronicleMap) ChronicleMapBuilder.of(Integer.class, CharSequence.class) .averageValueSize(100) .replication(SingleChronicleHashReplication.builder() diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java index f214b3d38..5607f8938 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationIntValueTest.java @@ -16,10 +16,9 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; +import net.openhft.chronicle.core.values.IntValue; +import net.openhft.chronicle.set.Builder; +import net.openhft.chronicle.values.Values; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -27,11 +26,10 @@ import org.junit.Test; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; -import java.nio.ByteBuffer; import java.util.Random; import java.util.Set; -import static net.openhft.chronicle.map.Builder.newTcpSocketShmBuilder; +import static net.openhft.chronicle.set.Builder.newTcpSocketShmBuilder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -50,8 +48,7 @@ public class TCPSocketReplicationIntValueTest { @Before public void setup() throws IOException { - value = DataValueClasses.newDirectReference(IntValue.class); - ((Byteable) value).bytes(new ByteBufferBytes(ByteBuffer.allocateDirect(4)), 0); + value = Values.newHeapInstance(IntValue.class); map1Builder = newTcpSocketShmBuilder(IntValue.class, CharSequence.class, (byte) 1, s_port, new InetSocketAddress("localhost", s_port + 1)) .averageValue("EXAMPLE-1"); diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java index 9f4e76ad8..5aef105d9 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationNativeTest.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.LongValue; +import net.openhft.chronicle.values.Values; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -87,7 +87,7 @@ public class TCPSocketReplicationNativeTest { @Test public void test() throws IOException, InterruptedException { - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); try (net.openhft.chronicle.core.io.Closeable c = map1.acquireContext(1, value)) { @@ -104,7 +104,7 @@ public class TCPSocketReplicationNativeTest { @Test public void test2Puts() throws IOException, InterruptedException { - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); try (net.openhft.chronicle.core.io.Closeable c = map1.acquireContext(1, value)) { diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java index acd469108..9cb6995eb 100755 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationPostConnectionTest.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.set.Builder; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -25,7 +26,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.util.Set; -import static net.openhft.chronicle.map.Builder.newTcpSocketShmBuilder; +import static net.openhft.chronicle.set.Builder.newTcpSocketShmBuilder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java index c27e6c670..cc49bbddd 100644 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/TCPSocketReplicationTest.java @@ -16,6 +16,7 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.set.Builder; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,7 +29,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; -import static net.openhft.chronicle.map.Builder.newTcpSocketShmBuilder; +import static net.openhft.chronicle.set.Builder.newTcpSocketShmBuilder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java index 87c538f42..281cd9323 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationLargeEntryTest.java @@ -16,9 +16,9 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.algo.MemoryUnit; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.lang.MemoryUnit; import org.junit.*; import java.io.Closeable; diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java index f9b1360f6..75cd044c2 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakCrdtTest.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map; import com.google.common.collect.MapDifference; -import com.google.common.collect.Maps; +import net.openhft.chronicle.algo.MemoryUnit; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; @@ -25,9 +25,9 @@ import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.map.replication.MapRemoteOperations; import net.openhft.chronicle.map.replication.MapRemoteQueryContext; import net.openhft.chronicle.map.replication.MapReplicableEntry; +import net.openhft.chronicle.set.Builder; import org.jetbrains.annotations.NotNull; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -38,9 +38,9 @@ import java.util.*; import java.util.concurrent.TimeUnit; import static com.google.common.collect.Maps.difference; +import static net.openhft.chronicle.algo.MemoryUnit.MEGABYTES; import static net.openhft.chronicle.map.TcpReplicationSoakCrdtTest.GrowOnlySetValuedMapEntryOperations.growOnlySetValuedMapEntryOperations; import static net.openhft.chronicle.map.TcpReplicationSoakCrdtTest.GrowOnlySetValuedMapRemoteOperations.growOnlySetValuedMapRemoteOperations; -import static net.openhft.lang.MemoryUnit.MEGABYTES; import static org.junit.Assert.assertEquals; public class TcpReplicationSoakCrdtTest { diff --git a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java index 599bf376c..6bd54d45b 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpReplicationSoakTest.java @@ -21,18 +21,16 @@ import com.google.common.collect.Maps; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.SingleChronicleHashReplication; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; +import net.openhft.chronicle.set.Builder; import org.junit.*; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -46,8 +44,6 @@ public class TcpReplicationSoakTest { @Before public void setup() throws IOException { - IntValue value = DataValueClasses.newDirectReference(IntValue.class); - ((Byteable) value).bytes(new ByteBufferBytes(ByteBuffer.allocateDirect(4)), 0); final InetSocketAddress endpoint = new InetSocketAddress("localhost", s_port + 1); @@ -118,7 +114,7 @@ public class TcpReplicationSoakTest { ChannelReplicationTest.checkThreadsShutdown(threads); } - + @Ignore @Test public void testSoakTestWithRandomData() throws IOException, InterruptedException { try { diff --git a/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java b/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java index bf179744a..d696f237b 100644 --- a/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java +++ b/src/test/java/net/openhft/chronicle/map/TcpTimeBasedReplicationSoakTest.java @@ -16,19 +16,19 @@ package net.openhft.chronicle.map; +import net.openhft.chronicle.core.values.IntValue; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.TimeProvider; -import net.openhft.lang.io.ByteBufferBytes; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; -import org.junit.*; +import net.openhft.chronicle.set.Builder; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; import org.mockito.Mockito; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; -import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.TimeUnit; @@ -40,15 +40,12 @@ public class TcpTimeBasedReplicationSoakTest { private ChronicleMap map1; private ChronicleMap map2; - private IntValue value; static int s_port = 8010; private TimeProvider timeProvider; int t = 0; @Before public void setup() throws IOException { - value = DataValueClasses.newDirectReference(IntValue.class); - ((Byteable) value).bytes(new ByteBufferBytes(ByteBuffer.allocateDirect(4)), 0); final InetSocketAddress endpoint = new InetSocketAddress("localhost", s_port + 1); timeProvider = new TimeProvider() { diff --git a/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java b/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java index ca6571f18..38c23d157 100644 --- a/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java +++ b/src/test/java/net/openhft/chronicle/map/TimeBasedReplicationTest.java @@ -30,7 +30,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; -import static net.openhft.chronicle.map.Builder.waitTillEqual; +import static net.openhft.chronicle.set.Builder.waitTillEqual; import static org.junit.Assert.assertEquals; /** diff --git a/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java b/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java index cdccd8171..670c24325 100644 --- a/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java +++ b/src/test/java/net/openhft/chronicle/map/TrickyContextCasesTest.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.core.values.IntValue; -import net.openhft.lang.model.DataValueClasses; +import net.openhft.chronicle.values.Values; import org.junit.Test; import java.util.Arrays; @@ -34,7 +34,7 @@ public class TrickyContextCasesTest { .of(Integer.class, IntValue.class) .entries(1).create(); - IntValue v = DataValueClasses.newInstance(IntValue.class); + IntValue v = Values.newHeapInstance(IntValue.class); v.setValue(2); map.put(1, v); try (ExternalMapQueryContext q = map.queryContext(1)) { diff --git a/src/test/java/net/openhft/chronicle/map/WriteThroughputTest.java b/src/test/java/net/openhft/chronicle/map/WriteThroughputTest.java index 3d6bf5cde..009343a80 100644 --- a/src/test/java/net/openhft/chronicle/map/WriteThroughputTest.java +++ b/src/test/java/net/openhft/chronicle/map/WriteThroughputTest.java @@ -16,7 +16,6 @@ package net.openhft.chronicle.map; -import net.openhft.lang.io.serialization.impl.SnappyStringMarshaller; import org.junit.Ignore; import org.junit.Test; @@ -64,7 +63,7 @@ public class WriteThroughputTest { .of(CharSequence.class, CharSequence.class) .entries(count * 3 / 2) .averageValueSize(size / 4) - .valueMarshaller(SnappyStringMarshaller.INSTANCE) +// .valueReaderAndDataAccess(, SnappyStringMarshaller.INSTANCE, ) .putReturnsNull(true) .createPersistedTo(file2)) { @@ -72,6 +71,7 @@ public class WriteThroughputTest { doTest(count, size, map); } } + @Ignore("TODO") @Test public void bandwidthTestZ() throws IOException { diff --git a/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java b/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java index 3f958e9cb..b55e66300 100644 --- a/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java +++ b/src/test/java/net/openhft/chronicle/map/example/ComplexSerializationTest.java @@ -16,11 +16,14 @@ package net.openhft.chronicle.map.example; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.bytes.BytesMarshallable; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.io.serialization.BytesMarshaller; +import net.openhft.chronicle.map.Issue43Test; +import org.jetbrains.annotations.NotNull; import org.junit.Test; import java.util.ArrayList; @@ -33,64 +36,62 @@ public class ComplexSerializationTest { List list_; } - enum AMarshaller implements BytesMarshaller { + enum AMarshaller implements BytesReader, BytesWriter { INSTANCE; @Override - public void write(Bytes out, A a) { - out.writeUTF(a.str_); - if (a.list_ != null) { - int size = a.list_.size(); + public void write(Bytes out, @NotNull A toWrite) { + out.writeUtf8(toWrite.str_); + if (toWrite.list_ != null) { + int size = toWrite.list_.size(); out.writeStopBit(size); for (int i = 0; i < size; i++) { - a.list_.get(i).writeMarshallable(out); + toWrite.list_.get(i).writeMarshallable(out); } } else { out.writeStopBit(-1); } } + @NotNull @Override - public A read(Bytes in) { - return read(in, null); - } - - @Override - public A read(Bytes in, A a) { - if (a == null) - a = new A(); - a.str_ = in.readUTF(); + public A read(Bytes in, A using) { + if (using == null) + using = new A(); + using.str_ = in.readUtf8(); int size = (int) in.readStopBit(); if (size >= 0) { - if (a.list_ == null) { - a.list_ = new ArrayList<>(size); + if (using.list_ == null) { + using.list_ = new ArrayList<>(size); } else { - a.list_.clear(); - if (a.list_ instanceof ArrayList) - ((ArrayList) a.list_).ensureCapacity(size); + using.list_.clear(); + if (using.list_ instanceof ArrayList) + ((ArrayList) using.list_).ensureCapacity(size); } for (int i = 0; i < size; i++) { B b = new B(); b.readMarshallable(in); - a.list_.add(b); + using.list_.add(b); } } else { assert size == -1; - a.list_ = null; + using.list_ = null; } - return a; + return using; } } static class B implements BytesMarshallable { String str_; - @Override public void readMarshallable(Bytes in) throws IllegalStateException { - str_ = in.readUTF(); + @Override + public void readMarshallable(Bytes in) { + str_ = in.readUtf8(); } - @Override public void writeMarshallable(Bytes out) { - out.writeUTF(str_); + @Override + public void writeMarshallable(Bytes out) { + out.writeUtf8(str_); } } diff --git a/src/test/java/net/openhft/chronicle/map/example/DistributedSequenceMain.java b/src/test/java/net/openhft/chronicle/map/example/DistributedSequenceMain.java index 69d62c15e..eea16dc26 100644 --- a/src/test/java/net/openhft/chronicle/map/example/DistributedSequenceMain.java +++ b/src/test/java/net/openhft/chronicle/map/example/DistributedSequenceMain.java @@ -16,10 +16,10 @@ package net.openhft.chronicle.map.example; +import net.openhft.chronicle.core.values.LongValue; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.LongValue; +import net.openhft.chronicle.values.Values; import java.io.File; import java.io.IOException; @@ -36,7 +36,7 @@ public class DistributedSequenceMain { .createPersistedTo(file)) { // throughput test. for (int t = 0; t < 5; t++) { - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); map.acquireUsing("sequence-" + t, value); long start = System.nanoTime(); @@ -49,7 +49,7 @@ public class DistributedSequenceMain { } // latency test. - LongValue value = DataValueClasses.newDirectReference(LongValue.class); + LongValue value = Values.newNativeReference(LongValue.class); map.acquireUsing("sequence-X", value); int runs = 1000000000, count = 0, wcount = 0; diff --git a/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java b/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java index 6e1d6d12e..f18c68e53 100755 --- a/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java +++ b/src/test/java/net/openhft/chronicle/map/example/LotsOfEntriesMain.java @@ -18,7 +18,7 @@ package net.openhft.chronicle.map.example; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.values.Array; import java.io.File; import java.io.IOException; @@ -99,7 +99,8 @@ public class LotsOfEntriesMain { } interface MyFloats { - public void setValueAt(@MaxSize(6) int index, float f); + @Array(length = 6) + public void setValueAt(int index, float f); public float getValueAt(int index); } diff --git a/src/test/java/net/openhft/chronicle/map/example/SimpleMapOperationsListeningTest.java b/src/test/java/net/openhft/chronicle/map/example/SimpleMapOperationsListeningTest.java index 77eb2d840..8ba735895 100644 --- a/src/test/java/net/openhft/chronicle/map/example/SimpleMapOperationsListeningTest.java +++ b/src/test/java/net/openhft/chronicle/map/example/SimpleMapOperationsListeningTest.java @@ -16,12 +16,11 @@ package net.openhft.chronicle.map.example; +import net.openhft.chronicle.core.values.IntValue; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.map.*; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.values.IntValue; +import net.openhft.chronicle.values.Values; import org.jetbrains.annotations.NotNull; -import org.junit.Ignore; import org.junit.Test; import static net.openhft.chronicle.map.example.SimpleMapOperationsListeningTest.SimpleLoggingDefaultValueProvider.simpleLoggingDefaultValueProvider; @@ -90,12 +89,12 @@ public class SimpleMapOperationsListeningTest { .defaultValueProvider(simpleLoggingDefaultValueProvider()) .create(); - IntValue value = DataValueClasses.newDirectInstance(IntValue.class); + IntValue value = Values.newHeapInstance(IntValue.class); value.setValue(2); map.put(1, value); map.remove(1); - map.acquireUsing(3, value).addAtomicValue(1); - IntValue value2 = DataValueClasses.newDirectInstance(IntValue.class); + map.acquireUsing(3, Values.newNativeReference(IntValue.class)).addAtomicValue(1); + IntValue value2 = Values.newHeapInstance(IntValue.class); value2.setValue(5); map.forEachEntry(e -> e.context().replaceValue(e, e.context().wrapValueAsData(value2))); map.forEachEntry(e -> e.context().remove(e)); diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java deleted file mode 100644 index b18c537b8..000000000 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.fromdocs; - -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class BondVOInterface$$Heap implements BondVOInterface, BytesMarshallable, Copyable { - private double _coupon; - private long _issueDate; - private long _maturityDate; - private int _entry; - private net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx[] _marketPxIntraDayHistory = new net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx[7]; - { - for (int i = 0; i < _marketPxIntraDayHistory.length; i++) - _marketPxIntraDayHistory[i] = new net.openhft.chronicle.map.fromdocs.BondVOInterface$MarketPx$$Heap(); - } private java.lang.String _symbol; - - public void setCoupon(double $) { - _coupon = $; - } - - public double getCoupon() { - return _coupon; - } - - public synchronized double addAtomicCoupon(double $) { - return _coupon += $; - } - - public synchronized boolean compareAndSwapCoupon(double _1, double _2) { - if (_coupon == _1) { - _coupon = _2; - return true; - } - return false; - } - public void setIssueDate(long $) { - _issueDate = $; - } - - public long getIssueDate() { - return _issueDate; - } - - public void setMaturityDate(long $) { - _maturityDate = $; - } - - public long getMaturityDate() { - return _maturityDate; - } - - public synchronized long addAtomicMaturityDate(long $) { - return _maturityDate += $; - } - - public void unlockEntry() { - throw new UnsupportedOperationException(); - } public void busyLockEntry() { - throw new UnsupportedOperationException(); - } public void setMarketPxIntraDayHistoryAt(int i, net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx $) { - if(i<0) throw new ArrayIndexOutOfBoundsException(i + " must be greater than 0"); - if(i>=7) throw new ArrayIndexOutOfBoundsException(i + " must be less than 7"); - _marketPxIntraDayHistory[i] = $; - } - - public net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx getMarketPxIntraDayHistoryAt(int i) { - if(i<0) throw new ArrayIndexOutOfBoundsException(i + " must be greater than 0"); - if(i>=7) throw new ArrayIndexOutOfBoundsException(i + " must be less than 7"); - return _marketPxIntraDayHistory[i]; - } - - public void setSymbol(java.lang.String $) { - _symbol = $; - } - - public java.lang.String getSymbol() { - return _symbol; - } - - @SuppressWarnings("unchecked") - public void copyFrom(net.openhft.chronicle.map.fromdocs.BondVOInterface from) { - setCoupon(from.getCoupon()); - setIssueDate(from.getIssueDate()); - setMaturityDate(from.getMaturityDate()); - for (int i = 0; i < 7; i++){ - setMarketPxIntraDayHistoryAt(i, from.getMarketPxIntraDayHistoryAt(i)); - } - setSymbol(from.getSymbol()); - } - - public void writeMarshallable(Bytes out) { - out.writeDouble(getCoupon()); - out.writeLong(getIssueDate()); - out.writeLong(getMaturityDate()); - for (int i = 0; i < 7; i++){ - out.writeObject(getMarketPxIntraDayHistoryAt(i)); - } - out.writeUTFΔ(getSymbol()); - } - public void readMarshallable(Bytes in) { - _coupon = in.readDouble(); - _issueDate = in.readLong(); - _maturityDate = in.readLong(); - _entry = in.readInt(); - for (int i = 0; i < 7; i++){ - _marketPxIntraDayHistory[i] = in.readObject(net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx.class); - } - _symbol = in.readUTFΔ(); - } - - public long longHashCode_marketPxIntraDayHistory() { - long hc = 0; - for (int i = 0; i < 7; i++) { - hc += calcLongHashCode(getMarketPxIntraDayHistoryAt(i)); - } - return hc; - } - - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return ((((calcLongHashCode(getCoupon())) * 10191 + - calcLongHashCode(getIssueDate())) * 10191 + - calcLongHashCode(getMaturityDate())) * 10191 + - longHashCode_marketPxIntraDayHistory()) * 10191 + - calcLongHashCode(getSymbol()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BondVOInterface)) return false; - BondVOInterface that = (BondVOInterface) o; - - if(!isEqual(getCoupon(), that.getCoupon())) return false; - if(!isEqual(getIssueDate(), that.getIssueDate())) return false; - if(!isEqual(getMaturityDate(), that.getMaturityDate())) return false; - for (int i = 0; i <7; i++) { - if(!isEqual(getMarketPxIntraDayHistoryAt(i), that.getMarketPxIntraDayHistoryAt(i))) return false; - } - if(!isEqual(getSymbol(), that.getSymbol())) return false; - return true; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("BondVOInterface{ "); - sb.append(" }"); - return sb.toString(); - } -} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java deleted file mode 100644 index 2f9e1d168..000000000 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.fromdocs; - - -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class BondVOInterface$$Native - implements BondVOInterface, BytesMarshallable, Byteable, - Copyable { - private static final int COUPON = 0; - private static final int ISSUEDATE = 8; - private static final int MATURITYDATE = 16; - private static final int ENTRY = 24; - private static final int MARKETPXINTRADAYHISTORY = 28; - private final BondVOInterface$MarketPx$$Native _marketPxIntraDayHistory[] = - new BondVOInterface$MarketPx$$Native[7]; - { - for (int i = 0; i < 7; i++) - _marketPxIntraDayHistory[i] = new BondVOInterface$MarketPx$$Native(); - } - private static final int SYMBOL = 308; - - - private Bytes _bytes; - private long _offset; - - - - public void setCoupon(double $) { - _bytes.writeDouble(_offset + COUPON, $); - } - - public double getCoupon() { - return _bytes.readDouble(_offset + COUPON); - } - - public double addAtomicCoupon(double $) { - return _bytes.addAtomicDouble(_offset + COUPON, $); - } public boolean compareAndSwapCoupon(double _1, double _2) { - return _bytes.compareAndSwapDouble(_offset + COUPON, _1, _2); - } - - public void setIssueDate(long $) { - _bytes.writeLong(_offset + ISSUEDATE, $); - } - - public long getIssueDate() { - return _bytes.readLong(_offset + ISSUEDATE); - } - - - - public void setMaturityDate(long $) { - _bytes.writeLong(_offset + MATURITYDATE, $); - } - - public long getMaturityDate() { - return _bytes.readLong(_offset + MATURITYDATE); - } - - public long addAtomicMaturityDate(long $) { - return _bytes.addAtomicLong(_offset + MATURITYDATE, $); - } public void unlockEntry() { - _bytes.unlockInt(_offset + ENTRY); - } public void busyLockEntry() throws InterruptedException { - _bytes.busyLockInt(_offset + ENTRY); - } public void setMarketPxIntraDayHistoryAt(int i, BondVOInterface.MarketPx $) { - _marketPxIntraDayHistory[i].copyFrom($); - } - - public BondVOInterface.MarketPx getMarketPxIntraDayHistoryAt(int i) { - return _marketPxIntraDayHistory[i]; - } - - - - public void setSymbol(java.lang.String $) { - _bytes.writeUTFΔ(_offset + SYMBOL, 20, $); - } - - public java.lang.String getSymbol() { - return _bytes.readUTFΔ(_offset + SYMBOL); - } - - @Override - public void copyFrom(BondVOInterface from) { - setCoupon(from.getCoupon()); - setIssueDate(from.getIssueDate()); - setMaturityDate(from.getMaturityDate()); - for (int i = 0; i < 7; i++){ - setMarketPxIntraDayHistoryAt(i, from.getMarketPxIntraDayHistoryAt(i)); - } - setSymbol(from.getSymbol()); - } - - @Override - public void writeMarshallable(Bytes out) { - out.writeDouble(getCoupon()); - out.writeLong(getIssueDate()); - out.writeLong(getMaturityDate()); - for (int i = 0; i < 7; i++){ - _marketPxIntraDayHistory[i].writeMarshallable(out); - } - out.writeUTFΔ(getSymbol()); - } - @Override - public void readMarshallable(Bytes in) { - setCoupon(in.readDouble()); - setIssueDate(in.readLong()); - setMaturityDate(in.readLong()); - for (int i = 0; i < 7; i++){ - _marketPxIntraDayHistory[i].readMarshallable(in); - } - setSymbol(in.readUTFΔ()); - } - @Override - public void bytes(Bytes bytes, long offset) { - this._bytes = bytes; - this._offset = offset; - for (int i = 0; i < 7; i++){ - ((Byteable) _marketPxIntraDayHistory[i]).bytes(bytes, - _offset + MARKETPXINTRADAYHISTORY + (i * 40)); - } - } - @Override - public Bytes bytes() { - return _bytes; - } - @Override - public long offset() { - return _offset; - } - @Override - public int maxSize() { - return 328; - } - - public long longHashCode_marketPxIntraDayHistory() { - long hc = 0; - for (int i = 0; i < 7; i++) { - hc += calcLongHashCode(getMarketPxIntraDayHistoryAt(i)); - } - return hc; - } - - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return ((((calcLongHashCode(getCoupon())) * 10191 + - calcLongHashCode(getIssueDate())) * 10191 + - calcLongHashCode(getMaturityDate())) * 10191 + - longHashCode_marketPxIntraDayHistory()) * 10191 + - calcLongHashCode(getSymbol()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BondVOInterface)) return false; - BondVOInterface that = (BondVOInterface) o; - - if(!isEqual(getCoupon(), that.getCoupon())) return false; - if(!isEqual(getIssueDate(), that.getIssueDate())) return false; - if(!isEqual(getMaturityDate(), that.getMaturityDate())) return false; - for (int i = 0; i <7; i++) { - if(!isEqual(getMarketPxIntraDayHistoryAt(i), that.getMarketPxIntraDayHistoryAt(i))) - return false; - } - if(!isEqual(getSymbol(), that.getSymbol())) return false; - return true; - } - - public String toString() { - if (_bytes == null) return "bytes is null"; - StringBuilder sb = new StringBuilder(); - sb.append("BondVOInterface{ "); - sb.append(" }"); - return sb.toString(); - } -} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java deleted file mode 100644 index 27cfac92e..000000000 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.fromdocs; - -import net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class BondVOInterface$MarketPx$$Heap implements MarketPx, BytesMarshallable, Copyable { - private double _askPx; - private double _bidPx; - private double _callPx; - private double _maturityPx; - private double _parPx; - - public void setAskPx(double $) { - _askPx = $; - } - - public double getAskPx() { - return _askPx; - } - - public void setBidPx(double $) { - _bidPx = $; - } - - public double getBidPx() { - return _bidPx; - } - - public void setCallPx(double $) { - _callPx = $; - } - - public double getCallPx() { - return _callPx; - } - - public void setMaturityPx(double $) { - _maturityPx = $; - } - - public double getMaturityPx() { - return _maturityPx; - } - - public void setParPx(double $) { - _parPx = $; - } - - public double getParPx() { - return _parPx; - } - - @SuppressWarnings("unchecked") - public void copyFrom(net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx from) { - setAskPx(from.getAskPx()); - setBidPx(from.getBidPx()); - setCallPx(from.getCallPx()); - setMaturityPx(from.getMaturityPx()); - setParPx(from.getParPx()); - } - - public void writeMarshallable(Bytes out) { - out.writeDouble(getAskPx()); - out.writeDouble(getBidPx()); - out.writeDouble(getCallPx()); - out.writeDouble(getMaturityPx()); - out.writeDouble(getParPx()); - } - public void readMarshallable(Bytes in) { - _askPx = in.readDouble(); - _bidPx = in.readDouble(); - _callPx = in.readDouble(); - _maturityPx = in.readDouble(); - _parPx = in.readDouble(); - } - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return ((((calcLongHashCode(getAskPx())) * 10191 + - calcLongHashCode(getBidPx())) * 10191 + - calcLongHashCode(getCallPx())) * 10191 + - calcLongHashCode(getMaturityPx())) * 10191 + - calcLongHashCode(getParPx()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BondVOInterface.MarketPx)) return false; - BondVOInterface.MarketPx that = (BondVOInterface.MarketPx) o; - - if(!isEqual(getAskPx(), that.getAskPx())) return false; - if(!isEqual(getBidPx(), that.getBidPx())) return false; - if(!isEqual(getCallPx(), that.getCallPx())) return false; - if(!isEqual(getMaturityPx(), that.getMaturityPx())) return false; - if(!isEqual(getParPx(), that.getParPx())) return false; - return true; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("BondVOInterface.MarketPx{ "); - sb.append(" }"); - return sb.toString(); - } -} \ No newline at end of file diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java deleted file mode 100644 index 168b4b381..000000000 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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.fromdocs; - -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class BondVOInterface$MarketPx$$Native - implements BondVOInterface.MarketPx, BytesMarshallable, Byteable, - Copyable { - private static final int ASKPX = 0; - private static final int BIDPX = 8; - private static final int CALLPX = 16; - private static final int MATURITYPX = 24; - private static final int PARPX = 32; - - - private Bytes _bytes; - private long _offset; - - - - public void setAskPx(double $) { - _bytes.writeDouble(_offset + ASKPX, $); - } - - public double getAskPx() { - return _bytes.readDouble(_offset + ASKPX); - } - - - - public void setBidPx(double $) { - _bytes.writeDouble(_offset + BIDPX, $); - } - - public double getBidPx() { - return _bytes.readDouble(_offset + BIDPX); - } - - - - public void setCallPx(double $) { - _bytes.writeDouble(_offset + CALLPX, $); - } - - public double getCallPx() { - return _bytes.readDouble(_offset + CALLPX); - } - - - - public void setMaturityPx(double $) { - _bytes.writeDouble(_offset + MATURITYPX, $); - } - - public double getMaturityPx() { - return _bytes.readDouble(_offset + MATURITYPX); - } - - - - public void setParPx(double $) { - _bytes.writeDouble(_offset + PARPX, $); - } - - public double getParPx() { - return _bytes.readDouble(_offset + PARPX); - } - - @Override - public void copyFrom(BondVOInterface.MarketPx from) { - setAskPx(from.getAskPx()); - setBidPx(from.getBidPx()); - setCallPx(from.getCallPx()); - setMaturityPx(from.getMaturityPx()); - setParPx(from.getParPx()); - } - - @Override - public void writeMarshallable(Bytes out) { - out.writeDouble(getAskPx()); - out.writeDouble(getBidPx()); - out.writeDouble(getCallPx()); - out.writeDouble(getMaturityPx()); - out.writeDouble(getParPx()); - } - @Override - public void readMarshallable(Bytes in) { - setAskPx(in.readDouble()); - setBidPx(in.readDouble()); - setCallPx(in.readDouble()); - setMaturityPx(in.readDouble()); - setParPx(in.readDouble()); - } - @Override - public void bytes(Bytes bytes, long offset) { - this._bytes = bytes; - this._offset = offset; - } - @Override - public Bytes bytes() { - return _bytes; - } - @Override - public long offset() { - return _offset; - } - @Override - public int maxSize() { - return 40; - } - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return ((((calcLongHashCode(getAskPx())) * 10191 + - calcLongHashCode(getBidPx())) * 10191 + - calcLongHashCode(getCallPx())) * 10191 + - calcLongHashCode(getMaturityPx())) * 10191 + - calcLongHashCode(getParPx()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BondVOInterface.MarketPx)) return false; - BondVOInterface.MarketPx that = (BondVOInterface.MarketPx) o; - - if(!isEqual(getAskPx(), that.getAskPx())) return false; - if(!isEqual(getBidPx(), that.getBidPx())) return false; - if(!isEqual(getCallPx(), that.getCallPx())) return false; - if(!isEqual(getMaturityPx(), that.getMaturityPx())) return false; - if(!isEqual(getParPx(), that.getParPx())) return false; - return true; - } - - public String toString() { - if (_bytes == null) return "bytes is null"; - StringBuilder sb = new StringBuilder(); - sb.append("BondVOInterface.MarketPx{ "); - sb.append(" }"); - return sb.toString(); - } -} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface.java index b30ebdd67..eaa09f44e 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface.java @@ -16,40 +16,39 @@ package net.openhft.chronicle.map.fromdocs; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.Group; +import net.openhft.chronicle.values.MaxUtf8Length; public interface BondVOInterface { - /* add support for entry based locking */ - @Deprecated() - void busyLockEntry() throws InterruptedException; - @Deprecated() - void unlockEntry(); + @Group(0) + long getEntryLockState(); + void setEntryLockState(long entryLockState); + @Group(1) long getIssueDate(); - void setIssueDate(long issueDate); /* time in millis */ + @Group(1) long getMaturityDate(); - void setMaturityDate(long maturityDate); /* time in millis */ - long addAtomicMaturityDate(long toAdd); + @Group(1) boolean compareAndSwapCoupon(double expected, double value); - double getCoupon(); - void setCoupon(double coupon); - double addAtomicCoupon(double toAdd); + @Group(1) String getSymbol(); - - void setSymbol(@MaxSize(20) String symbol); + void setSymbol(@MaxUtf8Length(20) String symbol); // OpenHFT Off-Heap array[ ] processing notice ‘At’ suffix - void setMarketPxIntraDayHistoryAt(@MaxSize(7) int tradingDayHour, MarketPx mPx); + @Group(1) + @Array(length = 7) + void setMarketPxIntraDayHistoryAt(int tradingDayHour, MarketPx mPx); /* 7 Hours in the Trading Day: * index_0 = 9.30am, diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java index 2535d4872..5981b8748 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayReader.java @@ -16,33 +16,27 @@ package net.openhft.chronicle.map.fromdocs; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.lang.io.Bytes; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedReader; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -enum LongPairArrayReader implements BytesReader { +enum LongPairArrayReader implements SizedReader { INSTANCE; @NotNull @Override - public LongPair[] read(@NotNull Bytes bytes, long size) { - return read(bytes, size, null); - } - - @NotNull - @Override - public LongPair[] read(@NotNull Bytes bytes, long size, LongPair[] toReuse) { + public LongPair[] read(@NotNull Bytes in, long size, LongPair[] using) { if (size > Integer.MAX_VALUE * 16L) throw new IllegalStateException("LongPair[] size couldn't be " + (size / 16L)); int resLen = (int) (size / 16L); LongPair[] res; - if (toReuse != null) { - if (toReuse.length == resLen) { - res = toReuse; + if (using != null) { + if (using.length == resLen) { + res = using; } else { - res = Arrays.copyOf(toReuse, resLen); + res = Arrays.copyOf(using, resLen); } } else { res = new LongPair[resLen]; @@ -51,8 +45,8 @@ enum LongPairArrayReader implements BytesReader { LongPair pair = res[i]; if (pair == null) res[i] = pair = new LongPair(); - pair.first = bytes.readLong(); - pair.second = bytes.readLong(); + pair.first = in.readLong(); + pair.second = in.readLong(); } return res; } diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java index fbd7c806b..591e6539a 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/LongPairArrayWriter.java @@ -16,23 +16,23 @@ package net.openhft.chronicle.map.fromdocs; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.lang.io.Bytes; +import net.openhft.chronicle.bytes.Bytes; +import net.openhft.chronicle.hash.serialization.SizedWriter; import org.jetbrains.annotations.NotNull; -enum LongPairArrayWriter implements BytesWriter { +enum LongPairArrayWriter implements SizedWriter { INSTANCE; @Override - public long size(@NotNull LongPair[] longPairs) { - return longPairs.length * 16L; + public long size(@NotNull LongPair[] toWrite) { + return toWrite.length * 16L; } @Override - public void write(@NotNull Bytes bytes, @NotNull LongPair[] longPairs) { - for (LongPair pair : longPairs) { - bytes.writeLong(pair.first); - bytes.writeLong(pair.second); + public void write(@NotNull Bytes out, long size, @NotNull LongPair[] toWrite) { + for (LongPair pair : toWrite) { + out.writeLong(pair.first); + out.writeLong(pair.second); } } } diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/StringEncodingExamplesTest.java b/src/test/java/net/openhft/chronicle/map/fromdocs/StringEncodingExamplesTest.java deleted file mode 100644 index 30bb480e3..000000000 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/StringEncodingExamplesTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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.fromdocs; - -import net.openhft.chronicle.set.ChronicleSet; -import net.openhft.chronicle.set.ChronicleSetBuilder; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.CharBuffers; -import net.openhft.lang.io.serialization.BytesMarshaller; -import net.openhft.lang.model.constraints.NotNull; -import net.openhft.lang.pool.CharSequenceInterner; -import net.openhft.lang.threadlocal.StatefulCopyable; -import org.jetbrains.annotations.Nullable; -import org.junit.Assert; -import org.junit.Test; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; - -public class StringEncodingExamplesTest { - - static class CustomEncodingMarshaller implements BytesMarshaller, - StatefulCopyable { - private static final long serialVersionUID = 0L; - - private String charsetName; - private transient Charset charset; - private transient CharsetEncoder encoder; - private transient CharsetDecoder decoder; - private transient ByteBuffer bytesAsBuffer; - private transient CharBuffer charSequenceAsBuffer; - private transient CharBuffer returnedCharBuffer; - - CustomEncodingMarshaller(Charset charset) { - this.charsetName = charset.name().intern(); - this.charset = charset; - initCoders(); - } - - CustomEncodingMarshaller(CustomEncodingMarshaller m) { - charsetName = m.charsetName; - charset = m.charset; - encoder = m.encoder; - decoder = m.decoder; - } - - private void initCoders() { - encoder = charset.newEncoder(); - decoder = charset.newDecoder(); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - charsetName = charsetName.intern(); - charset = Charset.forName(charsetName); - initCoders(); - } - - @Override - public void write(Bytes bytes, CharSequence cs) { - bytes.writeStopBit(cs.length()); - bytesAsBuffer = bytes.sliceAsByteBuffer(bytesAsBuffer); - charSequenceAsBuffer = CharBuffers.wrap(cs, charSequenceAsBuffer); - encoder.encode(charSequenceAsBuffer, bytesAsBuffer, true); - bytes.position(bytes.position() + bytesAsBuffer.position()); - } - - @Override - public CharSequence read(Bytes bytes) { - long csLen = bytes.readStopBit(); - if (csLen < 0 || csLen > Integer.MAX_VALUE) - throw new IllegalStateException("length invalid: " + csLen); - if (returnedCharBuffer == null || returnedCharBuffer.capacity() < csLen) { - returnedCharBuffer = CharBuffer.allocate((int) csLen); - } else { - returnedCharBuffer.clear().limit((int) csLen); - } - bytesAsBuffer = bytes.sliceAsByteBuffer(bytesAsBuffer); - decoder.decode(bytesAsBuffer, returnedCharBuffer, true); - bytes.position(bytes.position() + bytesAsBuffer.position()); - returnedCharBuffer.flip(); - return returnedCharBuffer; - } - - @Override - public CharSequence read(Bytes bytes, @Nullable CharSequence cs) { - return read(bytes); - } - - @Override - public Object stateIdentity() { - return charsetName; - } - - @Override - public CustomEncodingMarshaller copy() { - return new CustomEncodingMarshaller(this); - } - } - - static class Utf16Marshaller implements BytesMarshaller, - StatefulCopyable> { - private static final long serialVersionUID = 0L; - - private final Serializable identity; - private final CharSequenceInterner interner; - private transient char[] readBuffer; - - & Serializable> - Utf16Marshaller(Serializable identity, I interner) { - this.identity = identity; - this.interner = interner; - } - - @Override - public void write(Bytes bytes, CS cs) { - bytes.writeCompactInt(cs.length()); - bytes.writeChars(cs); - } - - @Override - public CS read(Bytes bytes) { - return read(bytes, null); - } - - @Override - public CS read(Bytes bytes, @Nullable CS cs) { - int csLen = bytes.readCompactInt(); - if (readBuffer == null || readBuffer.length < csLen) - readBuffer = new char[csLen]; - bytes.readFully(readBuffer, 0, csLen); - return interner.intern(CharBuffer.wrap(readBuffer, 0, csLen)); - } - - @Override - public Object stateIdentity() { - return identity; - } - - @Override - public Utf16Marshaller copy() { - return new Utf16Marshaller(identity, interner); - } - } - - enum NoInterning implements CharSequenceInterner { - INSTANCE; - - @Override - public CharSequence intern(@NotNull CharSequence cs) { - return cs; - } - } - - @Test - public void testCustomEncodingMarshaller() throws IOException { - CustomEncodingMarshaller gbkStringMarshaller = - new CustomEncodingMarshaller(Charset.forName("GBK")); - testCustomKeyMarshaller(gbkStringMarshaller); - } - - @Test - public void testNoEncodingMarshaller() throws IOException { - Utf16Marshaller noEncodingMarshaller = - new Utf16Marshaller(NoInterning.INSTANCE, NoInterning.INSTANCE); - testCustomKeyMarshaller(noEncodingMarshaller); - } - - private void testCustomKeyMarshaller(BytesMarshaller marshaller) - throws IOException { - try (ChronicleSet chineseWordSet = ChronicleSetBuilder.of(CharSequence.class) - .averageKeySize(10) - .keyMarshaller(marshaller) - .actualSegments(1) - .entriesPerSegment(1000) - .create()) { - chineseWordSet.add("新闻"); - chineseWordSet.add("地图"); - chineseWordSet.add("贴吧"); - chineseWordSet.add("登录"); - chineseWordSet.add("设置"); - Assert.assertEquals(5, chineseWordSet.size()); - System.out.println(chineseWordSet); - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongAddLeft.java b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongAddLeft.java index 262f91fb4..a397b55e4 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongAddLeft.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongAddLeft.java @@ -22,7 +22,7 @@ import net.openhft.chronicle.map.fromdocs.BondVOInterface; import java.io.IOException; import java.util.Arrays; -import static net.openhft.lang.model.DataValueClasses.newDirectReference; +import static net.openhft.chronicle.values.Values.newNativeReference; public class PingPongAddLeft { public static void main(String... ignored) throws IOException { @@ -32,10 +32,10 @@ public class PingPongAddLeft { } static void playPingPong(ChronicleMap chm, double add, boolean setFirst, final String desc) { - BondVOInterface bond1 = newDirectReference(BondVOInterface.class); - BondVOInterface bond2 = newDirectReference(BondVOInterface.class); - BondVOInterface bond3 = newDirectReference(BondVOInterface.class); - BondVOInterface bond4 = newDirectReference(BondVOInterface.class); + BondVOInterface bond1 = newNativeReference(BondVOInterface.class); + BondVOInterface bond2 = newNativeReference(BondVOInterface.class); + BondVOInterface bond3 = newNativeReference(BondVOInterface.class); + BondVOInterface bond4 = newNativeReference(BondVOInterface.class); chm.acquireUsing("369604101", bond1); chm.acquireUsing("369604102", bond2); diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongCASLeft.java b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongCASLeft.java index 613ad7a4e..60e286bff 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongCASLeft.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongCASLeft.java @@ -24,7 +24,7 @@ import net.openhft.chronicle.map.fromdocs.BondVOInterface; import java.io.IOException; import java.util.Arrays; -import static net.openhft.lang.model.DataValueClasses.newDirectReference; +import static net.openhft.chronicle.values.Values.newNativeReference; /* on an i7-4500 laptop. @@ -50,10 +50,10 @@ public class PingPongCASLeft { static void playPingPong(ChronicleMap chm, double _coupon, double _coupon2, boolean setFirst, final String desc) { - BondVOInterface bond1 = newDirectReference(BondVOInterface.class); - BondVOInterface bond2 = newDirectReference(BondVOInterface.class); - BondVOInterface bond3 = newDirectReference(BondVOInterface.class); - BondVOInterface bond4 = newDirectReference(BondVOInterface.class); + BondVOInterface bond1 = newNativeReference(BondVOInterface.class); + BondVOInterface bond2 = newNativeReference(BondVOInterface.class); + BondVOInterface bond3 = newNativeReference(BondVOInterface.class); + BondVOInterface bond4 = newNativeReference(BondVOInterface.class); chm.acquireUsing("369604101", bond1); chm.acquireUsing("369604102", bond2); diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongLockLeft.java b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongLockLeft.java index 31a0496ea..a360557e0 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongLockLeft.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/pingpong_latency/PingPongLockLeft.java @@ -16,13 +16,21 @@ package net.openhft.chronicle.map.fromdocs.pingpong_latency; +import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.algo.locks.AcquisitionStrategies; +import net.openhft.chronicle.algo.locks.ReadWriteLockingStrategy; +import net.openhft.chronicle.algo.locks.TryAcquireOperations; +import net.openhft.chronicle.algo.locks.VanillaReadWriteWithWaitsLockingStrategy; +import net.openhft.chronicle.bytes.Byteable; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.fromdocs.BondVOInterface; import java.io.IOException; import java.util.Arrays; +import java.util.concurrent.TimeUnit; -import static net.openhft.lang.model.DataValueClasses.newDirectReference; +import static net.openhft.chronicle.algo.bytes.Access.checkedBytesStoreAccess; +import static net.openhft.chronicle.values.Values.newNativeReference; public class PingPongLockLeft { public static void main(String... ignored) throws IOException, InterruptedException { @@ -32,10 +40,10 @@ public class PingPongLockLeft { } static void playPingPong(ChronicleMap chm, double _coupon, double _coupon2, boolean setFirst, final String desc) throws InterruptedException { - BondVOInterface bond1 = newDirectReference(BondVOInterface.class); - BondVOInterface bond2 = newDirectReference(BondVOInterface.class); - BondVOInterface bond3 = newDirectReference(BondVOInterface.class); - BondVOInterface bond4 = newDirectReference(BondVOInterface.class); + BondVOInterface bond1 = newNativeReference(BondVOInterface.class); + BondVOInterface bond2 = newNativeReference(BondVOInterface.class); + BondVOInterface bond3 = newNativeReference(BondVOInterface.class); + BondVOInterface bond4 = newNativeReference(BondVOInterface.class); chm.acquireUsing("369604101", bond1); chm.acquireUsing("369604102", bond2); @@ -67,9 +75,14 @@ public class PingPongLockLeft { } } - private static void toggleCoupon(BondVOInterface bond, double _coupon, double _coupon2) throws InterruptedException { + private static void toggleCoupon(BondVOInterface bond, double _coupon, double _coupon2) + throws InterruptedException { for (int i = 0; ; i++) { - bond.busyLockEntry(); + AcquisitionStrategies.spinLoopOrFail(5, TimeUnit.SECONDS) + .acquire(TryAcquireOperations.writeLock(), + VanillaReadWriteWithWaitsLockingStrategy.instance(), + checkedBytesStoreAccess(), + ((Byteable) bond).bytesStore(), ((Byteable) bond).offset()); try { if (bond.getCoupon() == _coupon) { bond.setCoupon(_coupon2); @@ -78,7 +91,9 @@ public class PingPongLockLeft { if (i > 1000) Thread.yield(); } finally { - bond.unlockEntry(); + VanillaReadWriteWithWaitsLockingStrategy.instance() + .writeUnlock(checkedBytesStoreAccess(), + ((Byteable) bond).bytesStore(), ((Byteable) bond).offset()); } } } diff --git a/src/test/java/net/openhft/chronicle/map/ipc/StateMachineData.java b/src/test/java/net/openhft/chronicle/map/ipc/StateMachineData.java index 26a0e2ae6..e302b4911 100644 --- a/src/test/java/net/openhft/chronicle/map/ipc/StateMachineData.java +++ b/src/test/java/net/openhft/chronicle/map/ipc/StateMachineData.java @@ -16,21 +16,21 @@ package net.openhft.chronicle.map.ipc; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.model.Byteable; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.BytesStore; /** * */ public class StateMachineData implements Byteable { - private Bytes bytes; + private BytesStore bs; private long offset; /** * c-tor */ public StateMachineData() { - this.bytes = null; + this.bs = null; this.offset = -1; } @@ -58,18 +58,18 @@ public class StateMachineData implements Byteable { * @param to */ public boolean setState(StateMachineState from, StateMachineState to) { - if (this.bytes == null) throw new NullPointerException("Byteable is not set to off heap"); + if (this.bs == null) throw new NullPointerException("Byteable is not set to off heap"); - return this.bytes.compareAndSwapInt(this.offset, from.value(), to.value()); + return this.bs.compareAndSwapInt(this.offset, from.value(), to.value()); } /** * @return */ public StateMachineState getState() { - if (this.bytes == null) throw new NullPointerException("Byteable is not set to off heap"); + if (this.bs == null) throw new NullPointerException("Byteable is not set to off heap"); - int value = this.bytes.readVolatileInt(this.offset); + int value = this.bs.readVolatileInt(this.offset); return StateMachineState.fromValue(value); } @@ -77,9 +77,9 @@ public class StateMachineData implements Byteable { * @param state */ public void setState(StateMachineState state) { - if (this.bytes == null) throw new NullPointerException("Byteable is not set to off heap"); + if (this.bs == null) throw new NullPointerException("Byteable is not set to off heap"); - this.bytes.writeInt(this.offset, state.value()); + this.bs.writeInt(this.offset, state.value()); } /** @@ -90,7 +90,7 @@ public class StateMachineData implements Byteable { * @param to */ public void waitForState(StateMachineState from, StateMachineState to) { - if (this.bytes == null) throw new NullPointerException("Byteable is not set to off heap"); + if (this.bs == null) throw new NullPointerException("Byteable is not set to off heap"); // spin for (int i = 0; !setState(from, to); i++) { @@ -108,8 +108,8 @@ public class StateMachineData implements Byteable { * @return */ public int getStateData() { - if (this.bytes != null) { - return this.bytes.readVolatileInt(this.offset + 4); + if (this.bs != null) { + return this.bs.readVolatileInt(this.offset + 4); } return -1; @@ -119,8 +119,8 @@ public class StateMachineData implements Byteable { * @param data */ public void setStateData(int data) { - if (this.bytes != null) { - this.bytes.writeInt(this.offset + 4, data); + if (this.bs != null) { + this.bs.writeInt(this.offset + 4, data); } } @@ -128,8 +128,8 @@ public class StateMachineData implements Byteable { * @return */ public int incStateData() { - if (this.bytes != null) { - return this.bytes.addInt(this.offset + 4, 1); + if (this.bs != null) { + return this.bs.addAndGetInt(this.offset + 4, 1); } return -1; @@ -139,7 +139,7 @@ public class StateMachineData implements Byteable { * @return */ public boolean done() { - if (this.bytes != null) { + if (this.bs != null) { return getStateData() > 100; } @@ -151,14 +151,16 @@ public class StateMachineData implements Byteable { // ************************************************************************* @Override - public void bytes(Bytes bytes, long offset) { - this.bytes = bytes; + public void bytesStore(BytesStore bytes, long offset, long size) { + if (size != 16) + throw new IllegalArgumentException(); + this.bs = bytes; this.offset = offset; } @Override - public Bytes bytes() { - return this.bytes; + public BytesStore bytesStore() { + return this.bs; } @Override @@ -167,7 +169,7 @@ public class StateMachineData implements Byteable { } @Override - public int maxSize() { + public long maxSize() { return 16; } } diff --git a/src/test/java/net/openhft/chronicle/map/jsr166/JSR166TestCase.java b/src/test/java/net/openhft/chronicle/map/jsr166/JSR166TestCase.java index 24c82c8c3..7538a8f11 100644 --- a/src/test/java/net/openhft/chronicle/map/jsr166/JSR166TestCase.java +++ b/src/test/java/net/openhft/chronicle/map/jsr166/JSR166TestCase.java @@ -17,7 +17,7 @@ package net.openhft.chronicle.map.jsr166; import junit.framework.AssertionFailedError; -import net.openhft.lang.Jvm; +import net.openhft.chronicle.core.Jvm; import org.junit.After; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java b/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java index ef6b4e743..58ba8b579 100644 --- a/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/jsr166/map/ChronicleMapTest.java @@ -115,7 +115,7 @@ public class ChronicleMapTest extends JSR166TestCase { @Test(timeout = 5000) public void testGet() throws IOException { try (ChronicleMap map = map5()) { - assertEquals("A", (String) map.get(one)); + assertEquals("A", map.get(one)); try (ChronicleMap empty = newStrStrMap(8078)) { assertNull(map.get(notPresent)); } diff --git a/src/test/java/net/openhft/chronicle/map/utility/ProcessInstanceLimiter.java b/src/test/java/net/openhft/chronicle/map/utility/ProcessInstanceLimiter.java index 0f236be5e..9de4a5bf8 100644 --- a/src/test/java/net/openhft/chronicle/map/utility/ProcessInstanceLimiter.java +++ b/src/test/java/net/openhft/chronicle/map/utility/ProcessInstanceLimiter.java @@ -17,10 +17,14 @@ package net.openhft.chronicle.map.utility; import net.openhft.affinity.AffinitySupport; +import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.algo.locks.*; +import net.openhft.chronicle.bytes.Byteable; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.ChronicleMapBuilder; -import net.openhft.lang.model.DataValueClasses; -import net.openhft.lang.model.constraints.MaxSize; +import net.openhft.chronicle.values.Array; +import net.openhft.chronicle.values.Group; +import net.openhft.chronicle.values.Values; import java.io.File; import java.io.IOException; @@ -29,6 +33,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import static net.openhft.chronicle.algo.bytes.Access.checkedBytesStoreAccess; /** * ProcessInstanceLimiter limits the number of JVM processes of a particular @@ -384,7 +391,7 @@ public class ProcessInstanceLimiter implements Runnable { if (maxNumberOfProcessesAllowed <= 0) { throw new IllegalArgumentException("maxNumberOfProcessesAllowed must be a positive number, not " + maxNumberOfProcessesAllowed); } - Data data = DataValueClasses.newDirectReference(Data.class); + Data data = Values.newNativeReference(Data.class); this.timedata.put(processType, data); this.theSharedMap.acquireUsing(processType, data); if (data.getMaxNumberOfProcessesAllowed() != maxNumberOfProcessesAllowed) { @@ -400,7 +407,7 @@ public class ProcessInstanceLimiter implements Runnable { } } String name = processType + '#'; - data = DataValueClasses.newDirectReference(Data.class); + data = Values.newNativeReference(Data.class); this.starttimedata.put(processType, data); this.processTypeToStartTimeType.put(processType, name); this.theSharedMap.acquireUsing(name, data); @@ -441,12 +448,20 @@ public class ProcessInstanceLimiter implements Runnable { } private boolean lock(Data data, int microsecondsToTry) { - return data.tryLockNanosTimelock(1000L * microsecondsToTry); + return AcquisitionStrategies + .spinLoop(microsecondsToTry, TimeUnit.MICROSECONDS) + .acquire(TryAcquireOperations.writeLock(), + VanillaReadWriteWithWaitsLockingStrategy.instance(), + checkedBytesStoreAccess(), + ((Byteable) data).bytesStore(), + ((Byteable) data).offset()); } private void unlock(Data data) { try { - data.unlockTimelock(); + VanillaReadWriteWithWaitsLockingStrategy.instance() + .writeUnlock(checkedBytesStoreAccess(), + ((Byteable) data).bytesStore(), ((Byteable) data).offset()); } catch (IllegalMonitorStateException e) { //odd, but we'll be unlocked either way System.out.println("Unexpected state: " + e); @@ -458,14 +473,14 @@ public class ProcessInstanceLimiter implements Runnable { * The Callback interface holds all the calls that can be made by the * process instance limiter. */ - public static interface Callback { + public interface Callback { /** * Called when there are already the specified number of processes of * the given type running, and this process is one too many. * * @param processType - the name of the type of process being limited */ - public void tooManyProcessesOfType(String processType); + void tooManyProcessesOfType(String processType); /** * Called when there is a lock conflict in the limiter @@ -474,7 +489,7 @@ public class ProcessInstanceLimiter implements Runnable { * @param processType - the name of the type of process being limited * @param index - the slot number held by the other process */ - public void lockConflictDetected(String processType, int index); + void lockConflictDetected(String processType, int index); /** * Called when another process has started and successfully acquired a @@ -484,7 +499,7 @@ public class ProcessInstanceLimiter implements Runnable { * @param slot - the slot number held by the other process * @param startTime - the start timestamp of the other process */ - public void anotherProcessHasStartedOnSlot(String processType, int slot, long startTime); + void anotherProcessHasStartedOnSlot(String processType, int slot, long startTime); /** * Called when this process has started and successfully acquired a slot @@ -493,7 +508,7 @@ public class ProcessInstanceLimiter implements Runnable { * @param processType - the name of the type of process being limited * @param slot - the slot number held by this process */ - public void thisProcessOfTypeHasStartedAtSlot(String processType, int slot); + void thisProcessOfTypeHasStartedAtSlot(String processType, int slot); /** * Called if the process was started but there was no data defined in @@ -501,7 +516,7 @@ public class ProcessInstanceLimiter implements Runnable { * * @param processType - the name of the type of process being limited */ - public void noDefinitionForProcessesOfType(String processType); + void noDefinitionForProcessesOfType(String processType); /** * Called when another process somehow managed to steal the slot that @@ -510,7 +525,7 @@ public class ProcessInstanceLimiter implements Runnable { * @param processType - the name of the type of process being limited * @param slot - the slot number held by this process */ - public void anotherProcessHasHijackedThisSlot(String processType, int slot); + void anotherProcessHasHijackedThisSlot(String processType, int slot); } /** @@ -519,25 +534,23 @@ public class ProcessInstanceLimiter implements Runnable { * *

The Timelock field is just for locking the time field */ - public static interface Data { - void setTimeAt(@MaxSize(50) int index, long time); + public interface Data { + /** Ensure lock goes first in flyweight layout, to apply external locking + */ + @Group(0) + long getTimeLock(); + void setTimeLock(long timeLock); + + @Group(1) + @Array(length = 50) + void setTimeAt(int index, long time); long getTimeAt(int index); + @Group(1) int getMaxNumberOfProcessesAllowed(); - void setMaxNumberOfProcessesAllowed(int num); - boolean compareAndSwapMaxNumberOfProcessesAllowed(int expected, int value); - - boolean tryLockNanosTimelock(long nanos); - - void unlockTimelock() throws IllegalMonitorStateException; - - //void resetlockTimelock() throws IllegalMonitorStateException; - int getTimelock(); - - void setTimelock(int num); } /** diff --git a/src/test/java/net/openhft/chronicle/map/Builder.java b/src/test/java/net/openhft/chronicle/set/Builder.java similarity index 88% rename from src/test/java/net/openhft/chronicle/map/Builder.java rename to src/test/java/net/openhft/chronicle/set/Builder.java index 16567a7c3..43b3b63db 100644 --- a/src/test/java/net/openhft/chronicle/map/Builder.java +++ b/src/test/java/net/openhft/chronicle/set/Builder.java @@ -14,23 +14,21 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.set; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; -import net.openhft.chronicle.hash.serialization.internal.DummyValueMarshaller; +import net.openhft.chronicle.hash.serialization.SizeMarshaller; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.map.ChronicleMapBuilder; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.InetSocketAddress; import java.util.Arrays; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import static com.google.common.collect.Maps.difference; - /** * @author Rob Austin. */ @@ -88,8 +86,10 @@ public class Builder { final InetSocketAddress... endpoints) throws IOException { return (T) newTcpSocketShmBuilder(Integer.class, DummyValue.class, identifier, serverPort, endpoints) - .valueMarshallers(DummyValueMarshaller.INSTANCE, DummyValueMarshaller.INSTANCE) - .valueSizeMarshaller(DummyValueMarshaller.INSTANCE).create(); + .valueReaderAndDataAccess( + DummyValueMarshaller.INSTANCE, DummyValueMarshaller.INSTANCE) + .valueSizeMarshaller(SizeMarshaller.constant(0)) + .create(); } public static ChronicleMapBuilder newTcpSocketShmBuilder( @@ -97,7 +97,8 @@ public class Builder { final byte identifier, final int serverPort, final InetSocketAddress... endpoints) throws IOException { - TcpTransportAndNetworkConfig tcpConfig = TcpTransportAndNetworkConfig.of(serverPort, Arrays.asList(endpoints)) + TcpTransportAndNetworkConfig tcpConfig = TcpTransportAndNetworkConfig + .of(serverPort, Arrays.asList(endpoints)) .heartBeatInterval(1L, TimeUnit.SECONDS).autoReconnectedUponDroppedConnection(true); return ChronicleMapBuilder.of(kClass, vClass) .entries(SIZE) diff --git a/src/test/java/net/openhft/chronicle/set/SetForTCPSocketReplication3wayTest.java b/src/test/java/net/openhft/chronicle/set/SetForTCPSocketReplication3wayTest.java index 99c6505ba..6d029ba1e 100644 --- a/src/test/java/net/openhft/chronicle/set/SetForTCPSocketReplication3wayTest.java +++ b/src/test/java/net/openhft/chronicle/set/SetForTCPSocketReplication3wayTest.java @@ -19,7 +19,6 @@ package net.openhft.chronicle.set; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -28,7 +27,7 @@ import java.net.InetSocketAddress; import static java.util.Arrays.asList; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.openhft.chronicle.map.Builder.getPersistenceFile; +import static net.openhft.chronicle.set.Builder.getPersistenceFile; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java b/src/test/java/net/openhft/chronicle/set/TCPSocketReplication3VoidValueTest.java old mode 100755 new mode 100644 similarity index 92% rename from src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java rename to src/test/java/net/openhft/chronicle/set/TCPSocketReplication3VoidValueTest.java index c9dfa92e2..89e35eef0 --- a/src/test/java/net/openhft/chronicle/map/TCPSocketReplication3VoidValueTest.java +++ b/src/test/java/net/openhft/chronicle/set/TCPSocketReplication3VoidValueTest.java @@ -14,9 +14,11 @@ * along with this program. If not, see . */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.set; -import net.openhft.chronicle.hash.serialization.internal.DummyValue; +import net.openhft.chronicle.map.ChannelReplicationTest; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.set.DummyValue; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -26,8 +28,8 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.util.Set; -import static net.openhft.chronicle.hash.serialization.internal.DummyValue.DUMMY_VALUE; -import static net.openhft.chronicle.map.Builder.newMapDummyValue; +import static net.openhft.chronicle.set.DummyValue.DUMMY_VALUE; +import static net.openhft.chronicle.set.Builder.newMapDummyValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/net/openhft/lang/values/DoubleArray.java b/src/test/java/net/openhft/lang/values/DoubleArray.java index 39e1b8979..6333bbb24 100755 --- a/src/test/java/net/openhft/lang/values/DoubleArray.java +++ b/src/test/java/net/openhft/lang/values/DoubleArray.java @@ -16,10 +16,10 @@ package net.openhft.lang.values; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.DirectStore; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.Copyable; +import net.openhft.chronicle.bytes.Byteable; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.NativeBytesStore; +import net.openhft.chronicle.values.Copyable; /** * Created by peter.lawrey on 23/04/2015. @@ -30,7 +30,7 @@ public class DoubleArray implements Byteable, Copyable { private static int LENGTH = CAPACITY + 4; // assume a 32-bit size. private static int BASE = LENGTH + 4; - private Bytes bytes; + private BytesStore bs; private long offset; // creates an empty DoubleArray @@ -38,21 +38,21 @@ public class DoubleArray implements Byteable, Copyable { } public DoubleArray(int capacity) { - bytes = DirectStore.allocate(BASE + capacity * 8L).bytes(); - bytes.writeInt(CAPACITY, capacity); + bs = NativeBytesStore.nativeStoreWithFixedCapacity(BASE + capacity * 8L); + bs.writeInt(CAPACITY, capacity); offset = 0; } @Override - public void bytes(Bytes bytes, long offset) { - this.bytes = bytes; + public void bytesStore(BytesStore bytes, long offset, long maxSize) { + this.bs = bytes; this.offset = offset; } @Override - public Bytes bytes() { - return bytes; + public BytesStore bytesStore() { + return bs; } @Override @@ -61,53 +61,53 @@ public class DoubleArray implements Byteable, Copyable { } @Override - public int maxSize() { + public long maxSize() { return BASE + length() * 8; } public int length() { - return HACK && bytes == null ? 6 * 8 : bytes.readInt(LENGTH + offset); + return HACK && bs == null ? 6 * 8 : bs.readInt(LENGTH + offset); } public int capacity() { - return bytes.readInt(CAPACITY + offset); + return bs.readInt(CAPACITY + offset); } public double getDataAt(int index) { if (index < 0 || index >= length()) throw new ArrayIndexOutOfBoundsException(); - return bytes.readDouble(BASE + offset + index * 8L); + return bs.readDouble(BASE + offset + index * 8L); } public void setDataAt(int index, double d) { if (index < 0 || index >= capacity()) throw new ArrayIndexOutOfBoundsException(); if (length() <= index) setLength(index + 1); - bytes.writeDouble(BASE + offset + index * 8L, d); + bs.writeDouble(BASE + offset + index * 8L, d); } public void setLength(int length) { if (length < 0 || length >= capacity()) throw new IllegalArgumentException(); - bytes.writeInt(LENGTH + offset, length); + bs.writeInt(LENGTH + offset, length); } public void addData(double d) { int index = length(); if (index >= capacity()) throw new IllegalStateException(); - bytes.writeInt(LENGTH + offset, index + 1); - bytes.writeDouble(BASE + offset + index * 8L, d); + bs.writeInt(LENGTH + offset, index + 1); + bs.writeDouble(BASE + offset + index * 8L, d); } public void setData(double[] doubles) { if (doubles.length > capacity()) throw new IllegalArgumentException(); - bytes.writeInt(LENGTH + offset, doubles.length); + bs.writeInt(LENGTH + offset, doubles.length); for (int index = 0; index < doubles.length; index++) - bytes.writeDouble(BASE + offset + index * 8L, doubles[index]); + bs.writeDouble(BASE + offset + index * 8L, doubles[index]); } public int getDataUsing(double[] doubles) { int length = Math.min(length(), doubles.length); for (int index = 0; index < length; index++) - doubles[index] = bytes.readDouble(BASE + offset + index * 8L); + doubles[index] = bs.readDouble(BASE + offset + index * 8L); return length; } diff --git a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java index 1abb6e528..61560aca7 100755 --- a/src/test/java/net/openhft/lang/values/DoubleArrayTest.java +++ b/src/test/java/net/openhft/lang/values/DoubleArrayTest.java @@ -62,7 +62,7 @@ public class DoubleArrayTest { // expected } // free the memory. - da.bytes().release(); + da.bytesStore().release(); } @Test diff --git a/src/test/java/net/openhft/lang/values/IntValue$$Native.java b/src/test/java/net/openhft/lang/values/IntValue$$Native.java deleted file mode 100644 index 404ebca7e..000000000 --- a/src/test/java/net/openhft/lang/values/IntValue$$Native.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.lang.values; - -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class IntValue$$Native implements IntValue, BytesMarshallable, Byteable, Copyable { - private static final int VALUE = 0; - - private Bytes _bytes; - private long _offset; - - public void setValue(int $) { - _bytes.writeInt(_offset + VALUE, $); - } - - public int getValue() { - return _bytes.readInt(_offset + VALUE); - } - - public void setOrderedValue(int $) { - _bytes.writeOrderedInt(_offset + VALUE, $); - } - - public int getVolatileValue() { - return _bytes.readVolatileInt(_offset + VALUE); - } - - public int addValue(int $) { - return _bytes.addInt(_offset + VALUE, $); - } - - public int addAtomicValue(int $) { - return _bytes.addAtomicInt(_offset + VALUE, $); - } - - public boolean compareAndSwapValue(int _1, int _2) { - return _bytes.compareAndSwapInt(_offset + VALUE, _1, _2); - } - - public boolean tryLockNanosValue(long nanos) { - return _bytes.tryLockNanosInt(_offset + VALUE, nanos); - } - - public boolean tryLockValue() { - return _bytes.tryLockInt(_offset + VALUE); - } - - @Deprecated() - public void unlockValue() { - _bytes.unlockInt(_offset + VALUE); - } - - @Deprecated() - public void busyLockValue() throws InterruptedException { - _bytes.busyLockInt(_offset + VALUE); - } - - @Override - public void copyFrom(net.openhft.lang.values.IntValue from) { - setValue(from.getValue()); - } - - @Override - public void writeMarshallable(Bytes out) { - out.writeInt(getValue()); - } - - @Override - public void readMarshallable(Bytes in) { - setValue(in.readInt()); - } - - @Override - public void bytes(Bytes bytes, long offset) { - this._bytes = bytes; - this._offset = offset; - } - - @Override - public Bytes bytes() { - return _bytes; - } - - @Override - public long offset() { - return _offset; - } - - @Override - public int maxSize() { - return 4; - } - - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return calcLongHashCode(getValue()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof IntValue)) return false; - IntValue that = (IntValue) o; - - if (!isEqual(getValue(), that.getValue())) return false; - return true; - } - - public String toString() { - if (_bytes == null) return "bytes is null"; - StringBuilder sb = new StringBuilder(); - sb.append("IntValue{ "); - sb.append("value= ").append(getValue()); - sb.append(" }"); - return sb.toString(); - } -} \ No newline at end of file diff --git a/src/test/java/net/openhft/lang/values/LongValue$$Native.java b/src/test/java/net/openhft/lang/values/LongValue$$Native.java deleted file mode 100644 index f9ff73dc9..000000000 --- a/src/test/java/net/openhft/lang/values/LongValue$$Native.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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.lang.values; - -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.serialization.BytesMarshallable; -import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.Copyable; - -import static net.openhft.lang.Compare.calcLongHashCode; -import static net.openhft.lang.Compare.isEqual; - -public class LongValue$$Native implements LongValue, BytesMarshallable, Byteable, Copyable { - private static final int VALUE = 0; - - private Bytes _bytes; - private long _offset; - - public void setValue(long $) { - _bytes.writeLong(_offset + VALUE, $); - } - - public long getValue() { - return _bytes.readLong(_offset + VALUE); - } - - public void setOrderedValue(long $) { - _bytes.writeOrderedLong(_offset + VALUE, $); - } - - public long getVolatileValue() { - return _bytes.readVolatileLong(_offset + VALUE); - } - - public long addValue(long $) { - return _bytes.addLong(_offset + VALUE, $); - } - - public long addAtomicValue(long $) { - return _bytes.addAtomicLong(_offset + VALUE, $); - } - - public boolean compareAndSwapValue(long _1, long _2) { - return _bytes.compareAndSwapLong(_offset + VALUE, _1, _2); - } - - @Override - public void copyFrom(net.openhft.lang.values.LongValue from) { - setValue(from.getValue()); - } - - @Override - public void writeMarshallable(Bytes out) { - out.writeLong(getValue()); - } - - @Override - public void readMarshallable(Bytes in) { - setValue(in.readLong()); - } - - @Override - public void bytes(Bytes bytes, long offset) { - this._bytes = bytes; - this._offset = offset; - } - - @Override - public Bytes bytes() { - return _bytes; - } - - @Override - public long offset() { - return _offset; - } - - @Override - public int maxSize() { - return 8; - } - - public int hashCode() { - long lhc = longHashCode(); - return (int) ((lhc >>> 32) ^ lhc); - } - - public long longHashCode() { - return calcLongHashCode(getValue()); - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof LongValue)) return false; - LongValue that = (LongValue) o; - - if (!isEqual(getValue(), that.getValue())) return false; - return true; - } - - public String toString() { - if (_bytes == null) return "bytes is null"; - StringBuilder sb = new StringBuilder(); - sb.append("LongValue{ "); - sb.append("value= ").append(getValue()); - sb.append(" }"); - return sb.toString(); - } -}