mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
|
@ -0,0 +1,736 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2013, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.io.IOException;
|
||||
import java.io.FileDescriptor;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.JavaIOFileDescriptorAccess;
|
||||
|
||||
/**
|
||||
* Windows implementation of AsynchronousFileChannel using overlapped I/O.
|
||||
*/
|
||||
|
||||
public class WindowsAsynchronousFileChannelImpl
|
||||
extends AsynchronousFileChannelImpl
|
||||
implements Iocp.OverlappedChannel, Groupable
|
||||
{
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
// error when EOF is detected asynchronously.
|
||||
private static final int ERROR_HANDLE_EOF = 38;
|
||||
|
||||
// Lazy initialization of default I/O completion port
|
||||
private static class DefaultIocpHolder {
|
||||
static final Iocp defaultIocp = defaultIocp();
|
||||
private static Iocp defaultIocp() {
|
||||
try {
|
||||
return new Iocp(null, ThreadPool.createDefault()).start();
|
||||
} catch (IOException ioe) {
|
||||
throw new InternalError(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used for force/truncate/size methods
|
||||
private static final FileDispatcher nd = new FileDispatcherImpl();
|
||||
|
||||
// The handle is extracted for use in native methods invoked from this class.
|
||||
private final long handle;
|
||||
|
||||
// The key that identifies the channel's association with the I/O port
|
||||
private final int completionKey;
|
||||
|
||||
// I/O completion port (group)
|
||||
private final Iocp iocp;
|
||||
|
||||
private final boolean isDefaultIocp;
|
||||
|
||||
// Caches OVERLAPPED structure for each outstanding I/O operation
|
||||
private final PendingIoCache ioCache;
|
||||
|
||||
|
||||
private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj,
|
||||
boolean reading,
|
||||
boolean writing,
|
||||
Iocp iocp,
|
||||
boolean isDefaultIocp)
|
||||
throws IOException
|
||||
{
|
||||
super(fdObj, reading, writing, iocp.executor());
|
||||
this.handle = fdAccess.getHandle(fdObj);
|
||||
this.iocp = iocp;
|
||||
this.isDefaultIocp = isDefaultIocp;
|
||||
this.ioCache = new PendingIoCache();
|
||||
this.completionKey = iocp.associate(this, handle);
|
||||
}
|
||||
|
||||
public static AsynchronousFileChannel open(FileDescriptor fdo,
|
||||
boolean reading,
|
||||
boolean writing,
|
||||
ThreadPool pool)
|
||||
throws IOException
|
||||
{
|
||||
Iocp iocp;
|
||||
boolean isDefaultIocp;
|
||||
if (pool == null) {
|
||||
iocp = DefaultIocpHolder.defaultIocp;
|
||||
isDefaultIocp = true;
|
||||
} else {
|
||||
iocp = new Iocp(null, pool).start();
|
||||
isDefaultIocp = false;
|
||||
}
|
||||
try {
|
||||
return new
|
||||
WindowsAsynchronousFileChannelImpl(fdo, reading, writing, iocp, isDefaultIocp);
|
||||
} catch (IOException x) {
|
||||
// error binding to port so need to close it (if created for this channel)
|
||||
if (!isDefaultIocp)
|
||||
iocp.implClose();
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
|
||||
return ioCache.remove(overlapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closeLock.writeLock().lock();
|
||||
try {
|
||||
if (closed)
|
||||
return; // already closed
|
||||
closed = true;
|
||||
} finally {
|
||||
closeLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
// invalidate all locks held for this channel
|
||||
invalidateAllLocks();
|
||||
|
||||
// close the file
|
||||
close0(handle);
|
||||
|
||||
// waits until all I/O operations have completed
|
||||
ioCache.close();
|
||||
|
||||
// disassociate from port
|
||||
iocp.disassociate(completionKey);
|
||||
|
||||
// for the non-default group close the port
|
||||
if (!isDefaultIocp)
|
||||
iocp.detachFromThreadPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousChannelGroupImpl group() {
|
||||
return iocp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates Throwable to IOException
|
||||
*/
|
||||
private static IOException toIOException(Throwable x) {
|
||||
if (x instanceof IOException) {
|
||||
if (x instanceof ClosedChannelException)
|
||||
x = new AsynchronousCloseException();
|
||||
return (IOException)x;
|
||||
}
|
||||
return new IOException(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() throws IOException {
|
||||
try {
|
||||
begin();
|
||||
return nd.size(fdObj);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousFileChannel truncate(long size) throws IOException {
|
||||
if (size < 0)
|
||||
throw new IllegalArgumentException("Negative size");
|
||||
if (!writing)
|
||||
throw new NonWritableChannelException();
|
||||
try {
|
||||
begin();
|
||||
if (size > nd.size(fdObj))
|
||||
return this;
|
||||
nd.truncate(fdObj, size);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void force(boolean metaData) throws IOException {
|
||||
try {
|
||||
begin();
|
||||
nd.force(fdObj, metaData);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
// -- file locking --
|
||||
|
||||
/**
|
||||
* Task that initiates locking operation and handles completion result.
|
||||
*/
|
||||
private class LockTask<A> implements Runnable, Iocp.ResultHandler {
|
||||
private final long position;
|
||||
private final FileLockImpl fli;
|
||||
private final PendingFuture<FileLock,A> result;
|
||||
|
||||
LockTask(long position,
|
||||
FileLockImpl fli,
|
||||
PendingFuture<FileLock,A> result)
|
||||
{
|
||||
this.position = position;
|
||||
this.fli = fli;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long overlapped = 0L;
|
||||
boolean pending = false;
|
||||
try {
|
||||
begin();
|
||||
|
||||
// allocate OVERLAPPED structure
|
||||
overlapped = ioCache.add(result);
|
||||
|
||||
// synchronize on result to avoid race with handler thread
|
||||
// when lock is acquired immediately.
|
||||
synchronized (result) {
|
||||
int n = lockFile(handle, position, fli.size(), fli.isShared(),
|
||||
overlapped);
|
||||
if (n == IOStatus.UNAVAILABLE) {
|
||||
// I/O is pending
|
||||
pending = true;
|
||||
return;
|
||||
}
|
||||
// acquired lock immediately
|
||||
result.setResult(fli);
|
||||
}
|
||||
|
||||
} catch (Throwable x) {
|
||||
// lock failed or channel closed
|
||||
removeFromFileLockTable(fli);
|
||||
result.setFailure(toIOException(x));
|
||||
} finally {
|
||||
if (!pending && overlapped != 0L)
|
||||
ioCache.remove(overlapped);
|
||||
end();
|
||||
}
|
||||
|
||||
// invoke completion handler
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completed(int bytesTransferred, boolean canInvokeDirect) {
|
||||
// release waiters and invoke completion handler
|
||||
result.setResult(fli);
|
||||
if (canInvokeDirect) {
|
||||
Invoker.invokeUnchecked(result);
|
||||
} else {
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(int error, IOException x) {
|
||||
// lock not acquired so remove from lock table
|
||||
removeFromFileLockTable(fli);
|
||||
|
||||
// release waiters
|
||||
if (isOpen()) {
|
||||
result.setFailure(x);
|
||||
} else {
|
||||
result.setFailure(new AsynchronousCloseException());
|
||||
}
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
<A> Future<FileLock> implLock(final long position,
|
||||
final long size,
|
||||
final boolean shared,
|
||||
A attachment,
|
||||
final CompletionHandler<FileLock,? super A> handler)
|
||||
{
|
||||
if (shared && !reading)
|
||||
throw new NonReadableChannelException();
|
||||
if (!shared && !writing)
|
||||
throw new NonWritableChannelException();
|
||||
|
||||
// add to lock table
|
||||
FileLockImpl fli = addToFileLockTable(position, size, shared);
|
||||
if (fli == null) {
|
||||
Throwable exc = new ClosedChannelException();
|
||||
if (handler == null)
|
||||
return CompletedFuture.withFailure(exc);
|
||||
Invoker.invoke(this, handler, attachment, null, exc);
|
||||
return null;
|
||||
}
|
||||
|
||||
// create Future and task that will be invoked to acquire lock
|
||||
PendingFuture<FileLock,A> result =
|
||||
new PendingFuture<FileLock,A>(this, handler, attachment);
|
||||
LockTask<A> lockTask = new LockTask<A>(position, fli, result);
|
||||
result.setContext(lockTask);
|
||||
|
||||
// initiate I/O
|
||||
lockTask.run();
|
||||
return result;
|
||||
}
|
||||
|
||||
static final int NO_LOCK = -1; // Failed to lock
|
||||
static final int LOCKED = 0; // Obtained requested lock
|
||||
|
||||
@Override
|
||||
public FileLock tryLock(long position, long size, boolean shared)
|
||||
throws IOException
|
||||
{
|
||||
if (shared && !reading)
|
||||
throw new NonReadableChannelException();
|
||||
if (!shared && !writing)
|
||||
throw new NonWritableChannelException();
|
||||
|
||||
// add to lock table
|
||||
final FileLockImpl fli = addToFileLockTable(position, size, shared);
|
||||
if (fli == null)
|
||||
throw new ClosedChannelException();
|
||||
|
||||
boolean gotLock = false;
|
||||
try {
|
||||
begin();
|
||||
// try to acquire the lock
|
||||
int res = nd.lock(fdObj, false, position, size, shared);
|
||||
if (res == NO_LOCK)
|
||||
return null;
|
||||
gotLock = true;
|
||||
return fli;
|
||||
} finally {
|
||||
if (!gotLock)
|
||||
removeFromFileLockTable(fli);
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implRelease(FileLockImpl fli) throws IOException {
|
||||
nd.release(fdObj, fli.position(), fli.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Task that initiates read operation and handles completion result.
|
||||
*/
|
||||
private class ReadTask<A> implements Runnable, Iocp.ResultHandler {
|
||||
private final ByteBuffer dst;
|
||||
private final int pos, rem; // buffer position/remaining
|
||||
private final long position; // file position
|
||||
private final PendingFuture<Integer,A> result;
|
||||
|
||||
// set to dst if direct; otherwise set to substituted direct buffer
|
||||
private volatile ByteBuffer buf;
|
||||
|
||||
ReadTask(ByteBuffer dst,
|
||||
int pos,
|
||||
int rem,
|
||||
long position,
|
||||
PendingFuture<Integer,A> result)
|
||||
{
|
||||
this.dst = dst;
|
||||
this.pos = pos;
|
||||
this.rem = rem;
|
||||
this.position = position;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
void releaseBufferIfSubstituted() {
|
||||
if (buf != dst)
|
||||
Util.releaseTemporaryDirectBuffer(buf);
|
||||
}
|
||||
|
||||
void updatePosition(int bytesTransferred) {
|
||||
// if the I/O succeeded then adjust buffer position
|
||||
if (bytesTransferred > 0) {
|
||||
if (buf == dst) {
|
||||
try {
|
||||
dst.position(pos + bytesTransferred);
|
||||
} catch (IllegalArgumentException x) {
|
||||
// someone has changed the position; ignore
|
||||
}
|
||||
} else {
|
||||
// had to substitute direct buffer
|
||||
buf.position(bytesTransferred).flip();
|
||||
try {
|
||||
dst.put(buf);
|
||||
} catch (BufferOverflowException x) {
|
||||
// someone has changed the position; ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int n = -1;
|
||||
long overlapped = 0L;
|
||||
long address;
|
||||
|
||||
// Substitute a native buffer if not direct
|
||||
if (dst instanceof DirectBuffer) {
|
||||
buf = dst;
|
||||
address = ((DirectBuffer)dst).address() + pos;
|
||||
} else {
|
||||
buf = Util.getTemporaryDirectBuffer(rem);
|
||||
address = ((DirectBuffer)buf).address();
|
||||
}
|
||||
|
||||
boolean pending = false;
|
||||
try {
|
||||
begin();
|
||||
|
||||
// allocate OVERLAPPED
|
||||
overlapped = ioCache.add(result);
|
||||
|
||||
// initiate read
|
||||
n = readFile(handle, address, rem, position, overlapped);
|
||||
if (n == IOStatus.UNAVAILABLE) {
|
||||
// I/O is pending
|
||||
pending = true;
|
||||
return;
|
||||
} else if (n == IOStatus.EOF) {
|
||||
result.setResult(n);
|
||||
} else {
|
||||
throw new InternalError("Unexpected result: " + n);
|
||||
}
|
||||
|
||||
} catch (Throwable x) {
|
||||
// failed to initiate read
|
||||
result.setFailure(toIOException(x));
|
||||
} finally {
|
||||
if (!pending) {
|
||||
// release resources
|
||||
if (overlapped != 0L)
|
||||
ioCache.remove(overlapped);
|
||||
releaseBufferIfSubstituted();
|
||||
}
|
||||
end();
|
||||
}
|
||||
|
||||
// invoke completion handler
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed when the I/O has completed
|
||||
*/
|
||||
@Override
|
||||
public void completed(int bytesTransferred, boolean canInvokeDirect) {
|
||||
updatePosition(bytesTransferred);
|
||||
|
||||
// return direct buffer to cache if substituted
|
||||
releaseBufferIfSubstituted();
|
||||
|
||||
// release waiters and invoke completion handler
|
||||
result.setResult(bytesTransferred);
|
||||
if (canInvokeDirect) {
|
||||
Invoker.invokeUnchecked(result);
|
||||
} else {
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(int error, IOException x) {
|
||||
// if EOF detected asynchronously then it is reported as error
|
||||
if (error == ERROR_HANDLE_EOF) {
|
||||
completed(-1, false);
|
||||
} else {
|
||||
// return direct buffer to cache if substituted
|
||||
releaseBufferIfSubstituted();
|
||||
|
||||
// release waiters
|
||||
if (isOpen()) {
|
||||
result.setFailure(x);
|
||||
} else {
|
||||
result.setFailure(new AsynchronousCloseException());
|
||||
}
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
<A> Future<Integer> implRead(ByteBuffer dst,
|
||||
long position,
|
||||
A attachment,
|
||||
CompletionHandler<Integer,? super A> handler)
|
||||
{
|
||||
if (!reading)
|
||||
throw new NonReadableChannelException();
|
||||
if (position < 0)
|
||||
throw new IllegalArgumentException("Negative position");
|
||||
if (dst.isReadOnly())
|
||||
throw new IllegalArgumentException("Read-only buffer");
|
||||
|
||||
// check if channel is closed
|
||||
if (!isOpen()) {
|
||||
Throwable exc = new ClosedChannelException();
|
||||
if (handler == null)
|
||||
return CompletedFuture.withFailure(exc);
|
||||
Invoker.invoke(this, handler, attachment, null, exc);
|
||||
return null;
|
||||
}
|
||||
|
||||
int pos = dst.position();
|
||||
int lim = dst.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
// no space remaining
|
||||
if (rem == 0) {
|
||||
if (handler == null)
|
||||
return CompletedFuture.withResult(0);
|
||||
Invoker.invoke(this, handler, attachment, 0, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
// create Future and task that initiates read
|
||||
PendingFuture<Integer,A> result =
|
||||
new PendingFuture<Integer,A>(this, handler, attachment);
|
||||
ReadTask<A> readTask = new ReadTask<A>(dst, pos, rem, position, result);
|
||||
result.setContext(readTask);
|
||||
|
||||
// initiate I/O
|
||||
readTask.run();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task that initiates write operation and handles completion result.
|
||||
*/
|
||||
private class WriteTask<A> implements Runnable, Iocp.ResultHandler {
|
||||
private final ByteBuffer src;
|
||||
private final int pos, rem; // buffer position/remaining
|
||||
private final long position; // file position
|
||||
private final PendingFuture<Integer,A> result;
|
||||
|
||||
// set to src if direct; otherwise set to substituted direct buffer
|
||||
private volatile ByteBuffer buf;
|
||||
|
||||
WriteTask(ByteBuffer src,
|
||||
int pos,
|
||||
int rem,
|
||||
long position,
|
||||
PendingFuture<Integer,A> result)
|
||||
{
|
||||
this.src = src;
|
||||
this.pos = pos;
|
||||
this.rem = rem;
|
||||
this.position = position;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
void releaseBufferIfSubstituted() {
|
||||
if (buf != src)
|
||||
Util.releaseTemporaryDirectBuffer(buf);
|
||||
}
|
||||
|
||||
void updatePosition(int bytesTransferred) {
|
||||
// if the I/O succeeded then adjust buffer position
|
||||
if (bytesTransferred > 0) {
|
||||
try {
|
||||
src.position(pos + bytesTransferred);
|
||||
} catch (IllegalArgumentException x) {
|
||||
// someone has changed the position
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int n = -1;
|
||||
long overlapped = 0L;
|
||||
long address;
|
||||
|
||||
// Substitute a native buffer if not direct
|
||||
if (src instanceof DirectBuffer) {
|
||||
buf = src;
|
||||
address = ((DirectBuffer)src).address() + pos;
|
||||
} else {
|
||||
buf = Util.getTemporaryDirectBuffer(rem);
|
||||
buf.put(src);
|
||||
buf.flip();
|
||||
// temporarily restore position as we don't know how many bytes
|
||||
// will be written
|
||||
src.position(pos);
|
||||
address = ((DirectBuffer)buf).address();
|
||||
}
|
||||
|
||||
try {
|
||||
begin();
|
||||
|
||||
// allocate an OVERLAPPED structure
|
||||
overlapped = ioCache.add(result);
|
||||
|
||||
// initiate the write
|
||||
n = writeFile(handle, address, rem, position, overlapped);
|
||||
if (n == IOStatus.UNAVAILABLE) {
|
||||
// I/O is pending
|
||||
return;
|
||||
} else {
|
||||
throw new InternalError("Unexpected result: " + n);
|
||||
}
|
||||
|
||||
} catch (Throwable x) {
|
||||
// failed to initiate read:
|
||||
result.setFailure(toIOException(x));
|
||||
|
||||
// release resources
|
||||
if (overlapped != 0L)
|
||||
ioCache.remove(overlapped);
|
||||
releaseBufferIfSubstituted();
|
||||
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
|
||||
// invoke completion handler
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed when the I/O has completed
|
||||
*/
|
||||
@Override
|
||||
public void completed(int bytesTransferred, boolean canInvokeDirect) {
|
||||
updatePosition(bytesTransferred);
|
||||
|
||||
// return direct buffer to cache if substituted
|
||||
releaseBufferIfSubstituted();
|
||||
|
||||
// release waiters and invoke completion handler
|
||||
result.setResult(bytesTransferred);
|
||||
if (canInvokeDirect) {
|
||||
Invoker.invokeUnchecked(result);
|
||||
} else {
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(int error, IOException x) {
|
||||
// return direct buffer to cache if substituted
|
||||
releaseBufferIfSubstituted();
|
||||
|
||||
// release waiters and invoker completion handler
|
||||
if (isOpen()) {
|
||||
result.setFailure(x);
|
||||
} else {
|
||||
result.setFailure(new AsynchronousCloseException());
|
||||
}
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
<A> Future<Integer> implWrite(ByteBuffer src,
|
||||
long position,
|
||||
A attachment,
|
||||
CompletionHandler<Integer,? super A> handler)
|
||||
{
|
||||
if (!writing)
|
||||
throw new NonWritableChannelException();
|
||||
if (position < 0)
|
||||
throw new IllegalArgumentException("Negative position");
|
||||
|
||||
// check if channel is closed
|
||||
if (!isOpen()) {
|
||||
Throwable exc = new ClosedChannelException();
|
||||
if (handler == null)
|
||||
return CompletedFuture.withFailure(exc);
|
||||
Invoker.invoke(this, handler, attachment, null, exc);
|
||||
return null;
|
||||
}
|
||||
|
||||
int pos = src.position();
|
||||
int lim = src.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
// nothing to write
|
||||
if (rem == 0) {
|
||||
if (handler == null)
|
||||
return CompletedFuture.withResult(0);
|
||||
Invoker.invoke(this, handler, attachment, 0, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
// create Future and task to initiate write
|
||||
PendingFuture<Integer,A> result =
|
||||
new PendingFuture<Integer,A>(this, handler, attachment);
|
||||
WriteTask<A> writeTask = new WriteTask<A>(src, pos, rem, position, result);
|
||||
result.setContext(writeTask);
|
||||
|
||||
// initiate I/O
|
||||
writeTask.run();
|
||||
return result;
|
||||
}
|
||||
|
||||
// -- Native methods --
|
||||
|
||||
private static native int readFile(long handle, long address, int len,
|
||||
long offset, long overlapped) throws IOException;
|
||||
|
||||
private static native int writeFile(long handle, long address, int len,
|
||||
long offset, long overlapped) throws IOException;
|
||||
|
||||
private static native int lockFile(long handle, long position, long size,
|
||||
boolean shared, long overlapped) throws IOException;
|
||||
|
||||
private static native void close0(long handle);
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue