Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2011-08-18 15:36:45 +0400
committerjfrijters <jfrijters>2011-08-18 15:36:45 +0400
commit05be269edcd34db64d7cfdcdfc85f62854109ba3 (patch)
tree8254d1d700ea8054b30142f25e0b8d4d59535497 /openjdk/sun/nio/ch
parent049db0ce5b02f51e5bfe13aeb5873cf67163a2c4 (diff)
Reduce the number of differences in FileChannelImpl.
Diffstat (limited to 'openjdk/sun/nio/ch')
-rw-r--r--openjdk/sun/nio/ch/FileChannelImpl.java765
-rw-r--r--openjdk/sun/nio/ch/FileDispatcherImpl.java213
-rw-r--r--openjdk/sun/nio/ch/NativeDispatcher.java24
3 files changed, 371 insertions, 631 deletions
diff --git a/openjdk/sun/nio/ch/FileChannelImpl.java b/openjdk/sun/nio/ch/FileChannelImpl.java
index d26fdb3f..033c8792 100644
--- a/openjdk/sun/nio/ch/FileChannelImpl.java
+++ b/openjdk/sun/nio/ch/FileChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -28,83 +28,73 @@ package sun.nio.ch;
import cli.Microsoft.Win32.SafeHandles.SafeFileHandle;
import cli.System.IntPtr;
import cli.System.IO.FileStream;
-import cli.System.Reflection.MethodInfo;
-import cli.System.Reflection.ParameterModifier;
-import cli.System.Reflection.BindingFlags;
import cli.System.Runtime.InteropServices.DllImportAttribute;
import cli.System.Runtime.InteropServices.StructLayoutAttribute;
import cli.System.Runtime.InteropServices.LayoutKind;
-import cli.System.Type;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.*;
-import java.nio.channels.spi.*;
import java.util.ArrayList;
import java.util.List;
-import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.lang.ref.WeakReference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.reflect.Field;
import java.security.AccessController;
-import java.security.PrivilegedAction;
import sun.misc.Cleaner;
import sun.security.action.GetPropertyAction;
-
public class FileChannelImpl
extends FileChannel
{
private static final boolean win32 = ikvm.internal.Util.WINDOWS;
- private static final boolean winNT = cli.System.Environment.get_OSVersion().get_Platform().Value == cli.System.PlatformID.Win32NT;
// Memory allocation size for mapping buffers
private static final long allocationGranularity = 64 * 1024; // HACK we're using a hard coded value here that works on all mainstream platforms
+ // Used to make native read and write calls
+ private final FileDispatcher nd;
+
// File descriptor
- private FileDescriptor fd;
+ private final FileDescriptor fd;
// File access mode (immutable)
- private boolean writable;
- private boolean readable;
- private boolean appending;
+ private final boolean writable;
+ private final boolean readable;
+ private final boolean append;
// Required to prevent finalization of creating stream (immutable)
- private Object parent;
+ private final Object parent;
+
+ // Thread-safe set of IDs of native threads, for signalling
+ private final NativeThreadSet threads = new NativeThreadSet(2);
// Lock for operations involving position and size
- private Object positionLock = new Object();
+ private final Object positionLock = new Object();
private FileChannelImpl(FileDescriptor fd, boolean readable,
- boolean writable, Object parent, boolean append)
+ boolean writable, boolean append, Object parent)
{
this.fd = fd;
this.readable = readable;
this.writable = writable;
+ this.append = append;
this.parent = parent;
- this.appending = append;
+ this.nd = new FileDispatcherImpl(append);
}
- // Invoked by getChannel() methods
- // of java.io.File{Input,Output}Stream and RandomAccessFile
- //
+ // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
public static FileChannel open(FileDescriptor fd,
boolean readable, boolean writable,
Object parent)
{
- return new FileChannelImpl(fd, readable, writable, parent, false);
+ return new FileChannelImpl(fd, readable, writable, false, parent);
}
+ // Used by FileOutputStream.getChannel
public static FileChannel open(FileDescriptor fd,
boolean readable, boolean writable,
- Object parent, boolean append)
+ boolean append, Object parent)
{
- return new FileChannelImpl(fd, readable, writable, parent, append);
+ return new FileChannelImpl(fd, readable, writable, append, parent);
}
private void ensureOpen() throws IOException {
@@ -116,17 +106,21 @@ public class FileChannelImpl
// -- Standard channel operations --
protected void implCloseChannel() throws IOException {
-
- // Invalidate and release any locks that we still hold
+ // Release and invalidate any locks that we still hold
if (fileLockTable != null) {
- fileLockTable.removeAll( new FileLockTable.Releaser() {
- public void release(FileLock fl) throws IOException {
- ((FileLockImpl)fl).invalidate();
- release0(fd, fl.position(), fl.size());
+ for (FileLock fl: fileLockTable.removeAll()) {
+ synchronized (fl) {
+ if (fl.isValid()) {
+ nd.release(fd, fl.position(), fl.size());
+ ((FileLockImpl)fl).invalidate();
+ }
}
- });
+ }
}
+ nd.preClose(fd);
+ threads.signalAndWait();
+
if (parent != null) {
// Close the fd via the parent stream's close method. The parent
@@ -134,17 +128,9 @@ public class FileChannelImpl
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// that method will prevent this method from being reinvoked.
//
- if (parent instanceof FileInputStream)
- ((FileInputStream)parent).close();
- else if (parent instanceof FileOutputStream)
- ((FileOutputStream)parent).close();
- else if (parent instanceof RandomAccessFile)
- ((RandomAccessFile)parent).close();
- else
- assert false;
-
+ ((java.io.Closeable)parent).close();
} else {
- fd.close();
+ nd.close(fd);
}
}
@@ -155,114 +141,119 @@ public class FileChannelImpl
throw new NonReadableChannelException();
synchronized (positionLock) {
int n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return 0;
n = readImpl(dst);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
}
}
- private long read0(ByteBuffer[] dsts) throws IOException {
+ public long read(ByteBuffer[] dsts, int offset, int length)
+ throws IOException
+ {
+ if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
+ throw new IndexOutOfBoundsException();
ensureOpen();
if (!readable)
throw new NonReadableChannelException();
synchronized (positionLock) {
long n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return 0;
- n = readImpl(dsts);
+ n = readImpl(dsts, offset, length);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
}
}
- public long read(ByteBuffer[] dsts, int offset, int length)
- throws IOException
- {
- if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
- throw new IndexOutOfBoundsException();
- // ## Fix IOUtil.write so that we can avoid this array copy
- return read0(Util.subsequence(dsts, offset, length));
- }
-
public int write(ByteBuffer src) throws IOException {
ensureOpen();
if (!writable)
throw new NonWritableChannelException();
synchronized (positionLock) {
int n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return 0;
- if (appending)
+ if (append)
position(size());
n = writeImpl(src);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
}
}
- private long write0(ByteBuffer[] srcs) throws IOException {
+ public long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException
+ {
+ if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
+ throw new IndexOutOfBoundsException();
ensureOpen();
if (!writable)
throw new NonWritableChannelException();
synchronized (positionLock) {
long n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return 0;
- if (appending)
+ if (append)
position(size());
- n = writeImpl(srcs);
+ n = writeImpl(srcs, offset, length);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
}
}
- public long write(ByteBuffer[] srcs, int offset, int length)
- throws IOException
- {
- if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
- throw new IndexOutOfBoundsException();
- // ## Fix IOUtil.write so that we can avoid this array copy
- return write0(Util.subsequence(srcs, offset, length));
- }
-
-
// -- Other operations --
public long position() throws IOException {
ensureOpen();
synchronized (positionLock) {
long p = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return 0;
do {
- p = position0(fd, -1);
+ // in append-mode then position is advanced to end before writing
+ p = (append) ? nd.size(fd) : position0(fd, -1);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(p);
} finally {
+ threads.remove(ti);
end(p > -1);
assert IOStatus.check(p);
}
@@ -275,8 +266,10 @@ public class FileChannelImpl
throw new IllegalArgumentException();
synchronized (positionLock) {
long p = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return null;
do {
@@ -284,6 +277,7 @@ public class FileChannelImpl
} while ((p == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
+ threads.remove(ti);
end(p > -1);
assert IOStatus.check(p);
}
@@ -294,15 +288,18 @@ public class FileChannelImpl
ensureOpen();
synchronized (positionLock) {
long s = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return -1;
do {
- s = size0(fd);
+ s = nd.size(fd);
} while ((s == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(s);
} finally {
+ threads.remove(ti);
end(s > -1);
assert IOStatus.check(s);
}
@@ -320,8 +317,10 @@ public class FileChannelImpl
synchronized (positionLock) {
int rv = -1;
long p = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return null;
@@ -335,7 +334,7 @@ public class FileChannelImpl
// truncate file
do {
- rv = truncate0(fd, size);
+ rv = nd.truncate(fd, size);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
if (!isOpen())
return null;
@@ -348,6 +347,7 @@ public class FileChannelImpl
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
+ threads.remove(ti);
end(rv > -1);
assert IOStatus.check(rv);
}
@@ -357,14 +357,17 @@ public class FileChannelImpl
public void force(boolean metaData) throws IOException {
ensureOpen();
int rv = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return;
do {
- rv = force0(fd, metaData);
+ rv = nd.force(fd, metaData);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
} finally {
+ threads.remove(ti);
end(rv > -1);
assert IOStatus.check(rv);
}
@@ -489,13 +492,16 @@ public class FileChannelImpl
throw new NonReadableChannelException();
ensureOpen();
int n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return -1;
n = readImpl(dst, position);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
@@ -510,13 +516,16 @@ public class FileChannelImpl
throw new NonWritableChannelException();
ensureOpen();
int n = 0;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return -1;
n = writeImpl(src, position);
return IOStatus.normalize(n);
} finally {
+ threads.remove(ti);
end(n > 0);
assert IOStatus.check(n);
}
@@ -528,14 +537,33 @@ public class FileChannelImpl
private static class Unmapper
implements Runnable
{
+ // may be required to close file
+ private static final NativeDispatcher nd = new FileDispatcherImpl();
+
+ // keep track of mapped buffer usage
+ static volatile int count;
+ static volatile long totalSize;
+ static volatile long totalCapacity;
- private long address;
- private long size;
+ private volatile long address;
+ private final long size;
+ private final int cap;
+ private final FileDescriptor fd;
- private Unmapper(long address, long size) {
+ private Unmapper(long address, long size, int cap,
+ FileDescriptor fd)
+ {
assert (address != 0);
this.address = address;
this.size = size;
+ this.cap = cap;
+ this.fd = fd;
+
+ synchronized (Unmapper.class) {
+ count++;
+ totalSize += size;
+ totalCapacity += cap;
+ }
}
public void run() {
@@ -543,8 +571,22 @@ public class FileChannelImpl
return;
unmap0(address, size);
address = 0;
- }
+ // if this mapping has a valid file descriptor then we close it
+ if (fd.valid()) {
+ try {
+ nd.close(fd);
+ } catch (IOException ignore) {
+ // nothing we can do
+ }
+ }
+
+ synchronized (Unmapper.class) {
+ count--;
+ totalSize -= size;
+ totalCapacity -= cap;
+ }
+ }
}
private static void unmap(MappedByteBuffer bb) {
@@ -583,8 +625,10 @@ public class FileChannelImpl
throw new NonReadableChannelException();
long addr = -1;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return null;
if (size() < position + size) { // Extend file size
@@ -594,7 +638,7 @@ public class FileChannelImpl
}
int rv;
do {
- rv = truncate0(fd, position + size);
+ rv = nd.truncate(fd, position + size);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
}
if (size == 0) {
@@ -630,26 +674,65 @@ public class FileChannelImpl
}
}
+ // On Windows, and potentially other platforms, we need an open
+ // file descriptor for some mapping operations.
+ FileDescriptor mfd;
+ try {
+ mfd = nd.duplicateForMapping(fd);
+ } catch (IOException ioe) {
+ unmap0(addr, mapSize);
+ throw ioe;
+ }
+
assert (IOStatus.checkAll(addr));
assert (addr % allocationGranularity == 0);
int isize = (int)size;
- Unmapper um = new Unmapper(addr, size + pagePosition);
- if ((!writable) || (imode == MAP_RO))
- return Util.newMappedByteBufferR(isize, addr + pagePosition, fd, um);
- else
- return Util.newMappedByteBuffer(isize, addr + pagePosition, fd, um);
+ Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+ if ((!writable) || (imode == MAP_RO)) {
+ return Util.newMappedByteBufferR(isize,
+ addr + pagePosition,
+ mfd,
+ um);
+ } else {
+ return Util.newMappedByteBuffer(isize,
+ addr + pagePosition,
+ mfd,
+ um);
+ }
} finally {
+ threads.remove(ti);
end(IOStatus.checkAll(addr));
}
}
+ /**
+ * Invoked by sun.management.ManagementFactoryHelper to create the management
+ * interface for mapped buffers.
+ */
+ public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() {
+ return new sun.misc.JavaNioAccess.BufferPool() {
+ @Override
+ public String getName() {
+ return "mapped";
+ }
+ @Override
+ public long getCount() {
+ return Unmapper.count;
+ }
+ @Override
+ public long getTotalCapacity() {
+ return Unmapper.totalCapacity;
+ }
+ @Override
+ public long getMemoryUsed() {
+ return Unmapper.totalSize;
+ }
+ };
+ }
// -- Locks --
- public static final int NO_LOCK = -1; // Failed to lock
- public static final int LOCKED = 0; // Obtained requested lock
- public static final int RET_EX_LOCK = 1; // Obtained exclusive lock
- public static final int INTERRUPTED = 2; // Request interrupted
+
// keeps track of locks on this file
private volatile FileLockTable fileLockTable;
@@ -679,12 +762,21 @@ public class FileChannelImpl
return isSharedFileLockTable;
}
- private FileLockTable fileLockTable() {
+ private FileLockTable fileLockTable() throws IOException {
if (fileLockTable == null) {
synchronized (this) {
if (fileLockTable == null) {
- fileLockTable = isSharedFileLockTable() ?
- new SharedFileLockTable(this) : new SimpleFileLockTable();
+ if (isSharedFileLockTable()) {
+ int ti = threads.add();
+ try {
+ ensureOpen();
+ fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
+ } finally {
+ threads.remove(ti);
+ }
+ } else {
+ fileLockTable = new SimpleFileLockTable();
+ }
}
}
}
@@ -702,29 +794,33 @@ public class FileChannelImpl
FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable();
flt.add(fli);
- boolean i = true;
+ boolean completed = false;
+ int ti = -1;
try {
begin();
+ ti = threads.add();
if (!isOpen())
return null;
- int result = lock0(fd, true, position, size, shared);
- if (result == RET_EX_LOCK) {
- assert shared;
- FileLockImpl fli2 = new FileLockImpl(this, position, size,
- false);
- flt.replace(fli, fli2);
- return fli2;
- }
- if (result == INTERRUPTED || result == NO_LOCK) {
- flt.remove(fli);
- i = false;
+ int n;
+ do {
+ n = nd.lock(fd, true, position, size, shared);
+ } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
+ if (isOpen()) {
+ if (n == FileDispatcher.RET_EX_LOCK) {
+ assert shared;
+ FileLockImpl fli2 = new FileLockImpl(this, position, size,
+ false);
+ flt.replace(fli, fli2);
+ fli = fli2;
+ }
+ completed = true;
}
- } catch (IOException e) {
- flt.remove(fli);
- throw e;
} finally {
+ if (!completed)
+ flt.remove(fli);
+ threads.remove(ti);
try {
- end(i);
+ end(completed);
} catch (ClosedByInterruptException e) {
throw new FileLockInterruptionException();
}
@@ -743,79 +839,55 @@ public class FileChannelImpl
FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable();
flt.add(fli);
- int result = lock0(fd, false, position, size, shared);
- if (result == NO_LOCK) {
- flt.remove(fli);
- return null;
- }
- if (result == RET_EX_LOCK) {
- assert shared;
- FileLockImpl fli2 = new FileLockImpl(this, position, size,
- false);
- flt.replace(fli, fli2);
- return fli2;
+ int result;
+
+ int ti = threads.add();
+ try {
+ try {
+ ensureOpen();
+ result = nd.lock(fd, false, position, size, shared);
+ } catch (IOException e) {
+ flt.remove(fli);
+ throw e;
+ }
+ if (result == FileDispatcher.NO_LOCK) {
+ flt.remove(fli);
+ return null;
+ }
+ if (result == FileDispatcher.RET_EX_LOCK) {
+ assert shared;
+ FileLockImpl fli2 = new FileLockImpl(this, position, size,
+ false);
+ flt.replace(fli, fli2);
+ return fli2;
+ }
+ return fli;
+ } finally {
+ threads.remove(ti);
}
- return fli;
}
void release(FileLockImpl fli) throws IOException {
- ensureOpen();
- release0(fd, fli.position(), fli.size());
+ int ti = threads.add();
+ try {
+ ensureOpen();
+ nd.release(fd, fli.position(), fli.size());
+ } finally {
+ threads.remove(ti);
+ }
assert fileLockTable != null;
fileLockTable.remove(fli);
}
-
- // -- File lock support --
-
- /**
- * A table of FileLocks.
- */
- private interface FileLockTable {
- /**
- * Adds a file lock to the table.
- *
- * @throws OverlappingFileLockException if the file lock overlaps
- * with an existing file lock in the table
- */
- void add(FileLock fl) throws OverlappingFileLockException;
-
- /**
- * Remove an existing file lock from the table.
- */
- void remove(FileLock fl);
-
- /**
- * An implementation of this interface releases a given file lock.
- * Used with removeAll.
- */
- interface Releaser {
- void release(FileLock fl) throws IOException;
- }
-
- /**
- * Removes all file locks from the table.
- * <p>
- * The Releaser#release method is invoked for each file lock before
- * it is removed.
- *
- * @throws IOException if the release method throws IOException
- */
- void removeAll(Releaser r) throws IOException;
-
- /**
- * Replaces an existing file lock in the table.
- */
- void replace(FileLock fl1, FileLock fl2);
- }
+ // -- File lock support --
/**
* A simple file lock table that maintains a list of FileLocks obtained by a
* FileChannel. Use to get 1.4/5.0 behaviour.
*/
- private static class SimpleFileLockTable implements FileLockTable {
+ private static class SimpleFileLockTable extends FileLockTable {
// synchronize on list for access
- private List<FileLock> lockList = new ArrayList<FileLock>(2);
+ private final List<FileLock> lockList = new ArrayList<FileLock>(2);
public SimpleFileLockTable() {
}
@@ -844,14 +916,11 @@ public class FileChannelImpl
}
}
- public void removeAll(Releaser releaser) throws IOException {
+ public List<FileLock> removeAll() {
synchronized(lockList) {
- Iterator<FileLock> i = lockList.iterator();
- while (i.hasNext()) {
- FileLock fl = i.next();
- releaser.release(fl);
- i.remove();
- }
+ List<FileLock> result = new ArrayList<FileLock>(lockList);
+ lockList.clear();
+ return result;
}
}
@@ -863,197 +932,6 @@ public class FileChannelImpl
}
}
- /**
- * A weak reference to a FileLock.
- * <p>
- * SharedFileLockTable uses a list of file lock references to avoid keeping the
- * FileLock (and FileChannel) alive.
- */
- private static class FileLockReference extends WeakReference<FileLock> {
- private FileKey fileKey;
-
- FileLockReference(FileLock referent,
- ReferenceQueue queue,
- FileKey key) {
- super(referent, queue);
- this.fileKey = key;
- }
-
- private FileKey fileKey() {
- return fileKey;
- }
- }
-
- /**
- * A file lock table that is over a system-wide map of all file locks.
- */
- private static class SharedFileLockTable implements FileLockTable {
- // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey.
- // The map value is a list of file locks represented by FileLockReferences.
- // All access to the list must be synchronized on the list.
- private static ConcurrentHashMap<FileKey, ArrayList<FileLockReference>> lockMap =
- new ConcurrentHashMap<FileKey, ArrayList<FileLockReference>>();
-
- // reference queue for cleared refs
- private static ReferenceQueue queue = new ReferenceQueue();
-
- // the enclosing file channel
- private FileChannelImpl fci;
-
- // File key for the file that this channel is connected to
- private FileKey fileKey;
-
- public SharedFileLockTable(FileChannelImpl fci) {
- this.fci = fci;
- this.fileKey = FileKey.create(fci.fd);
- }
-
- public void add(FileLock fl) throws OverlappingFileLockException {
- ArrayList<FileLockReference> list = lockMap.get(fileKey);
-
- for (;;) {
-
- // The key isn't in the map so we try to create it atomically
- if (list == null) {
- list = new ArrayList<FileLockReference>(2);
- ArrayList<FileLockReference> prev;
- synchronized (list) {
- prev = lockMap.putIfAbsent(fileKey, list);
- if (prev == null) {
- // we successfully created the key so we add the file lock
- list.add(new FileLockReference(fl, queue, fileKey));
- break;
- }
- }
- // someone else got there first
- list = prev;
- }
-
- // There is already a key. It is possible that some other thread
- // is removing it so we re-fetch the value from the map. If it
- // hasn't changed then we check the list for overlapping locks
- // and add the new lock to the list.
- synchronized (list) {
- ArrayList<FileLockReference> current = lockMap.get(fileKey);
- if (list == current) {
- checkList(list, fl.position(), fl.size());
- list.add(new FileLockReference(fl, queue, fileKey));
- break;
- }
- list = current;
- }
-
- }
-
- // process any stale entries pending in the reference queue
- removeStaleEntries();
- }
-
- private void removeKeyIfEmpty(FileKey fk, ArrayList<FileLockReference> list) {
- assert Thread.holdsLock(list);
- assert lockMap.get(fk) == list;
- if (list.isEmpty()) {
- lockMap.remove(fk);
- }
- }
-
- public void remove(FileLock fl) {
- assert fl != null;
-
- // the lock must exist so the list of locks must be present
- ArrayList<FileLockReference> list = lockMap.get(fileKey);
- assert list != null;
-
- synchronized (list) {
- int index = 0;
- while (index < list.size()) {
- FileLockReference ref = list.get(index);
- FileLock lock = ref.get();
- if (lock == fl) {
- assert (lock != null) && (lock.channel() == fci);
- ref.clear();
- list.remove(index);
- break;
- }
- index++;
- }
- }
- }
-
- public void removeAll(Releaser releaser) throws IOException {
- ArrayList<FileLockReference> list = lockMap.get(fileKey);
- if (list != null) {
- synchronized (list) {
- int index = 0;
- while (index < list.size()) {
- FileLockReference ref = list.get(index);
- FileLock lock = ref.get();
-
- // remove locks obtained by this channel
- if (lock != null && lock.channel() == fci) {
- // invoke the releaser to invalidate/release the lock
- releaser.release(lock);
-
- // remove the lock from the list
- ref.clear();
- list.remove(index);
- } else {
- index++;
- }
- }
-
- // once the lock list is empty we remove it from the map
- removeKeyIfEmpty(fileKey, list);
- }
- }
- }
-
- public void replace(FileLock fromLock, FileLock toLock) {
- // the lock must exist so there must be a list
- ArrayList<FileLockReference> list = lockMap.get(fileKey);
- assert list != null;
-
- synchronized (list) {
- for (int index=0; index<list.size(); index++) {
- FileLockReference ref = list.get(index);
- FileLock lock = ref.get();
- if (lock == fromLock) {
- ref.clear();
- list.set(index, new FileLockReference(toLock, queue, fileKey));
- break;
- }
- }
- }
- }
-
- // Check for overlapping file locks
- private void checkList(List<FileLockReference> list, long position, long size)
- throws OverlappingFileLockException
- {
- assert Thread.holdsLock(list);
- for (FileLockReference ref: list) {
- FileLock fl = ref.get();
- if (fl != null && fl.overlaps(position, size))
- throw new OverlappingFileLockException();
- }
- }
-
- // Process the reference queue
- private void removeStaleEntries() {
- FileLockReference ref;
- while ((ref = (FileLockReference)queue.poll()) != null) {
- FileKey fk = ref.fileKey();
- ArrayList<FileLockReference> list = lockMap.get(fk);
- if (list != null) {
- synchronized (list) {
- list.remove(ref);
- removeKeyIfEmpty(fk, list);
- }
- }
- }
- }
- }
-
// -- Native methods --
private int readImpl(ByteBuffer dst) throws IOException
@@ -1097,12 +975,12 @@ public class FileChannelImpl
}
}
- private long readImpl(ByteBuffer[] dsts) throws IOException
+ private long readImpl(ByteBuffer[] dsts, int offset, int length) throws IOException
{
long totalRead = 0;
try
{
- for (int i = 0; i < dsts.length; i++)
+ for (int i = offset; i < offset + length; i++)
{
int size = dsts[i].remaining();
if (size > 0)
@@ -1168,12 +1046,12 @@ public class FileChannelImpl
}
}
- private long writeImpl(ByteBuffer[] srcs) throws IOException
+ private long writeImpl(ByteBuffer[] srcs, int offset, int length) throws IOException
{
long totalWritten = 0;
try
{
- for (int i = 0; i < srcs.length; i++)
+ for (int i = offset; i < offset + length; i++)
{
int size = srcs[i].remaining();
if (size > 0)
@@ -1197,125 +1075,6 @@ public class FileChannelImpl
return totalWritten;
}
- @StructLayoutAttribute.Annotation(LayoutKind.__Enum.Sequential)
- private static final class OVERLAPPED extends cli.System.Object
- {
- IntPtr Internal;
- IntPtr InternalHigh;
- int OffsetLow;
- int OffsetHigh;
- IntPtr hEvent;
- }
-
- // Grabs a file lock
- @cli.System.Security.SecuritySafeCriticalAttribute.Annotation
- static int lock0(FileDescriptor fd, boolean blocking, long pos, long size, boolean shared) throws IOException
- {
- FileStream fs = (FileStream)fd.getStream();
- if (winNT)
- {
- int LOCKFILE_FAIL_IMMEDIATELY = 1;
- int LOCKFILE_EXCLUSIVE_LOCK = 2;
- int ERROR_LOCK_VIOLATION = 33;
- int flags = 0;
- OVERLAPPED o = new OVERLAPPED();
- o.OffsetLow = (int)pos;
- o.OffsetHigh = (int)(pos >> 32);
- if (!blocking)
- {
- flags |= LOCKFILE_FAIL_IMMEDIATELY;
- }
- if (!shared)
- {
- flags |= LOCKFILE_EXCLUSIVE_LOCK;
- }
- int result = LockFileEx(fs.get_SafeFileHandle(), flags, 0, (int)size, (int)(size >> 32), o);
- if (result == 0)
- {
- int error = cli.System.Runtime.InteropServices.Marshal.GetLastWin32Error();
- if (!blocking && error == ERROR_LOCK_VIOLATION)
- {
- return NO_LOCK;
- }
- throw new IOException("Lock failed");
- }
- return LOCKED;
- }
- else
- {
- try
- {
- if (false) throw new cli.System.ArgumentOutOfRangeException();
- for (;;)
- {
- try
- {
- if (false) throw new cli.System.IO.IOException();
- if (false) throw new cli.System.ObjectDisposedException("");
- fs.Lock(pos, size);
- return shared ? RET_EX_LOCK : LOCKED;
- }
- catch (cli.System.IO.IOException x)
- {
- if (!blocking)
- {
- return NO_LOCK;
- }
- cli.System.Threading.Thread.Sleep(100);
- }
- catch (cli.System.ObjectDisposedException x)
- {
- throw new IOException(x.getMessage());
- }
- }
- }
- catch (cli.System.ArgumentOutOfRangeException x)
- {
- throw new IOException(x.getMessage());
- }
- }
- }
-
- // Releases a file lock
- @cli.System.Security.SecuritySafeCriticalAttribute.Annotation
- static void release0(FileDescriptor fd, long pos, long size) throws IOException
- {
- FileStream fs = (FileStream)fd.getStream();
- if (winNT)
- {
- OVERLAPPED o = new OVERLAPPED();
- o.OffsetLow = (int)pos;
- o.OffsetHigh = (int)(pos >> 32);
- int result = UnlockFileEx(fs.get_SafeFileHandle(), 0, (int)size, (int)(size >> 32), o);
- if (result == 0)
- {
- throw new IOException("Release failed");
- }
- }
- else
- {
- try
- {
- if (false) throw new cli.System.ArgumentOutOfRangeException();
- if (false) throw new cli.System.IO.IOException();
- if (false) throw new cli.System.ObjectDisposedException("");
- fs.Unlock(pos, size);
- }
- catch (cli.System.ArgumentOutOfRangeException x)
- {
- throw new IOException(x.getMessage());
- }
- catch (cli.System.IO.IOException x)
- {
- throw new IOException(x.getMessage());
- }
- catch (cli.System.ObjectDisposedException x)
- {
- throw new IOException(x.getMessage());
- }
- }
- }
-
// Creates a new mapping
private long map0(int prot, long position, long length) throws IOException
{
@@ -1414,12 +1173,6 @@ public class FileChannelImpl
@DllImportAttribute.Annotation("kernel32")
private static native int UnmapViewOfFile(IntPtr lpBaseAddress);
- @DllImportAttribute.Annotation(value="kernel32", SetLastError=true)
- static native int LockFileEx(SafeFileHandle hFile, int dwFlags, int dwReserved, int nNumberOfBytesToLockLow, int nNumberOfBytesToLockHigh, OVERLAPPED lpOverlapped);
-
- @DllImportAttribute.Annotation("kernel32")
- static native int UnlockFileEx(SafeFileHandle hFile, int dwReserved, int nNumberOfBytesToUnlockLow, int nNumberOfBytesToUnlockHigh, OVERLAPPED lpOverlapped);
-
@DllImportAttribute.Annotation("ikvm-native")
private static native int ikvm_munmap(IntPtr address, int size);
@@ -1438,20 +1191,6 @@ public class FileChannelImpl
return 0;
}
- // Forces output to device
- private static int force0(FileDescriptor fd, boolean metaData) throws IOException
- {
- fd.sync();
- return 0;
- }
-
- // Truncates a file
- private static int truncate0(FileDescriptor fd, long size) throws IOException
- {
- fd.setLength(size);
- return 0;
- }
-
// Sets or reports this file's position
// If offset is -1, the current position is returned
// otherwise the position is set to offset
@@ -1464,10 +1203,4 @@ public class FileChannelImpl
fd.seek(offset);
return offset;
}
-
- // Reports this file's size
- private static long size0(FileDescriptor fd) throws IOException
- {
- return fd.length();
- }
}
diff --git a/openjdk/sun/nio/ch/FileDispatcherImpl.java b/openjdk/sun/nio/ch/FileDispatcherImpl.java
index 276c6199..20842d72 100644
--- a/openjdk/sun/nio/ch/FileDispatcherImpl.java
+++ b/openjdk/sun/nio/ch/FileDispatcherImpl.java
@@ -26,15 +26,17 @@
package sun.nio.ch;
import java.io.*;
-import sun.misc.SharedSecrets;
-import sun.misc.JavaIOFileDescriptorAccess;
+import cli.Microsoft.Win32.SafeHandles.SafeFileHandle;
+import cli.System.IntPtr;
+import cli.System.IO.FileStream;
+import cli.System.Runtime.InteropServices.DllImportAttribute;
+import cli.System.Runtime.InteropServices.StructLayoutAttribute;
+import cli.System.Runtime.InteropServices.LayoutKind;
+import static ikvm.internal.Util.WINDOWS;
+import ikvm.internal.NotYetImplementedError;
class FileDispatcherImpl extends FileDispatcher
{
- static {
- Util.load();
- }
-
/**
* Indicates if the dispatcher should first advance the file position
* to the end of file when writing.
@@ -49,113 +51,142 @@ class FileDispatcherImpl extends FileDispatcher
this(false);
}
- int read(FileDescriptor fd, long address, int len)
- throws IOException
- {
- return read0(fd, address, len);
- }
-
- int pread(FileDescriptor fd, long address, int len,
- long position, Object lock) throws IOException
- {
- synchronized(lock) {
- return pread0(fd, address, len, position);
- }
- }
-
- long readv(FileDescriptor fd, long address, int len) throws IOException {
- return readv0(fd, address, len);
- }
-
- int write(FileDescriptor fd, long address, int len) throws IOException {
- return write0(fd, address, len, append);
- }
-
- int pwrite(FileDescriptor fd, long address, int len,
- long position, Object lock) throws IOException
- {
- synchronized(lock) {
- return pwrite0(fd, address, len, position);
- }
- }
-
- long writev(FileDescriptor fd, long address, int len) throws IOException {
- return writev0(fd, address, len, append);
- }
-
int force(FileDescriptor fd, boolean metaData) throws IOException {
- return force0(fd, metaData);
+ fd.sync();
+ return 0;
}
int truncate(FileDescriptor fd, long size) throws IOException {
- return truncate0(fd, size);
+ fd.setLength(size);
+ return 0;
}
long size(FileDescriptor fd) throws IOException {
- return size0(fd);
+ return fd.length();
}
+ @StructLayoutAttribute.Annotation(LayoutKind.__Enum.Sequential)
+ private static final class OVERLAPPED extends cli.System.Object
+ {
+ IntPtr Internal;
+ IntPtr InternalHigh;
+ int OffsetLow;
+ int OffsetHigh;
+ IntPtr hEvent;
+ }
+
+ @cli.System.Security.SecuritySafeCriticalAttribute.Annotation
int lock(FileDescriptor fd, boolean blocking, long pos, long size,
boolean shared) throws IOException
{
- return lock0(fd, blocking, pos, size, shared);
+ FileStream fs = (FileStream)fd.getStream();
+ if (WINDOWS)
+ {
+ int LOCKFILE_FAIL_IMMEDIATELY = 1;
+ int LOCKFILE_EXCLUSIVE_LOCK = 2;
+ int ERROR_LOCK_VIOLATION = 33;
+ int flags = 0;
+ OVERLAPPED o = new OVERLAPPED();
+ o.OffsetLow = (int)pos;
+ o.OffsetHigh = (int)(pos >> 32);
+ if (!blocking)
+ {
+ flags |= LOCKFILE_FAIL_IMMEDIATELY;
+ }
+ if (!shared)
+ {
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ int result = LockFileEx(fs.get_SafeFileHandle(), flags, 0, (int)size, (int)(size >> 32), o);
+ if (result == 0)
+ {
+ int error = cli.System.Runtime.InteropServices.Marshal.GetLastWin32Error();
+ if (!blocking && error == ERROR_LOCK_VIOLATION)
+ {
+ return NO_LOCK;
+ }
+ throw new IOException("Lock failed");
+ }
+ return LOCKED;
+ }
+ else
+ {
+ try
+ {
+ if (false) throw new cli.System.ArgumentOutOfRangeException();
+ for (;;)
+ {
+ try
+ {
+ if (false) throw new cli.System.IO.IOException();
+ if (false) throw new cli.System.ObjectDisposedException("");
+ fs.Lock(pos, size);
+ return shared ? RET_EX_LOCK : LOCKED;
+ }
+ catch (cli.System.IO.IOException x)
+ {
+ if (!blocking)
+ {
+ return NO_LOCK;
+ }
+ cli.System.Threading.Thread.Sleep(100);
+ }
+ catch (cli.System.ObjectDisposedException x)
+ {
+ throw new IOException(x.getMessage());
+ }
+ }
+ }
+ catch (cli.System.ArgumentOutOfRangeException x)
+ {
+ throw new IOException(x.getMessage());
+ }
+ }
}
+ @cli.System.Security.SecuritySafeCriticalAttribute.Annotation
void release(FileDescriptor fd, long pos, long size) throws IOException {
- release0(fd, pos, size);
+ FileStream fs = (FileStream)fd.getStream();
+ if (WINDOWS)
+ {
+ OVERLAPPED o = new OVERLAPPED();
+ o.OffsetLow = (int)pos;
+ o.OffsetHigh = (int)(pos >> 32);
+ int result = UnlockFileEx(fs.get_SafeFileHandle(), 0, (int)size, (int)(size >> 32), o);
+ if (result == 0)
+ {
+ throw new IOException("Release failed");
+ }
+ }
+ else
+ {
+ try
+ {
+ if (false) throw new cli.System.ArgumentOutOfRangeException();
+ if (false) throw new cli.System.IO.IOException();
+ if (false) throw new cli.System.ObjectDisposedException("");
+ fs.Unlock(pos, size);
+ }
+ catch (cli.System.ArgumentOutOfRangeException
+ | cli.System.IO.IOException
+ | cli.System.ObjectDisposedException x)
+ {
+ throw new IOException(x.getMessage());
+ }
+ }
}
void close(FileDescriptor fd) throws IOException {
- close0(fd);
+ fd.close();
}
FileDescriptor duplicateForMapping(FileDescriptor fd) throws IOException {
- // on Windows we need to keep a handle to the file
- JavaIOFileDescriptorAccess fdAccess =
- SharedSecrets.getJavaIOFileDescriptorAccess();
- FileDescriptor result = new FileDescriptor();
- long handle = duplicateHandle(fdAccess.getHandle(fd));
- fdAccess.setHandle(result, handle);
- return result;
+ return fd;
}
- //-- Native methods
-
- static native int read0(FileDescriptor fd, long address, int len)
- throws IOException;
-
- static native int pread0(FileDescriptor fd, long address, int len,
- long position) throws IOException;
-
- static native long readv0(FileDescriptor fd, long address, int len)
- throws IOException;
-
- static native int write0(FileDescriptor fd, long address, int len, boolean append)
- throws IOException;
-
- static native int pwrite0(FileDescriptor fd, long address, int len,
- long position) throws IOException;
-
- static native long writev0(FileDescriptor fd, long address, int len, boolean append)
- throws IOException;
-
- static native int force0(FileDescriptor fd, boolean metaData)
- throws IOException;
-
- static native int truncate0(FileDescriptor fd, long size)
- throws IOException;
-
- static native long size0(FileDescriptor fd) throws IOException;
-
- static native int lock0(FileDescriptor fd, boolean blocking, long pos,
- long size, boolean shared) throws IOException;
-
- static native void release0(FileDescriptor fd, long pos, long size)
- throws IOException;
-
- static native void close0(FileDescriptor fd) throws IOException;
-
- static native void closeByHandle(long fd) throws IOException;
+ @DllImportAttribute.Annotation(value="kernel32", SetLastError=true)
+ private static native int LockFileEx(SafeFileHandle hFile, int dwFlags, int dwReserved, int nNumberOfBytesToLockLow, int nNumberOfBytesToLockHigh, OVERLAPPED lpOverlapped);
- static native long duplicateHandle(long fd) throws IOException;
+ @DllImportAttribute.Annotation("kernel32")
+ private static native int UnlockFileEx(SafeFileHandle hFile, int dwReserved, int nNumberOfBytesToUnlockLow, int nNumberOfBytesToUnlockHigh, OVERLAPPED lpOverlapped);
}
diff --git a/openjdk/sun/nio/ch/NativeDispatcher.java b/openjdk/sun/nio/ch/NativeDispatcher.java
index 4752ce8e..823a101f 100644
--- a/openjdk/sun/nio/ch/NativeDispatcher.java
+++ b/openjdk/sun/nio/ch/NativeDispatcher.java
@@ -35,30 +35,6 @@ import java.io.*;
abstract class NativeDispatcher
{
- abstract int read(FileDescriptor fd, long address, int len)
- throws IOException;
-
- int pread(FileDescriptor fd, long address, int len,
- long position, Object lock) throws IOException
- {
- throw new IOException("Operation Unsupported");
- }
-
- abstract long readv(FileDescriptor fd, long address, int len)
- throws IOException;
-
- abstract int write(FileDescriptor fd, long address, int len)
- throws IOException;
-
- int pwrite(FileDescriptor fd, long address, int len,
- long position, Object lock) throws IOException
- {
- throw new IOException("Operation Unsupported");
- }
-
- abstract long writev(FileDescriptor fd, long address, int len)
- throws IOException;
-
abstract void close(FileDescriptor fd) throws IOException;
// Prepare the given fd for closing by duping it to a known internal fd