package voldemort.store.readonly.io.jna; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.apache.log4j.Logger; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Pointer; public class mman { private static final Logger logger = Logger.getLogger(mman.class); public static final int PROT_READ = 0x1; /* Page can be read. */ public static final int PROT_WRITE = 0x2; /* Page can be written. */ public static final int PROT_EXEC = 0x4; /* Page can be executed. */ public static final int PROT_NONE = 0x0; /* Page can not be accessed. */ public static final int MAP_SHARED = 0x01; /* Share changes. */ public static final int MAP_PRIVATE = 0x02; /* Changes are private. */ // http://linux.die.net/man/2/mmap // http://www.opengroup.org/sud/sud1/xsh/mmap.htm // http://linux.die.net/include/sys/mman.h // http://linux.die.net/include/bits/mman.h // off_t = 8 // size_t = 8 /** * Map the given region of the given file descriptor into memory. * Returns a Pointer to the newly mapped memory throws an * IOException on error. */ public static Pointer mmap(long len, int prot, int flags, int fildes, long off) throws IOException { // we don't really have a need to change the recommended pointer. Pointer addr = new Pointer(0); Pointer result = Delegate.mmap(addr, new NativeLong(len), prot, flags, fildes, new NativeLong(off)); if(Pointer.nativeValue(result) == -1) { if(logger.isDebugEnabled()) logger.debug(errno.strerror()); throw new IOException("mmap failed: " + errno.strerror()); } return result; } /** * Unmap the given region. Returns 0 on success or -1 (and sets * errno) on failure. */ public static int munmap(Pointer addr, long len) throws IOException { int result = Delegate.munmap(addr, new NativeLong(len)); if(result != 0) { if(logger.isDebugEnabled()) logger.debug(errno.strerror()); throw new IOException("munmap failed: " + errno.strerror()); } return result; } /** * Lock the given region. Does not report failures. */ public static void mlock(Pointer addr, long len) { int res = Delegate.mlock(addr, new NativeLong(len)); if(res != 0) { if(logger.isDebugEnabled()) { logger.debug("Mlock failed probably because of insufficient privileges, errno:" + errno.strerror() + ", return value:" + res); } } else { if(logger.isDebugEnabled()) logger.debug("Mlock successfull"); } } /** * Unlock the given region. Does not report failures. */ public static void munlock(Pointer addr, long len) { if(Delegate.munlock(addr, new NativeLong(len)) != 0) { if(logger.isDebugEnabled()) logger.debug("munlocking failed with errno:" + errno.strerror()); } else { if(logger.isDebugEnabled()) logger.debug("munlocking region"); } } static class Delegate { public static native Pointer mmap(Pointer addr, NativeLong len, int prot, int flags, int fildes, NativeLong off); public static native int munmap(Pointer addr, NativeLong len); public static native int mlock(Pointer addr, NativeLong len); public static native int munlock(Pointer addr, NativeLong len); static { Native.register("c"); } } public static void main(String[] args) throws Exception { String path = args[0]; File file = new File(path); FileInputStream in = new FileInputStream(file); int fd = voldemort.store.readonly.io.Native.getFd(in.getFD()); if(logger.isDebugEnabled()) logger.debug("File descriptor is: " + fd); // mmap a large file... Pointer addr = mmap(file.length(), PROT_READ, mman.MAP_SHARED, fd, 0L); if(logger.isDebugEnabled()) logger.debug("mmap address is: " + Pointer.nativeValue(addr)); // try to mlock it directly mlock(addr, file.length()); munlock(addr, file.length()); munmap(addr, file.length()); } }