Fix msync JNA implementations and add SimplePersistedMapOverflowTest

This commit is contained in:
leventov
2016-02-05 16:35:46 +07:00
parent 288aaa0920
commit 01f15fb9b1
4 changed files with 79 additions and 21 deletions
@@ -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 {
@@ -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);
}
}
}
@@ -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() {}
}