< prev index next >

src/java.base/share/classes/java/nio/MappedByteBuffer.java

Print this page

        

@@ -75,22 +75,36 @@
 
     // For mapped buffers, a FileDescriptor that may be used for mapping
     // operations if valid; null if the buffer is not mapped.
     private final FileDescriptor fd;
 
+    // A flag true if this buffer is mapped against persistent memory
+    // via a call to FileChannel.map_persistent and false if it is
+    // some other sort of file mapped via a call to FileChannel.map.
+    // this flag only determines the behaviour of force operations.
+    private final boolean isPersistent;
+    
     // This should only be invoked by the DirectByteBuffer constructors
     //
     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
-                     FileDescriptor fd)
-    {
+                     FileDescriptor fd, boolean isPersistent) {
         super(mark, pos, lim, cap);
         this.fd = fd;
+        this.isPersistent = isPersistent;
+    }
+
+    MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
+                     boolean isPersistent) {
+        super(mark, pos, lim, cap);
+        this.fd = null;
+        this.isPersistent = isPersistent;
     }
 
     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
         super(mark, pos, lim, cap);
         this.fd = null;
+        this.isPersistent = false;
     }
 
     // Returns the distance (in bytes) of the buffer from the page aligned address
     // of the mapping. Computed each time to avoid storing in every direct buffer.
     private long mappingOffset() {

@@ -106,10 +120,25 @@
     private long mappingLength(long mappingOffset) {
         return (long)capacity() + mappingOffset;
     }
 
     /**
+     * Tells whether this buffer was mapped against persistent memory
+     * by calling {@link java.nio.channels.FileChannel#map_persistent
+     * FileChannel.map_persistent} or mapped against some other form
+     * of device file using {@link java.nio.channels.FileChannel#map
+     * FileChannel.map}.
+     *
+     * @return true if the file was mapped using {@link
+     * java.nio.channels.FileChannel#map_persistent
+     * FileChannel.map_persistent} otherwise false.
+     */
+    public boolean isPersistent() {
+        return isPersistent;
+    }
+    
+    /**
      * Tells whether or not this buffer's content is resident in physical
      * memory.
      *
      * <p> A return value of {@code true} implies that it is highly likely
      * that all of the data in this buffer is resident in physical memory and

@@ -127,10 +156,14 @@
      */
     public final boolean isLoaded() {
         if (fd == null) {
             return true;
         }
+        // a persistent mapped buffer is always loaded
+        if (isPersistent()) {
+            return true;
+        }
         if ((address == 0) || (capacity() == 0))
             return true;
         long offset = mappingOffset();
         long length = mappingLength(offset);
         return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length));

@@ -151,10 +184,14 @@
      */
     public final MappedByteBuffer load() {
         if (fd == null) {
             return this;
         }
+        // no need to load a persistent mapped buffer
+        if (isPersistent()) {
+            return this;
+        }
         if ((address == 0) || (capacity() == 0))
             return this;
         long offset = mappingOffset();
         long length = mappingLength(offset);
         load0(mappingAddress(offset), length);

@@ -200,16 +237,64 @@
      * method has no effect. </p>
      *
      * @return  This buffer
      */
     public final MappedByteBuffer force() {
+        return force(0, capacity());
+    }
+
+    /**
+     * Forces any changes made to some subregion of this buffer's
+     * content to be written to the storage device containing the
+     * mapped file.
+     *
+     * <p> If the file mapped into this buffer resides on a local storage
+     * device then when this method returns it is guaranteed that all changes
+     * made to the buffer since it was created, or since this method was last
+     * invoked, will have been written to that device.
+     *
+     * <p> If the file does not reside on a local device then no such guarantee
+     * is made.
+     *
+     * <p> If this buffer was not mapped in read/write mode ({@link
+     * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this
+     * method has no effect. </p>
+     *
+     * @param from
+     *        The offset to the first byte in the buffer subregion
+     *        that is to be written back to storage
+     *
+     * @param to
+     *        The offset to the first byte beyond the buffer subregion
+     *        that is to be written back to storage
+     *
+     * @return  This buffer
+     */
+    public final MappedByteBuffer force(long from, long to) {
         if (fd == null) {
             return this;
         }
         if ((address != 0) && (capacity() != 0)) {
+            // check inputs
+            if (from < 0 || from >= capacity()) {
+                throw new IllegalArgumentException();
+            }
+            if (to < from || to > capacity()) {
+                throw new IllegalArgumentException();
+            }
+            
             long offset = mappingOffset();
-            force0(fd, mappingAddress(offset), mappingLength(offset));
+            long a = mappingAddress(offset) + from;
+            long length = offset + to;
+            if (isPersistent) {
+                // simply force writeback of associated cache lines
+                Unsafe unsafe = Unsafe.getUnsafe();
+                unsafe.writebackMemory(a, length);
+            } else {
+                // writeback using device associated with fd
+                force0(fd, a, length);
+            }
         }
         return this;
     }
 
     private native boolean isLoaded0(long address, long length, int pageCount);
< prev index next >