diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java index 333d006c5..a89942f33 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java @@ -26,6 +26,7 @@ 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.chronicle.map.utils.MultiMapFactory; import net.openhft.chronicle.set.ChronicleSetBuilder; import net.openhft.lang.Maths; import net.openhft.lang.io.ByteBufferBytes; @@ -344,13 +345,13 @@ public abstract class AbstractChronicleMapBuilder VanillaIntIntMultiMap.MAX_CAPACITY; + return entriesPerSegment > MultiMapFactory.MAX_CAPACITY; } long actualEntriesPerSegment() { @@ -361,7 +362,7 @@ public abstract class AbstractChronicleMapBuilder 0) return actualSegments; - long shortMMapSegments = trySegments(VanillaShortShortMultiMap.MAX_CAPACITY, + long shortMMapSegments = trySegments(MultiMapFactory.I16_MAX_CAPACITY, MAX_SEGMENTS_TO_CHAISE_COMPACT_MULTI_MAPS); if (shortMMapSegments > 0L) return (int) shortMMapSegments; - long intMMapSegments = trySegments(VanillaIntIntMultiMap.MAX_CAPACITY, MAX_SEGMENTS); + long intMMapSegments = trySegments(MultiMapFactory.MAX_CAPACITY, MAX_SEGMENTS); if (intMMapSegments > 0L) return (int) intMMapSegments; throw new IllegalStateException("Max segments is " + MAX_SEGMENTS + ", configured so much" + @@ -938,5 +939,9 @@ public abstract class AbstractChronicleMapBuilder, private final int segmentHeaderSize; private final HashSplitting hashSplitting; final boolean isNativeValueClass; + final MultiMapFactory multiMapFactory; transient Provider> keyReaderProvider; transient Provider keyInteropProvider; transient Provider> valueReaderProvider; @@ -142,6 +144,7 @@ class VanillaChronicleMap, this.actualSegments = builder.actualSegments(); this.entriesPerSegment = builder.actualEntriesPerSegment(); + this.multiMapFactory = builder.multiMapFactory(); this.metaDataBytes = builder.metaDataBytes(); this.eventListener = builder.eventListener(); this.segmentHeaderSize = builder.segmentHeaderSize(); @@ -247,19 +250,11 @@ class VanillaChronicleMap, } long sizeOfMultiMap() { - return useSmallMultiMaps() ? - VanillaShortShortMultiMap.sizeInBytes(entriesPerSegment) : - VanillaIntIntMultiMap.sizeInBytes(entriesPerSegment); + return multiMapFactory.sizeInBytes(entriesPerSegment); } long sizeOfMultiMapBitSet() { - return useSmallMultiMaps() ? - VanillaShortShortMultiMap.sizeOfBitSetInBytes(entriesPerSegment) : - VanillaIntIntMultiMap.sizeOfBitSetInBytes(entriesPerSegment); - } - - boolean useSmallMultiMaps() { - return entriesPerSegment <= VanillaShortShortMultiMap.MAX_CAPACITY; + return multiMapFactory.sizeOfBitSetInBytes(entriesPerSegment); } long sizeOfBitSets() { @@ -725,9 +720,7 @@ class VanillaChronicleMap, new NativeBytes(new VanillaBytesMarshallerFactory(), start, start + sizeOfMultiMapBitSet(), null); multiMapBytes.load(); - return useSmallMultiMaps() ? - new VanillaShortShortMultiMap(multiMapBytes, sizeOfMultiMapBitSetBytes) : - new VanillaIntIntMultiMap(multiMapBytes, sizeOfMultiMapBitSetBytes); + return multiMapFactory.create(multiMapBytes, sizeOfMultiMapBitSetBytes); } public int getIndex() { diff --git a/src/main/java/net/openhft/chronicle/map/IntIntMultiMap.java b/src/main/java/net/openhft/chronicle/map/utils/IntIntMultiMap.java similarity index 98% rename from src/main/java/net/openhft/chronicle/map/IntIntMultiMap.java rename to src/main/java/net/openhft/chronicle/map/utils/IntIntMultiMap.java index e51c4f9ae..7f444e02c 100644 --- a/src/main/java/net/openhft/chronicle/map/IntIntMultiMap.java +++ b/src/main/java/net/openhft/chronicle/map/utils/IntIntMultiMap.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import net.openhft.lang.collection.DirectBitSet; diff --git a/src/main/java/net/openhft/chronicle/map/MultiMap.java b/src/main/java/net/openhft/chronicle/map/utils/MultiMap.java similarity index 96% rename from src/main/java/net/openhft/chronicle/map/MultiMap.java rename to src/main/java/net/openhft/chronicle/map/utils/MultiMap.java index 60d013d1d..c7104ae87 100644 --- a/src/main/java/net/openhft/chronicle/map/MultiMap.java +++ b/src/main/java/net/openhft/chronicle/map/utils/MultiMap.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import net.openhft.lang.collection.DirectBitSet; /** * This is only used to store keys and positions, but it could store int/int key/values for another purpose. */ -interface MultiMap { +public interface MultiMap { /** * @return gets all the active positions as a bitset diff --git a/src/main/java/net/openhft/chronicle/map/utils/MultiMapFactory.java b/src/main/java/net/openhft/chronicle/map/utils/MultiMapFactory.java new file mode 100644 index 000000000..a2c445c17 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/utils/MultiMapFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright 2014 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.utils; + +import net.openhft.lang.io.NativeBytes; + +/** + * Created by peter on 09/11/14. + * + * In future we might support I32 -> I16 or similar. + */ +public enum MultiMapFactory { + I16 { + @Override + public long sizeInBytes(long minCapacity) { + return VanillaShortShortMultiMap.sizeInBytes(minCapacity); + } + + @Override + public long sizeOfBitSetInBytes(long minCapacity) { + return VanillaShortShortMultiMap.sizeOfBitSetInBytes(minCapacity); + } + + @Override + public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) { + return new VanillaShortShortMultiMap(bytes, bitSetBytes); + } + }, + I24 { + @Override + public long sizeInBytes(long minCapacity) { + return VanillaI24I24MultiMap.sizeInBytes(minCapacity); + } + + @Override + public long sizeOfBitSetInBytes(long minCapacity) { + return VanillaI24I24MultiMap.sizeOfBitSetInBytes(minCapacity); + } + + @Override + public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) { + return new VanillaI24I24MultiMap(bytes, bitSetBytes); + } + }, + I32 { + @Override + public long sizeInBytes(long minCapacity) { + return VanillaIntIntMultiMap.sizeInBytes(minCapacity); + } + + @Override + public long sizeOfBitSetInBytes(long minCapacity) { + return VanillaIntIntMultiMap.sizeOfBitSetInBytes(minCapacity); + } + + @Override + public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) { + return new VanillaIntIntMultiMap(bytes, bitSetBytes); + } + }; + + public static final long I16_MAX_CAPACITY = VanillaShortShortMultiMap.MAX_CAPACITY; + public static final long MAX_CAPACITY = VanillaIntIntMultiMap.MAX_CAPACITY; + + public static MultiMapFactory forCapacity(long capacity) { + if (capacity <= VanillaShortShortMultiMap.MAX_CAPACITY) + return I16; +// if (capacity <= VanillaI24I24MultiMap.MAX_CAPACITY) +// return I24; + if (capacity <= VanillaIntIntMultiMap.MAX_CAPACITY) + return I32; + throw new IllegalArgumentException("Capacity " + capacity + " not supported"); + } + + public abstract long sizeInBytes(long minCapacity); + + public abstract long sizeOfBitSetInBytes(long minCapacity); + + public abstract MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes); +} diff --git a/src/main/java/net/openhft/chronicle/map/VanillaI24I24MultiMap.java b/src/main/java/net/openhft/chronicle/map/utils/VanillaI24I24MultiMap.java similarity index 99% rename from src/main/java/net/openhft/chronicle/map/VanillaI24I24MultiMap.java rename to src/main/java/net/openhft/chronicle/map/utils/VanillaI24I24MultiMap.java index cb96fdfde..01933c5db 100644 --- a/src/main/java/net/openhft/chronicle/map/VanillaI24I24MultiMap.java +++ b/src/main/java/net/openhft/chronicle/map/utils/VanillaI24I24MultiMap.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import net.openhft.lang.collection.ATSDirectBitSet; import net.openhft.lang.collection.DirectBitSet; diff --git a/src/main/java/net/openhft/chronicle/map/VanillaIntIntMultiMap.java b/src/main/java/net/openhft/chronicle/map/utils/VanillaIntIntMultiMap.java similarity index 99% rename from src/main/java/net/openhft/chronicle/map/VanillaIntIntMultiMap.java rename to src/main/java/net/openhft/chronicle/map/utils/VanillaIntIntMultiMap.java index 09e1c5b80..d1f2bd646 100644 --- a/src/main/java/net/openhft/chronicle/map/VanillaIntIntMultiMap.java +++ b/src/main/java/net/openhft/chronicle/map/utils/VanillaIntIntMultiMap.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import net.openhft.lang.Maths; import net.openhft.lang.collection.ATSDirectBitSet; diff --git a/src/main/java/net/openhft/chronicle/map/VanillaShortShortMultiMap.java b/src/main/java/net/openhft/chronicle/map/utils/VanillaShortShortMultiMap.java similarity index 98% rename from src/main/java/net/openhft/chronicle/map/VanillaShortShortMultiMap.java rename to src/main/java/net/openhft/chronicle/map/utils/VanillaShortShortMultiMap.java index 82670c5d6..00c9ea67a 100644 --- a/src/main/java/net/openhft/chronicle/map/VanillaShortShortMultiMap.java +++ b/src/main/java/net/openhft/chronicle/map/utils/VanillaShortShortMultiMap.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import net.openhft.lang.collection.ATSDirectBitSet; @@ -24,7 +24,7 @@ import net.openhft.lang.collection.DirectBitSet; import net.openhft.lang.io.Bytes; import net.openhft.lang.io.DirectStore; -import static net.openhft.chronicle.map.VanillaIntIntMultiMap.multiMapCapacity; +import static net.openhft.chronicle.map.utils.VanillaIntIntMultiMap.multiMapCapacity; import static net.openhft.lang.Maths.isPowerOf2; /** diff --git a/src/test/java/net/openhft/chronicle/map/IntIntMultiMapTest.java b/src/test/java/net/openhft/chronicle/map/utils/IntIntMultiMapTest.java similarity index 91% rename from src/test/java/net/openhft/chronicle/map/IntIntMultiMapTest.java rename to src/test/java/net/openhft/chronicle/map/utils/IntIntMultiMapTest.java index 852c339b0..9d1ad11a3 100644 --- a/src/test/java/net/openhft/chronicle/map/IntIntMultiMapTest.java +++ b/src/test/java/net/openhft/chronicle/map/utils/IntIntMultiMapTest.java @@ -16,13 +16,14 @@ * limitations under the License. */ -package net.openhft.chronicle.map; +package net.openhft.chronicle.map.utils; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.openhft.lang.collection.SingleThreadedDirectBitSet; import net.openhft.lang.io.DirectStore; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,9 +34,6 @@ import java.io.FileNotFoundException; import java.lang.reflect.Field; import java.util.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - /** * User: peter Date: 09/12/13 */ @@ -75,12 +73,12 @@ public class IntIntMultiMapTest { @Override public void accept(long key, long value) { mapSize++; - assertTrue(referenceMap.containsEntry(key, value)); + Assert.assertTrue(referenceMap.containsEntry(key, value)); } } Action action = new Action(); map.forEach(action); - assertEquals(referenceMap.size(), action.mapSize); + Assert.assertEquals(referenceMap.size(), action.mapSize); } private void valuesEqualsByKey(long k) { @@ -90,8 +88,8 @@ public class IntIntMultiMapTest { while ((v = map.nextPos()) >= 0L) values.add(v); Set valueSet = new HashSet(values); - assertEquals(values.size(), valueSet.size()); - assertEquals(new HashSet(referenceMap.get(k)), valueSet); + Assert.assertEquals(values.size(), valueSet.size()); + Assert.assertEquals(new HashSet(referenceMap.get(k)), valueSet); } private void put(long k, long v) { @@ -150,7 +148,7 @@ public class IntIntMultiMapTest { map.put(15, 1); map.remove(15, 1); map.startSearch(15); - assertTrue(map.nextPos() < 0); + Assert.assertTrue(map.nextPos() < 0); } @Test @@ -180,7 +178,7 @@ public class IntIntMultiMapTest { bs.set(value); } }); - assertTrue(bs.allSet(0L, maxCapacity)); + Assert.assertTrue(bs.allSet(0L, maxCapacity)); } private long maxMemory() {