8221696: MappedByteBuffer.force method to specify range

Overload MappedByteBuffer.force to accept index and length arguments

Reviewed-by: dfuchs, alanb, bpb
This commit is contained in:
Andrew Dinn 2019-04-25 17:27:37 +01:00
parent 3103d346a7
commit 2b55e4834e
2 changed files with 142 additions and 8 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@ package java.nio;
import java.io.FileDescriptor;
import java.lang.ref.Reference;
import java.util.Objects;
import jdk.internal.misc.Unsafe;
@ -91,20 +92,52 @@ public abstract class MappedByteBuffer
this.fd = null;
}
// 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.
// Returns the distance (in bytes) of the buffer start from the
// largest page aligned address of the mapping less than or equal
// to the start address.
private long mappingOffset() {
return mappingOffset(0);
}
// Returns the distance (in bytes) of the buffer element
// identified by index from the largest page aligned address of
// the mapping less than or equal to the element address. Computed
// each time to avoid storing in every direct buffer.
private long mappingOffset(int index) {
int ps = Bits.pageSize();
long offset = address % ps;
return (offset >= 0) ? offset : (ps + offset);
long indexAddress = address + index;
long baseAddress = (indexAddress & ~(ps-1));
return indexAddress - baseAddress;
}
// Given an offset previously obtained from calling
// mappingOffset() returns the largest page aligned address of the
// mapping less than or equal to the buffer start address.
private long mappingAddress(long mappingOffset) {
return address - mappingOffset;
return mappingAddress(mappingOffset, 0);
}
// Given an offset previously otained from calling
// mappingOffset(index) returns the largest page aligned address
// of the mapping less than or equal to the address of the buffer
// element identified by index.
private long mappingAddress(long mappingOffset, long index) {
long indexAddress = address + index;
return indexAddress - mappingOffset;
}
// given a mappingOffset previously otained from calling
// mappingOffset() return that offset added to the buffer
// capacity.
private long mappingLength(long mappingOffset) {
return (long)capacity() + mappingOffset;
return mappingLength(mappingOffset, (long)capacity());
}
// given a mappingOffset previously otained from calling
// mappingOffset(index) return that offset added to the supplied
// length.
private long mappingLength(long mappingOffset, long length) {
return length + mappingOffset;
}
/**
@ -212,6 +245,58 @@ public abstract class MappedByteBuffer
return this;
}
/**
* Forces any changes made to a region of this buffer's content to
* be written to the storage device containing the mapped
* file. The region starts at the given {@code index} in this
* buffer and is {@code length} bytes.
*
* <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 selected region buffer since it
* was created, or since this method was last invoked, will have
* been written to that device. The force operation is free to
* write bytes that lie outside the specified region, for example
* to ensure that data blocks of some device-specific granularity
* are transferred in their entirety.
*
* <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 index
* The index of the first byte in the buffer region that is
* to be written back to storage; must be non-negative
* and less than limit()
*
* @param length
* The length of the region in bytes; must be non-negative
* and no larger than limit() - index
*
* @throws IndexOutOfBoundsException
* if the preconditions on the index and length do not
* hold.
*
* @return This buffer
*
* @since 13
*/
public final MappedByteBuffer force(int index, int length) {
if (fd == null) {
return this;
}
if ((address != 0) && (limit() != 0)) {
// check inputs
Objects.checkFromIndexSize(index, length, limit());
long offset = mappingOffset(index);
force0(fd, mappingAddress(offset, index), mappingLength(offset, length));
}
return this;
}
private native boolean isLoaded0(long address, long length, int pageCount);
private native void load0(long address, long length);
private native void force0(FileDescriptor fd, long address, long length);