diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java old mode 100644 new mode 100755 index fb48abd51..7a80a7638 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -708,8 +708,8 @@ public abstract class VanillaChronicleHash implements DataAcc // no fields to read initTransients(); } + + @Override + public String toString() { + return new String(array, 0, 0, array.length); + } } diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index b74200b0c..72ef14a10 100755 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -730,6 +730,8 @@ public final class ChronicleMapBuilder implements } if (actualChunkSize <= 0) throw new IllegalArgumentException("Chunk size must be positive"); + if (alignment > 0 && actualChunkSize % alignment != 0) + throw new IllegalArgumentException("The chunk size (" + actualChunkSize + ") must be a multiple of the alignment (" + alignment + ")"); this.actualChunkSize = actualChunkSize; return this; } @@ -928,16 +930,25 @@ public final class ChronicleMapBuilder implements } if (Jvm.isArm() && alignment < 8) return this; + validateAlignment(actualChunkSize, actualChunkSize, alignment); + this.alignment = alignment; return this; } + public void validateAlignment(int ifSet, int actualChunkSize, int alignment) { + if (ifSet > 0 && actualChunkSize % alignment != 0) + throw new IllegalArgumentException("The chunk size (" + actualChunkSize + ") must be a multiple of the alignment (" + alignment + ")"); + } + int valueAlignment() { if (alignment != UNDEFINED_ALIGNMENT_CONFIG) return alignment; try { if (Values.isValueInterfaceOrImplClass(valueBuilder.tClass)) { - return ValueModel.acquire(valueBuilder.tClass).recommendedOffsetAlignment(); + int alignment = ValueModel.acquire(valueBuilder.tClass).recommendedOffsetAlignment(); + validateAlignment(alignment, actualChunkSize, alignment); + return alignment; } else { return NO_ALIGNMENT; } diff --git a/src/test/java/net/openhft/chronicle/map/ValueAlignmentRelocationTest.java b/src/test/java/net/openhft/chronicle/map/ValueAlignmentRelocationTest.java index f5f7f6fb5..2330fcc48 100755 --- a/src/test/java/net/openhft/chronicle/map/ValueAlignmentRelocationTest.java +++ b/src/test/java/net/openhft/chronicle/map/ValueAlignmentRelocationTest.java @@ -20,17 +20,24 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; public class ValueAlignmentRelocationTest { private final boolean persisted; + private final int alignment; + private final int chunk; - public ValueAlignmentRelocationTest(String name, boolean persisted) { + public ValueAlignmentRelocationTest(String name, boolean persisted, int alignment, int chunk) { this.persisted = persisted; + this.alignment = alignment; + this.chunk = chunk; } @Parameterized.Parameters(name = "{0}") public static Collection data() { return Arrays.asList(new Object[][]{ - // TODO FIX https://github.com/OpenHFT/Chronicle-Map/issues/169 -// {"Volatile", false}, - {"Persisted", true} + {"Volatile a=1, c=1", false, 1, 1}, + {"Volatile a=1, c=2", false, 1, 2}, + {"Volatile a=4, c=4", false, 4, 4}, + {"Volatile a=4, c=8", false, 4, 8}, + {"Persisted a=1, c=1", true, 1, 1}, + {"Persisted a=4, c=8", true, 4, 8} }); } @@ -42,7 +49,7 @@ public class ValueAlignmentRelocationTest { @Test public void testValueAlignmentRelocation() throws IOException { - File file = Files.createTempFile("test", "cm3").toFile(); + File file = Files.createTempFile("test", ".cm3").toFile(); file.deleteOnExit(); ChronicleMapBuilder builder = ChronicleMapBuilder @@ -51,9 +58,9 @@ public class ValueAlignmentRelocationTest { .averageValueSize(5) .keySizeMarshaller(SizeMarshaller.stopBit()) .valueSizeMarshaller(SizeMarshaller.stopBit()) - .entryAndValueOffsetAlignment(8) + .entryAndValueOffsetAlignment(alignment) .actualSegments(1) - .actualChunkSize(2) + .actualChunkSize(chunk) .entries(10); ChronicleMap map = persisted ? builder.createPersistedTo(file) : builder.create(); Random r = new Random(0); @@ -90,7 +97,7 @@ public class ValueAlignmentRelocationTest { @Test public void testValueAlignmentRelocationNoRandomTest() throws IOException { - File file = Files.createTempFile("test", "cm3").toFile(); + File file = Files.createTempFile("test", ".cm3").toFile(); file.deleteOnExit(); ChronicleMapBuilder builder = ChronicleMapBuilder @@ -99,15 +106,15 @@ public class ValueAlignmentRelocationTest { .averageValueSize(5) .keySizeMarshaller(SizeMarshaller.stopBit()) .valueSizeMarshaller(SizeMarshaller.stopBit()) - .entryAndValueOffsetAlignment(8) + .entryAndValueOffsetAlignment(alignment) .actualSegments(1) - .actualChunkSize(2) + .actualChunkSize(chunk) .entries(10); ChronicleMap map = persisted ? builder.createPersistedTo(file) : builder.create(); for (int k = 1; k <= 16; k++) { for (int i = 1; i < 10; i++) { - for (int j = i + 1; j <= i + 2; j++) { + for (int j = i + 1; j <= i + 10; j++) { map.clear(); byte[] _austi = "abcdefghijklmnopqrstuvwxyz".substring(0, k).getBytes(ISO_8859_1);