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 65d47a13c..255529653 100644
--- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
+++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
@@ -24,6 +24,8 @@ 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.impl.util.jna.PosixMsync;
+import net.openhft.chronicle.hash.impl.util.jna.WindowsMsync;
import net.openhft.chronicle.hash.serialization.DataAccess;
import net.openhft.chronicle.hash.serialization.SizeMarshaller;
import net.openhft.chronicle.hash.serialization.SizedReader;
@@ -762,10 +764,6 @@ public abstract class VanillaChronicleHash.
*/
-package net.openhft.chronicle.hash.impl;
+package net.openhft.chronicle.hash.impl.util.jna;
+import com.sun.jna.IntegerType;
import com.sun.jna.Native;
import com.sun.jna.Platform;
+import com.sun.jna.Pointer;
import java.io.IOException;
-final class PosixMsync {
+public final class PosixMsync {
private static final int MS_SYNC = 4;
public static void msync(long addr, long length) throws IOException {
- if (msync(addr, length, MS_SYNC) == -1)
- throw new IOException(strerror_r(Native.getLastError(), null, 0));
+ if (msync(new Pointer(addr), new size_t(length), MS_SYNC) == -1)
+ throw new IOException("msync failed: error code " + Native.getLastError());
}
- private static native String strerror_r(int errnum, char[] buf, int buflen);
-
- private static native int msync(long addr, long length, int flags);
+ private static native int msync(Pointer addr, size_t length, int flags);
static {
Native.register(PosixMsync.class, Platform.C_LIBRARY_NAME);
}
private PosixMsync() {}
+
+ public static class size_t extends IntegerType {
+ private static final long serialVersionUID = 0L;
+
+ // no-arg constructor is required by JNA
+ @SuppressWarnings("unused")
+ public size_t() {
+ this(0);
+ }
+
+ public size_t(long value) {
+ super(Native.SIZE_T_SIZE, value, true);
+ }
+ }
}
diff --git a/src/main/java/net/openhft/chronicle/hash/impl/WindowsMsync.java b/src/main/java/net/openhft/chronicle/hash/impl/util/jna/WindowsMsync.java
similarity index 71%
rename from src/main/java/net/openhft/chronicle/hash/impl/WindowsMsync.java
rename to src/main/java/net/openhft/chronicle/hash/impl/util/jna/WindowsMsync.java
index b5f97d873..ce5043119 100644
--- a/src/main/java/net/openhft/chronicle/hash/impl/WindowsMsync.java
+++ b/src/main/java/net/openhft/chronicle/hash/impl/util/jna/WindowsMsync.java
@@ -14,17 +14,21 @@
* along with this program. If not, see .
*/
-package net.openhft.chronicle.hash.impl;
+package net.openhft.chronicle.hash.impl.util.jna;
import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
+import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
+import com.sun.jna.win32.W32APIOptions;
import java.io.IOException;
import java.io.RandomAccessFile;
import static com.sun.jna.platform.win32.WinError.ERROR_LOCK_VIOLATION;
-final class WindowsMsync {
+public final class WindowsMsync {
public static void msync(RandomAccessFile raf, long addr, long length)
throws IOException {
@@ -35,8 +39,8 @@ final class WindowsMsync {
// pages to disk. As there is no way to synchronize the flushing then we retry a limited
// number of times.
do {
- if ((success = FlushViewOfFile(addr, length)) ||
- (lastError = GetLastError()) != ERROR_LOCK_VIOLATION)
+ success = KERNEL_32.FlushViewOfFile(new Pointer(addr), new SIZE_T(length));
+ if (success || (lastError = KERNEL_32.GetLastError()) != ERROR_LOCK_VIOLATION)
break;
retry++;
} while (retry < 3);
@@ -49,13 +53,12 @@ final class WindowsMsync {
}
}
- private static native boolean FlushViewOfFile(long addr, long length);
-
- private static native int GetLastError();
-
- static {
- Native.register(WindowsMsync.class, "kernel32");
+ public interface Kernel32Ex extends Kernel32 {
+ boolean FlushViewOfFile(Pointer addr, SIZE_T length);
}
+ private static final Kernel32Ex KERNEL_32 = (Kernel32Ex)
+ Native.loadLibrary("kernel32", Kernel32Ex.class, W32APIOptions.UNICODE_OPTIONS);
+
private WindowsMsync() {}
}
diff --git a/src/test/java/net/openhft/chronicle/map/SimplePersistedMapOverflowTest.java b/src/test/java/net/openhft/chronicle/map/SimplePersistedMapOverflowTest.java
new file mode 100644
index 000000000..31c74b519
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/SimplePersistedMapOverflowTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.set.Builder;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SimplePersistedMapOverflowTest {
+
+ @Test
+ public void simplePersistedMapOverflowTest() throws IOException {
+ try (ChronicleMap map = ChronicleMap
+ .of(Integer.class, Integer.class)
+ .entries(1_000)
+ .createPersistedTo(Builder.getPersistenceFile())) {
+ for (int i = 0; i < 2_000; i++) {
+ map.put(i, i);
+ }
+ }
+ }
+}