mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Fix msync JNA implementations and add SimplePersistedMapOverflowTest
This commit is contained in:
@@ -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<K,
|
||||
|
||||
if (persisted()) {
|
||||
long address = tierBytesStore.address(firstTierOffset - tierBulkInnerOffsetToTiers);
|
||||
// address should be a multiple of page size
|
||||
if (OS.pageAlign(address) != address) {
|
||||
address = OS.pageAlign(address) - OS.pageSize();
|
||||
}
|
||||
long endAddress = tierBytesStore.address(tierBytesOffset(lastTierIndex)) + tierSize;
|
||||
long length = endAddress - address;
|
||||
msync(raf, address, length);
|
||||
@@ -777,6 +775,12 @@ public abstract class VanillaChronicleHash<K,
|
||||
}
|
||||
|
||||
private static void msync(RandomAccessFile raf, long address, long length) throws IOException {
|
||||
// address should be a multiple of page size
|
||||
if (OS.pageAlign(address) != address) {
|
||||
long oldAddress = address;
|
||||
address = OS.pageAlign(address) - OS.pageSize();
|
||||
length += oldAddress - address;
|
||||
}
|
||||
if (OS.isWindows()) {
|
||||
WindowsMsync.msync(raf, address, length);
|
||||
} else {
|
||||
|
||||
+21
-7
@@ -14,29 +14,43 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-10
@@ -14,17 +14,21 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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() {}
|
||||
}
|
||||
Reference in New Issue
Block a user