--- a/make/java/nio/Makefile Tue Jan 20 15:25:51 2009 +0000
+++ b/make/java/nio/Makefile Wed Jan 21 15:09:31 2009 +0000
@@ -185,6 +185,7 @@ ifeq ($(PLATFORM), linux)
ifeq ($(PLATFORM), linux)
FILES_java += \
sun/nio/ch/AbstractPollSelectorImpl.java \
+ sun/nio/ch/EPoll.java \
sun/nio/ch/EPollArrayWrapper.java \
sun/nio/ch/EPollPort.java \
sun/nio/ch/EPollSelectorProvider.java \
@@ -227,6 +228,7 @@ FILES_java += \
sun/nio/fs/UnixUserPrincipals.java
FILES_c += \
+ EPoll.c \
EPollArrayWrapper.c \
EPollPort.c \
InheritedChannel.c \
@@ -242,6 +244,7 @@ FILES_c += \
UnixNativeDispatcher.c
FILES_export += \
+ sun/nio/ch/EPoll.java \
sun/nio/ch/EPollArrayWrapper.java \
sun/nio/ch/EPollPort.java \
sun/nio/ch/InheritedChannel.java \
--- a/make/java/nio/mapfile-linux Tue Jan 20 15:25:51 2009 +0000
+++ b/make/java/nio/mapfile-linux Wed Jan 21 15:09:31 2009 +0000
@@ -44,11 +44,14 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_EPollArrayWrapper_interrupt;
Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
- Java_sun_nio_ch_EPollPort_init;
+ Java_sun_nio_ch_EPoll_init;
+ Java_sun_nio_ch_EPoll_eventSize;
+ Java_sun_nio_ch_EPoll_eventsOffset;
+ Java_sun_nio_ch_EPoll_dataOffset;
+ Java_sun_nio_ch_EPoll_epollCreate;
+ Java_sun_nio_ch_EPoll_epollCtl;
+ Java_sun_nio_ch_EPoll_epollWait;
Java_sun_nio_ch_EPollPort_close0;
- Java_sun_nio_ch_EPollPort_epollCreate;
- Java_sun_nio_ch_EPollPort_epollCtl;
- Java_sun_nio_ch_EPollPort_epollWait;
Java_sun_nio_ch_EPollPort_drain1;
Java_sun_nio_ch_EPollPort_interrupt;
Java_sun_nio_ch_EPollPort_socketpair;
@@ -124,6 +127,8 @@ SUNWprivate_1.1 {
Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs;
Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs;
Java_sun_nio_fs_LinuxWatchService_init;
+ Java_sun_nio_fs_LinuxWatchService_eventSize;
+ Java_sun_nio_fs_LinuxWatchService_eventOffsets;
Java_sun_nio_fs_LinuxWatchService_inotifyInit;
Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch;
Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch;
--- a/src/share/classes/java/nio/file/DirectoryStream.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/DirectoryStream.java Wed Jan 21 15:09:31 2009 +0000
@@ -114,7 +114,7 @@ public interface DirectoryStream<T>
*/
public static interface Filter<T> {
/**
- * Decides if the given directory entry should be accept or filtered.
+ * Decides if the given directory entry should be accepted or filtered.
*
* @param entry
* The directory entry to be tested
--- a/src/share/classes/java/nio/file/FileRef.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/FileRef.java Wed Jan 21 15:09:31 2009 +0000
@@ -166,7 +166,9 @@ public interface FileRef {
* @throws SecurityException
* In the case of the default provider, and a security manager is
* installed, the {@link SecurityManager#checkRead(String) checkRead}
- * method is invoked to check read access to the file.
+ * method is invoked to check read access to the file, and in
+ * addition it checks {@link RuntimePermission}<tt>
+ * ("getFileStoreAttributes")</tt>
*/
FileStore getFileStore() throws IOException;
--- a/src/share/classes/java/nio/file/FileSystem.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/FileSystem.java Wed Jan 21 15:09:31 2009 +0000
@@ -200,13 +200,15 @@ public abstract class FileSystem
* Java virtual machine. When an I/O error occurs, perhaps because a file
* store is not accessible, then it is not returned by the iterator.
*
- * <p> When a security manager is installed, it is invoked to check access
- * to each file store. If denied, the file store is not returned by the
- * iterator. In the case of the default provider, the {@link
- * SecurityManager#checkRead(String)} method is invoked to check read access
- * to the file store's <em>top-most</em> directory. It is system dependent
- * if the permission checks are done when the iterator is obtained or during
- * iteration.
+ * <p> In the case of the default provider, and a security manager is
+ * installed, the security manager is invoked to check {@link
+ * RuntimePermission}<tt>("getFileStoreAttributes")</tt>. If denied, then
+ * no file stores are returned by the iterator. In addition, the security
+ * manager's {@link SecurityManager#checkRead(String)} method is invoked to
+ * check read access to the file store's <em>top-most</em> directory. If
+ * denied, the file store is not returned by the iterator. It is system
+ * dependent if the permission checks are done when the iterator is obtained
+ * or during iteration.
*
* <p> <b>Usage Example:</b>
* Suppose we want to print the space usage for all file stores:
--- a/src/share/classes/java/nio/file/StandardOpenOption.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/StandardOpenOption.java Wed Jan 21 15:09:31 2009 +0000
@@ -77,7 +77,7 @@ public enum StandardOpenOption implement
/**
* Delete on close. When this option is present then the implementation
- * makes a <em>best effort</em> attempt to delete the file when the closed
+ * makes a <em>best effort</em> attempt to delete the file when closed
* by the appropriate {@code close} method. If the {@code close} method is
* not invoked then a <em>best effort</em> attempt is made to delete the
* file when the Java virtual machine terminates (either normally, as
--- a/src/share/classes/java/nio/file/attribute/Attributes.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/attribute/Attributes.java Wed Jan 21 15:09:31 2009 +0000
@@ -688,13 +688,6 @@ public final class Attributes {
* If the file store space attribute view is not supported
* @throws IOException
* If an I/O error occurs
- * @throws SecurityException
- * In the case of the default provider, and a security manager is
- * installed, its {@link SecurityManager#checkRead(String) checkRead}
- * method is invoked to check read access to the file used to {@link
- * FileRef#getFileStore obtain} access to the file
- * store, and in addition it checks {@link RuntimePermission}<tt>
- * ("getFileStoreAttributes")</tt>
*
* @see FileStoreSpaceAttributeView#readAttributes()
*/
--- a/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java Wed Jan 21 15:09:31 2009 +0000
@@ -25,8 +25,6 @@
package java.nio.file.attribute;
-import java.nio.file.*;
-import java.util.Map;
import java.io.IOException;
/**
@@ -82,13 +80,6 @@ public interface FileStoreSpaceAttribute
*
* @throws IOException
* If an I/O error occurs
- * @throws SecurityException
- * In the case of the default provider, and a security manager is
- * installed, its {@link SecurityManager#checkRead(String) checkRead}
- * method is invoked to check read access to the file used to {@link
- * FileRef#getFileStore obtain} access to the file
- * system, and in addition it checks {@link RuntimePermission}<tt>
- * ("getFileStoreAttributes")</tt>
*/
FileStoreSpaceAttributes readAttributes() throws IOException;
}
--- a/src/share/classes/java/nio/file/spi/AbstractPath.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/java/nio/file/spi/AbstractPath.java Wed Jan 21 15:09:31 2009 +0000
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -26,6 +26,7 @@ package java.nio.file.spi;
package java.nio.file.spi;
import java.nio.file.*;
+import static java.nio.file.StandardOpenOption.*;
import java.nio.file.attribute.*;
import java.nio.channels.*;
import java.nio.ByteBuffer;
@@ -84,8 +85,7 @@ public abstract class AbstractPath exten
public Path createFile(FileAttribute<?>... attrs)
throws IOException
{
- EnumSet<StandardOpenOption> options =
- EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
+ EnumSet<StandardOpenOption> options = EnumSet.of(CREATE_NEW, WRITE);
SeekableByteChannel sbc = newByteChannel(options, attrs);
try {
sbc.close();
@@ -131,7 +131,23 @@ public abstract class AbstractPath exten
*/
@Override
public InputStream newInputStream() throws IOException {
- return Channels.newInputStream(newByteChannel(StandardOpenOption.READ));
+ return Channels.newInputStream(newByteChannel());
+ }
+
+ // opts must be modifiable
+ private OutputStream implNewOutputStream(Set<OpenOption> opts,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ if (opts.isEmpty()) {
+ opts.add(CREATE);
+ opts.add(TRUNCATE_EXISTING);
+ } else {
+ if (opts.contains(READ))
+ throw new IllegalArgumentException("READ not allowed");
+ }
+ opts.add(WRITE);
+ return Channels.newOutputStream(newByteChannel(opts, attrs));
}
/**
@@ -149,21 +165,14 @@ public abstract class AbstractPath exten
*/
@Override
public OutputStream newOutputStream(OpenOption... options) throws IOException {
-
int len = options.length;
Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
- if (len == 0) {
- opts.add(StandardOpenOption.CREATE);
- opts.add(StandardOpenOption.TRUNCATE_EXISTING);
- } else {
+ if (len > 0) {
for (OpenOption opt: options) {
- if (opt == StandardOpenOption.READ)
- throw new IllegalArgumentException("READ not allowed");
opts.add(opt);
}
}
- opts.add(StandardOpenOption.WRITE);
- return Channels.newOutputStream(newByteChannel(opts));
+ return implNewOutputStream(opts);
}
/**
@@ -185,15 +194,7 @@ public abstract class AbstractPath exten
throws IOException
{
Set<OpenOption> opts = new HashSet<OpenOption>(options);
- if (opts.isEmpty()) {
- opts.add(StandardOpenOption.CREATE);
- opts.add(StandardOpenOption.TRUNCATE_EXISTING);
- } else {
- if (opts.contains(StandardOpenOption.READ))
- throw new IllegalArgumentException("READ not allowed");
- }
- opts.add(StandardOpenOption.WRITE);
- return Channels.newOutputStream(newByteChannel(opts, attrs));
+ return implNewOutputStream(opts, attrs);
}
/**
@@ -507,7 +508,6 @@ public abstract class AbstractPath exten
if (attrs.isDirectory()) {
target.createDirectory();
} else {
- target.createFile();
xProviderCopyRegularFileTo(target);
}
@@ -540,8 +540,7 @@ public abstract class AbstractPath exten
ReadableByteChannel rbc = newByteChannel();
try {
// open target file for writing
- SeekableByteChannel sbc = target
- .newByteChannel(StandardOpenOption.WRITE);
+ SeekableByteChannel sbc = target.newByteChannel(CREATE, WRITE);
// simple copy loop
try {
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java Wed Jan 21 15:09:31 2009 +0000
@@ -98,7 +98,6 @@ public class FileChannelImpl
// -- Standard channel operations --
protected void implCloseChannel() throws IOException {
-
// Invalidate and release any locks that we still hold
if (fileLockTable != null) {
fileLockTable.removeAll( new FileLockTable.Releaser() {
@@ -110,7 +109,7 @@ public class FileChannelImpl
}
nd.preClose(fd);
- threads.signal();
+ threads.signalAndWait();
if (parent != null) {
@@ -132,12 +131,11 @@ public class FileChannelImpl
throw new NonReadableChannelException();
synchronized (positionLock) {
int n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return 0;
- ti = threads.add();
do {
n = IOUtil.read(fd, dst, -1, nd, positionLock);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -156,12 +154,11 @@ public class FileChannelImpl
throw new NonReadableChannelException();
synchronized (positionLock) {
long n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return 0;
- ti = threads.add();
do {
n = IOUtil.read(fd, dsts, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -189,12 +186,11 @@ public class FileChannelImpl
throw new NonWritableChannelException();
synchronized (positionLock) {
int n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return 0;
- ti = threads.add();
do {
n = IOUtil.write(fd, src, -1, nd, positionLock);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -213,12 +209,11 @@ public class FileChannelImpl
throw new NonWritableChannelException();
synchronized (positionLock) {
long n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return 0;
- ti = threads.add();
do {
n = IOUtil.write(fd, srcs, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -247,12 +242,11 @@ public class FileChannelImpl
ensureOpen();
synchronized (positionLock) {
long p = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return 0;
- ti = threads.add();
do {
p = position0(fd, -1);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
@@ -271,12 +265,11 @@ public class FileChannelImpl
throw new IllegalArgumentException();
synchronized (positionLock) {
long p = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return null;
- ti = threads.add();
do {
p = position0(fd, newPosition);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
@@ -293,12 +286,11 @@ public class FileChannelImpl
ensureOpen();
synchronized (positionLock) {
long s = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return -1;
- ti = threads.add();
do {
s = nd.size(fd);
} while ((s == IOStatus.INTERRUPTED) && isOpen());
@@ -322,12 +314,11 @@ public class FileChannelImpl
synchronized (positionLock) {
int rv = -1;
long p = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return null;
- ti = threads.add();
// get current position
do {
@@ -362,12 +353,11 @@ public class FileChannelImpl
public void force(boolean metaData) throws IOException {
ensureOpen();
int rv = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return;
- ti = threads.add();
do {
rv = nd.force(fd, metaData);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
@@ -419,12 +409,11 @@ public class FileChannelImpl
return IOStatus.UNSUPPORTED;
long n = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return -1;
- ti = threads.add();
do {
n = transferTo0(thisFDVal, position, icount, targetFDVal);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -626,12 +615,11 @@ public class FileChannelImpl
throw new NonReadableChannelException();
ensureOpen();
int n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return -1;
- ti = threads.add();
do {
n = IOUtil.read(fd, dst, position, nd, positionLock);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -652,12 +640,11 @@ public class FileChannelImpl
throw new NonWritableChannelException();
ensureOpen();
int n = 0;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return -1;
- ti = threads.add();
do {
n = IOUtil.write(fd, src, position, nd, positionLock);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -747,12 +734,11 @@ public class FileChannelImpl
throw new NonReadableChannelException();
long addr = -1;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return null;
- ti = threads.add();
if (size() < position + size) { // Extend file size
if (!writable) {
throw new IOException("Channel not open for writing " +
@@ -888,10 +874,17 @@ public class FileChannelImpl
if (fileLockTable == null) {
synchronized (this) {
if (fileLockTable == null) {
- fileLockTable = isSharedFileLockTable() ?
- // FIXME - handle async close
- FileLockTable.newSharedFileLockTable(this, fd) :
- new SimpleFileLockTable();
+ if (isSharedFileLockTable()) {
+ int ti = threads.add();
+ try {
+ ensureOpen();
+ fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
+ } finally {
+ threads.remove(ti);
+ }
+ } else {
+ fileLockTable = new SimpleFileLockTable();
+ }
}
}
}
@@ -910,12 +903,11 @@ public class FileChannelImpl
FileLockTable flt = fileLockTable();
flt.add(fli);
boolean i = true;
- int ti = -1;
+ int ti = threads.add();
try {
begin();
if (!isOpen())
return null;
- ti = threads.add();
int result = nd.lock(fd, true, position, size, shared);
if (result == FileDispatcher.RET_EX_LOCK) {
assert shared;
@@ -954,31 +946,42 @@ public class FileChannelImpl
FileLockTable flt = fileLockTable();
flt.add(fli);
int result;
- try {
- // FIXME - handle async close
- 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;
+
+ 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);
+ }
}
void release(FileLockImpl fli) throws IOException {
ensureOpen();
- // FIXME - handle async close
- nd.release(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);
}
--- a/src/share/classes/sun/nio/ch/NativeThreadSet.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/sun/nio/ch/NativeThreadSet.java Wed Jan 21 15:09:31 2009 +0000
@@ -33,6 +33,7 @@ class NativeThreadSet {
private long[] elts;
private int used = 0;
+ private boolean waitingToEmpty;
NativeThreadSet(int n) {
elts = new long[n];
@@ -75,12 +76,14 @@ class NativeThreadSet {
synchronized (this) {
elts[i] = 0;
used--;
+ if (used == 0 && waitingToEmpty)
+ notifyAll();
}
}
// Signals all threads in this set.
//
- void signal() {
+ void signalAndWait() {
synchronized (this) {
int u = used;
int n = elts.length;
@@ -92,7 +95,12 @@ class NativeThreadSet {
if (--u == 0)
break;
}
+ waitingToEmpty = true;
+ while (used > 0) {
+ try {
+ wait();
+ } catch (InterruptedException ignore) { }
+ }
}
}
-
}
--- a/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Wed Jan 21 15:09:31 2009 +0000
@@ -99,9 +99,9 @@ public class SimpleAsynchronousFileChann
// signal any threads blocked on this channel
nd.preClose(fdObj);
- threads.signal();
-
- // wait until all I/O operations have completely gracefully
+ threads.signalAndWait();
+
+ // wait until all async I/O operations have completely gracefully
closeLock.writeLock().lock();
try {
// do nothing
--- a/src/share/classes/sun/nio/fs/AbstractWatchKey.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/classes/sun/nio/fs/AbstractWatchKey.java Wed Jan 21 15:09:31 2009 +0000
@@ -63,6 +63,10 @@ abstract class AbstractWatchKey extends
this.watcher = watcher;
this.state = State.READY;
this.events = new ArrayList<WatchEvent<?>>();
+ }
+
+ final AbstractWatchService watcher() {
+ return watcher;
}
/**
--- a/src/share/sample/nio/file/WatchDir.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/share/sample/nio/file/WatchDir.java Wed Jan 21 15:09:31 2009 +0000
@@ -46,6 +46,11 @@ public class WatchDir {
private final Map<WatchKey,Path> keys;
private final boolean recursive;
private boolean trace = false;
+
+ @SuppressWarnings("unchecked")
+ static <T> WatchEvent<T> cast(WatchEvent<?> event) {
+ return (WatchEvent<T>)event;
+ }
/**
* Register the given directory with the WatchService
@@ -133,7 +138,8 @@ public class WatchDir {
}
// Context for directory entry event is the file name of entry
- Path name = ((WatchEvent<Path>)event).context();
+ WatchEvent<Path> ev = cast(event);
+ Path name = ev.context();
Path child = dir.resolve(name);
// print out event
--- a/src/solaris/classes/sun/nio/ch/EPollPort.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/ch/EPollPort.java Wed Jan 21 15:09:31 2009 +0000
@@ -30,7 +30,7 @@ import java.util.concurrent.ArrayBlockin
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
-import sun.misc.Unsafe;
+import static sun.nio.ch.EPoll.*;
/**
* AsynchronousChannelGroup implementation based on the Linux epoll facility.
@@ -39,36 +39,8 @@ final class EPollPort
final class EPollPort
extends Port
{
- private static final Unsafe unsafe = Unsafe.getUnsafe();
-
- /**
- * typedef union epoll_data {
- * void *ptr;
- * int fd;
- * __uint32_t u32;
- * __uint64_t u64;
- * } epoll_data_t;
- *
- * struct epoll_event {
- * __uint32_t events;
- * epoll_data_t data;
- * }
- */
- // FIMXE - make this architecture independent
- private static final short SIZEOF_EPOLLEVENT = 12;
- private static final short EVENT_OFFSET = 0;
- private static final short FD_OFFSET = 4;
-
- // opcodes
- private static final int EPOLL_CTL_ADD = 1;
- private static final int EPOLL_CTL_DEL = 2;
- private static final int EPOLL_CTL_MOD = 3;
-
// maximum number of events to poll at a time
- private static final int MAX_EPOLL_EVENTS = 512;
-
- // flags
- private static final int EPOLLONESHOT = (1 << 30);
+ private static final int MAX_EPOLL_EVENTS = 64;
// errors
private static final int ENOENT = 2;
@@ -129,8 +101,7 @@ final class EPollPort
this.sp = sv;
// allocate the poll array
- int allocationSize = MAX_EPOLL_EVENTS * SIZEOF_EPOLLEVENT;
- this.address = unsafe.allocateMemory(allocationSize);
+ this.address = allocatePollArray(MAX_EPOLL_EVENTS);
// create the queue and offer the special event to ensure that the first
// threads polls
@@ -152,7 +123,7 @@ final class EPollPort
return;
closed = true;
}
- unsafe.freeMemory(address);
+ freePollArray(address);
close0(sp[0]);
close0(sp[1]);
close0(epfd);
@@ -230,8 +201,8 @@ final class EPollPort
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
- long eventAddress = address + (SIZEOF_EPOLLEVENT*n);
- int fd = unsafe.getInt(eventAddress + FD_OFFSET);
+ long eventAddress = getEvent(address, n);
+ int fd = getDescriptor(eventAddress);
// wakeup
if (fd == sp[0]) {
@@ -251,7 +222,7 @@ final class EPollPort
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
- int events = unsafe.getInt(eventAddress + EVENT_OFFSET);
+ int events = getEvents(eventAddress);
Event ev = new Event(channel, events);
// n-1 events are queued; This thread handles
@@ -337,25 +308,15 @@ final class EPollPort
// -- Native methods --
- private static native void init();
-
- private static native int epollCreate() throws IOException;
-
- private static native int epollCtl(int epfd, int opcode, int fd, int events);
-
- private static native int epollWait(int epfd, long pollAddress, int numfds)
- throws IOException;
-
private static native void socketpair(int[] sv) throws IOException;
private static native void interrupt(int fd) throws IOException;
private static native void drain1(int fd) throws IOException;
- private static native void close0(int epfd);
+ private static native void close0(int fd);
static {
Util.load();
- init();
}
}
--- a/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java Wed Jan 21 15:09:31 2009 +0000
@@ -38,6 +38,9 @@ public class GnomeFileTypeDetector
public class GnomeFileTypeDetector
extends AbstractFileTypeDetector
{
+ private static final String GNOME_VFS_MIME_TYPE_UNKNOWN =
+ "application/octet-stream";
+
// true if GIO available
private final boolean gioAvailable;
@@ -71,7 +74,7 @@ public class GnomeFileTypeDetector
if (type == null)
return null;
String s = new String(type);
- return s.equals("application/octet-stream") ? null : s;
+ return s.equals(GNOME_VFS_MIME_TYPE_UNKNOWN) ? null : s;
}
} finally {
--- a/src/solaris/classes/sun/nio/fs/LinuxFileStore.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileStore.java Wed Jan 21 15:09:31 2009 +0000
@@ -39,7 +39,7 @@ class LinuxFileStore
super(file);
}
- LinuxFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+ LinuxFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
super(fs, entry);
}
@@ -48,7 +48,9 @@ class LinuxFileStore
* resides.
*/
@Override
- UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException {
+ UnixMountEntry findMountEntry() throws IOException {
+ UnixFileSystem fs = file().getFileSystem();
+
// step 1: get realpath
UnixPath path = null;
try {
@@ -99,4 +101,9 @@ class LinuxFileStore
return super.supportsFileAttributeView(name);
}
+
+ @Override
+ boolean isLoopback() {
+ return false;
+ }
}
--- a/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java Wed Jan 21 15:09:31 2009 +0000
@@ -38,9 +38,8 @@ import static sun.nio.fs.LinuxNativeDisp
*/
class LinuxFileSystem extends UnixFileSystem {
- private final int majorVersion;
- private final int minorVersion;
- private final int microVersion;
+ private final boolean hasInotify;
+ private final boolean hasAtSysCalls;
LinuxFileSystem(UnixFileSystemProvider provider, String dir) {
super(provider, dir);
@@ -49,35 +48,38 @@ class LinuxFileSystem extends UnixFileSy
String osversion = AccessController
.doPrivileged(new GetPropertyAction("os.version"));
String[] vers = osversion.split("\\.", 0);
- if (vers.length >= 2) {
- this.majorVersion = Integer.parseInt(vers[0]);
- this.minorVersion = Integer.parseInt(vers[1]);
- if (vers.length > 2) {
- String[] microVers = vers[2].split("-", 0);
- this.microVersion = (microVers.length > 0) ?
- Integer.parseInt(microVers[0]) : 0;
- } else {
- this.microVersion = 0;
- }
- } else {
- throw new AssertionError();
+ assert vers.length >= 2;
+
+ int majorVersion = Integer.parseInt(vers[0]);
+ int minorVersion = Integer.parseInt(vers[1]);
+ int microVersion = 0;
+ if (vers.length > 2) {
+ String[] microVers = vers[2].split("-", 0);
+ microVersion = (microVers.length > 0) ?
+ Integer.parseInt(microVers[0]) : 0;
}
+
+ // inotify available since 2.6.13
+ this.hasInotify = ((majorVersion > 2) ||
+ (majorVersion == 2 && minorVersion > 6) ||
+ ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)));
+
+ // openat etc. available since 2.6.16
+ this.hasAtSysCalls = ((majorVersion > 2) ||
+ (majorVersion == 2 && minorVersion > 6) ||
+ ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 16)));
}
@Override
public WatchService newWatchService()
throws IOException
{
- // inotify available since 2.6.13
- if ((majorVersion > 2) ||
- (majorVersion == 2 && minorVersion > 6) ||
- ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)))
- {
+ if (hasInotify) {
return new LinuxWatchService(this);
+ } else {
+ // use polling implementation on older kernels
+ return new PollingWatchService();
}
-
- // use polling implementation on older kernels
- return new PollingWatchService();
}
@Override
@@ -132,14 +134,7 @@ class LinuxFileSystem extends UnixFileSy
@Override
boolean supportsSecureDirectoryStreams() {
- // openat etc. available since 2.6.16
- if ((majorVersion > 2) ||
- (majorVersion == 2 && minorVersion > 6) ||
- ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 16)))
- {
- return true;
- }
- return false;
+ return hasAtSysCalls;
}
/**
@@ -174,7 +169,7 @@ class LinuxFileSystem extends UnixFileSy
}
@Override
- FileStore getFileStore(UnixMountEntry entry) {
+ FileStore getFileStore(UnixMountEntry entry) throws IOException {
return new LinuxFileStore(this, entry);
}
}
--- a/src/solaris/classes/sun/nio/fs/LinuxWatchService.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/LinuxWatchService.java Wed Jan 21 15:09:31 2009 +0000
@@ -96,7 +96,7 @@ class LinuxWatchService
/**
* WatchKey implementation
*/
- private class LinuxWatchKey extends AbstractWatchKey {
+ private static class LinuxWatchKey extends AbstractWatchKey {
// inotify descriptor
private final int ifd;
// watch descriptor
@@ -132,7 +132,7 @@ class LinuxWatchService
public void cancel() {
if (isValid()) {
// delegate to poller
- poller.cancel(this);
+ ((LinuxWatchService)watcher()).poller.cancel(this);
}
}
}
@@ -140,7 +140,7 @@ class LinuxWatchService
/**
* Background thread to read from inotify
*/
- private class Poller extends AbstractPoller {
+ private static class Poller extends AbstractPoller {
/**
* struct inotify_event {
* int wd;
@@ -149,11 +149,12 @@ class LinuxWatchService
* char name __flexarr; // present if len > 0
* } act_t;
*/
- private static final short SIZEOF_INOTIFY_EVENT = 16;
- private static final short OFFSETOF_WD = 0;
- private static final short OFFSETOF_MASK = 4;
- private static final short OFFSETOF_LEN = 12;
- private static final short OFFSETOF_NAME = 16;
+ private static final int SIZEOF_INOTIFY_EVENT = eventSize();
+ private static final int[] offsets = eventOffsets();
+ private static final int OFFSETOF_WD = offsets[0];
+ private static final int OFFSETOF_MASK = offsets[1];
+ private static final int OFFSETOF_LEN = offsets[3];
+ private static final int OFFSETOF_NAME = offsets[4];
private static final int IN_MODIFY = 0x00000002;
private static final int IN_ATTRIB = 0x00000004;
@@ -165,9 +166,6 @@ class LinuxWatchService
private static final int IN_UNMOUNT = 0x00002000;
private static final int IN_Q_OVERFLOW = 0x00004000;
private static final int IN_IGNORED = 0x00008000;
-
- private static final int IN_ISDIR = 0x40000000;
- private static final int IN_MASK_ADD = 0x20000000;
// sizeof buffer for when polling inotify
private static final int BUFFER_SIZE = 8192;
@@ -441,6 +439,12 @@ class LinuxWatchService
private static native void init();
+ // sizeof inotify_event
+ private static native int eventSize();
+
+ // offsets of inotify_event
+ private static native int[] eventOffsets();
+
private static native int inotifyInit() throws UnixException;
private static native int inotifyAddWatch(int fd, long pathAddress, int mask)
--- a/src/solaris/classes/sun/nio/fs/SolarisFileStore.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/SolarisFileStore.java Wed Jan 21 15:09:31 2009 +0000
@@ -44,7 +44,7 @@ class SolarisFileStore
this.xattrEnabled = xattrEnabled();
}
- SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+ SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
super(fs, entry);
this.xattrEnabled = xattrEnabled();
}
@@ -61,9 +61,9 @@ class SolarisFileStore
}
@Override
- UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException {
+ UnixMountEntry findMountEntry() throws IOException {
// On Solaris iterate over the entries in the mount table to find device
- for (UnixMountEntry entry: fs.getMountEntries()) {
+ for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) {
if (entry.dev() == dev()) {
return entry;
}
@@ -95,4 +95,9 @@ class SolarisFileStore
return super.supportsFileAttributeView(name);
}
+
+ @Override
+ boolean isLoopback() {
+ return type().equals("lofs");
+ }
}
--- a/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java Wed Jan 21 15:09:31 2009 +0000
@@ -38,34 +38,20 @@ import static sun.nio.fs.UnixNativeDispa
*/
class SolarisFileSystem extends UnixFileSystem {
- private final int majorVersion;
- private final int minorVersion;
+ private final boolean hasSolaris11Features;
SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
super(provider, dir);
+ // check os.version
String osversion = AccessController
.doPrivileged(new GetPropertyAction("os.version"));
String[] vers = osversion.split("\\.", 0);
- if (vers.length >= 2) {
- this.majorVersion = Integer.parseInt(vers[0]);
- this.minorVersion = Integer.parseInt(vers[1]);
- } else {
- // should not get here
- throw new AssertionError();
- }
-
- // O_NOFOLLOW not supported prior to Solaris 10
- if ((majorVersion < 5) || (majorVersion == 5 && minorVersion < 10))
- throw new RuntimeException("Need Solaris 10 or greater");
- }
-
- private boolean hasSolaris11Features() {
- if (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11)) {
- return true;
- } else {
- return false;
- }
+ assert vers.length >= 2;
+ int majorVersion = Integer.parseInt(vers[0]);
+ int minorVersion = Integer.parseInt(vers[1]);
+ this.hasSolaris11Features =
+ (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11));
}
@Override
@@ -78,7 +64,7 @@ class SolarisFileSystem extends UnixFile
throws IOException
{
// FEN available since Solaris 11
- if (hasSolaris11Features()) {
+ if (hasSolaris11Features) {
return new SolarisWatchService(this);
} else {
return new PollingWatchService();
@@ -172,7 +158,7 @@ class SolarisFileSystem extends UnixFile
}
@Override
- FileStore getFileStore(UnixMountEntry entry) {
+ FileStore getFileStore(UnixMountEntry entry) throws IOException {
return new SolarisFileStore(this, entry);
}
}
--- a/src/solaris/classes/sun/nio/fs/UnixFileStore.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/UnixFileStore.java Wed Jan 21 15:09:31 2009 +0000
@@ -49,29 +49,38 @@ abstract class UnixFileStore
// entry in the mount tab
private final UnixMountEntry entry;
- UnixFileStore(UnixPath file) throws IOException {
- // need device ID
- long devID = 0;
+ // return the device ID where the given file resides
+ private static long devFor(UnixPath file) throws IOException {
try {
- devID = UnixFileAttributes.get(file, true).dev();
+ return UnixFileAttributes.get(file, true).dev();
} catch (UnixException x) {
x.rethrowAsIOException(file);
- }
+ return 0L; // keep compiler happy
+ }
+ }
+
+ UnixFileStore(UnixPath file) throws IOException {
this.file = file;
- this.dev = devID;
- this.entry = findMountEntry(file.getFileSystem());
- }
-
- UnixFileStore(UnixFileSystem fs, UnixMountEntry entry) {
+ this.dev = devFor(file);
+ this.entry = findMountEntry();
+ }
+
+ UnixFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
this.file = new UnixPath(fs, entry.dir());
- this.dev = entry.dev();
+ this.dev = (entry.dev() == 0L) ? devFor(this.file) : entry.dev();
this.entry = entry;
}
/**
- * Find the mount entry for this file system
- */
- abstract UnixMountEntry findMountEntry(UnixFileSystem fs) throws IOException;
+ * Find the mount entry for the file store
+ */
+ abstract UnixMountEntry findMountEntry() throws IOException;
+
+ /**
+ * Returns true if this file store represents a loopback file system that
+ * will have the same device ID as undelrying file system.
+ */
+ abstract boolean isLoopback();
UnixPath file() {
return file;
@@ -150,7 +159,17 @@ abstract class UnixFileStore
if (!(ob instanceof UnixFileStore))
return false;
UnixFileStore other = (UnixFileStore)ob;
- return dev == other.dev;
+ if (dev != other.dev)
+ return false;
+ // deviceIDs are equal but they may not be equal if one or both of
+ // them is a loopback file system
+ boolean thisIsLoopback = isLoopback();
+ if (thisIsLoopback != other.isLoopback())
+ return false; // one, but not both, are lofs
+ if (!thisIsLoopback)
+ return true; // neither is lofs
+ // both are lofs so compare mount points
+ return Arrays.equals(this.entry.dir(), other.entry.dir());
}
@Override
@@ -181,12 +200,6 @@ abstract class UnixFileStore
throws IOException
{
UnixPath file = fs.file();
-
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- file.checkRead();
- sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
- }
final UnixFileStoreAttributes attrs;
try {
attrs = UnixFileStoreAttributes.get(file);
--- a/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Wed Jan 21 15:09:31 2009 +0000
@@ -182,7 +182,7 @@ abstract class UnixFileSystem
* Returns a FileStore to represent the file system for the given mount
* mount.
*/
- abstract FileStore getFileStore(UnixMountEntry entry);
+ abstract FileStore getFileStore(UnixMountEntry entry) throws IOException;
/**
* Iterator returned by getFileStores method.
@@ -215,7 +215,11 @@ abstract class UnixFileSystem
continue;
}
}
- return getFileStore(entry);
+ try {
+ return getFileStore(entry);
+ } catch (IOException ignore) {
+ // ignore as per spec
+ }
}
}
@@ -248,6 +252,14 @@ abstract class UnixFileSystem
@Override
public final Iterable<FileStore> getFileStores() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+ } catch (SecurityException se) {
+ return Collections.emptyList();
+ }
+ }
return new Iterable<FileStore>() {
public Iterator<FileStore> iterator() {
return new FileStoreIterator();
--- a/src/solaris/classes/sun/nio/fs/UnixMountEntry.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/UnixMountEntry.java Wed Jan 21 15:09:31 2009 +0000
@@ -36,6 +36,7 @@ class UnixMountEntry {
private byte[] opts; // mount options
private long dev; // device ID
+ private volatile String fstypeAsString;
private volatile String optionsAsString;
UnixMountEntry() {
@@ -46,7 +47,9 @@ class UnixMountEntry {
}
String fstype() {
- return new String(fstype);
+ if (fstypeAsString == null)
+ fstypeAsString = new String(fstype);
+ return fstypeAsString;
}
byte[] dir() {
--- a/src/solaris/classes/sun/nio/fs/UnixPath.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/classes/sun/nio/fs/UnixPath.java Wed Jan 21 15:09:31 2009 +0000
@@ -759,7 +759,11 @@ class UnixPath
public FileStore getFileStore()
throws IOException
{
- checkRead();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+ checkRead();
+ }
return getFileSystem().getFileStore(this);
}
--- a/src/solaris/native/sun/nio/ch/EPollPort.c Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/native/sun/nio/ch/EPollPort.c Wed Jan 21 15:09:31 2009 +0000
@@ -31,106 +31,9 @@
#include "sun_nio_ch_EPollPort.h"
-#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* epoll_wait(2) man page */
-
-typedef union epoll_data {
- void *ptr;
- int fd;
- __uint32_t u32;
- __uint64_t u64;
-} epoll_data_t;
-
-struct epoll_event {
- __uint32_t events; /* Epoll events */
- epoll_data_t data; /* User data variable */
-} __attribute__ ((__packed__));
-
-#ifdef __cplusplus
-}
-#endif
-
-/*
- * epoll event notification is new in 2.6 kernel. As the offical build
- * platform for the JDK is on a 2.4-based distribution then we must
- * obtain the addresses of the epoll functions dynamically.
- */
-typedef int (*epoll_create_t)(int size);
-typedef int (*epoll_ctl_t) (int epfd, int op, int fd, struct epoll_event *event);
-typedef int (*epoll_wait_t) (int epfd, struct epoll_event *events, int maxevents, int timeout);
-
-static epoll_create_t epoll_create_func;
-static epoll_ctl_t epoll_ctl_func;
-static epoll_wait_t epoll_wait_func;
-
-#ifndef EPOLL_CTL_ADD
-#define EPOLL_CTL_ADD 1
-#define EPOLL_CTL_DEL 2
-#define EPOLL_CTL_MOD 3
-#endif
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_init(JNIEnv *env, jclass this)
-{
- epoll_create_func = (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create");
- epoll_ctl_func = (epoll_ctl_t) dlsym(RTLD_DEFAULT, "epoll_ctl");
- epoll_wait_func = (epoll_wait_t) dlsym(RTLD_DEFAULT, "epoll_wait");
-
- if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) ||
- (epoll_wait_func == NULL)) {
- JNU_ThrowInternalError(env, "unable to get address of epoll functions, pre-2.6 kernel?");
- }
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollPort_epollCreate(JNIEnv *env, jclass c) {
- /*
- * epoll_create expects a size as a hint to the kernel about how to
- * dimension internal structures. We can't predict the size in advance.
- */
- int epfd = (*epoll_create_func)(256);
- if (epfd < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
- }
- return epfd;
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollPort_epollCtl(JNIEnv *env, jclass c, jint epfd,
- jint opcode, jint fd, jint events)
-{
- struct epoll_event event;
- int res;
-
- event.events = events;
- event.data.fd = fd;
-
- RESTARTABLE((*epoll_ctl_func)(epfd, (int)opcode, (int)fd, &event), res);
-
- return (res == 0) ? 0 : errno;
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollPort_epollWait(JNIEnv *env, jclass c,
- jint epfd, jlong address, jint numfds)
-{
- struct epoll_event *events = jlong_to_ptr(address);
- int res;
-
- RESTARTABLE((*epoll_wait_func)(epfd, events, numfds, -1), res);
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
- }
- return res;
-}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
@@ -167,7 +70,7 @@ Java_sun_nio_ch_EPollPort_drain1(JNIEnv
}
JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint epfd) {
+Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint fd) {
int res;
- RESTARTABLE(close(epfd), res);
+ RESTARTABLE(close(fd), res);
}
--- a/src/solaris/native/sun/nio/fs/LinuxWatchService.c Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/native/sun/nio/fs/LinuxWatchService.c Wed Jan 21 15:09:31 2009 +0000
@@ -36,6 +36,22 @@
#include "sun_nio_fs_LinuxWatchService.h"
+/* inotify.h may not be available at build time */
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct inotify_event
+{
+ int wd;
+ uint32_t mask;
+ uint32_t cookie;
+ uint32_t len;
+ char name __flexarr;
+};
+#ifdef __cplusplus
+}
+#endif
+
typedef int inotify_init_func(void);
typedef int inotify_add_watch_func(int fd, const char* path, uint32_t mask);
typedef int inotify_rm_watch_func(int fd, uint32_t wd);
@@ -67,6 +83,29 @@ Java_sun_nio_fs_LinuxWatchService_init(J
JNU_ThrowInternalError(env, "unable to get address of inotify functions");
}
}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_LinuxWatchService_eventSize(JNIEnv *env, jclass clazz)
+{
+ return (jint)sizeof(struct inotify_event);
+}
+
+JNIEXPORT jintArray JNICALL
+Java_sun_nio_fs_LinuxWatchService_eventOffsets(JNIEnv *env, jclass clazz)
+{
+ jintArray result = (*env)->NewIntArray(env, 5);
+ if (result != NULL) {
+ jint arr[5];
+ arr[0] = (jint)offsetof(struct inotify_event, wd);
+ arr[1] = (jint)offsetof(struct inotify_event, mask);
+ arr[2] = (jint)offsetof(struct inotify_event, cookie);
+ arr[3] = (jint)offsetof(struct inotify_event, len);
+ arr[4] = (jint)offsetof(struct inotify_event, name);
+ (*env)->SetIntArrayRegion(env, result, 0, 5, arr);
+ }
+ return result;
+}
+
JNIEXPORT jint JNICALL
Java_sun_nio_fs_LinuxWatchService_inotifyInit
--- a/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c Tue Jan 20 15:25:51 2009 +0000
+++ b/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c Wed Jan 21 15:09:31 2009 +0000
@@ -103,9 +103,10 @@ static fdopendir_func* my_fdopendir_func
/**
* fstatat missing from glibc on Linux. Temporary workaround
- * for x86/x64, will fail to compile on other architectures.
+ * for x86/x64.
*/
#if defined(__linux__) && defined(__i386)
+#define FSTATAT64_SYSCALL_AVAILABLE
static int fstatat64_wrapper(int dfd, const char *path,
struct stat64 *statbuf, int flag)
{
@@ -117,6 +118,7 @@ static int fstatat64_wrapper(int dfd, co
#endif
#if defined(__linux__) && defined(__x86_64__)
+#define FSTATAT64_SYSCALL_AVAILABLE
static int fstatat64_wrapper(int dfd, const char *path,
struct stat64 *statbuf, int flag)
{
@@ -197,7 +199,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_ini
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir");
-#if defined(__linux__)
+#if defined(FSTATAT64_SYSCALL_AVAILABLE)
/* fstatat64 missing from glibc */
if (my_fstatat64_func == NULL)
my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
--- a/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Wed Jan 21 15:09:31 2009 +0000
@@ -131,7 +131,7 @@ class WindowsFileAttributes
/**
* If this object represents the attributes of a reparse point then read
- * the reparse point tag. This method has effect if the attributes were
+ * the reparse point tag. This method has no effect if the attributes were
* read from a file that is not a reparse point.
*/
WindowsFileAttributes finishRead(WindowsPath path)
--- a/src/windows/classes/sun/nio/fs/WindowsFileStore.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/windows/classes/sun/nio/fs/WindowsFileStore.java Wed Jan 21 15:09:31 2009 +0000
@@ -41,16 +41,12 @@ class WindowsFileStore
extends FileStore
{
private final String root;
- private final String pathForPermissionCheck;
private final VolumeInformation info;
private final String displayName; // returned by toString
- private WindowsFileStore(String root, String pathForPermissionCheck)
- throws WindowsException
- {
+ private WindowsFileStore(String root) throws WindowsException {
assert root.charAt(root.length()-1) == '\\';
this.root = root;
- this.pathForPermissionCheck = pathForPermissionCheck;
this.info = GetVolumeInformation(root);
// file store "display name" is the volume name if available
@@ -68,7 +64,7 @@ class WindowsFileStore
throws IOException
{
try {
- return new WindowsFileStore(root, root);
+ return new WindowsFileStore(root);
} catch (WindowsException x) {
if (ignoreNotReady && x.lastError() == ERROR_NOT_READY)
return null;
@@ -91,7 +87,7 @@ class WindowsFileStore
target = file.getPathForWin32Calls();
}
String root = GetVolumePathName(target);
- return new WindowsFileStore(root, file.getPathForPermissionCheck());
+ return new WindowsFileStore(root);
} catch (WindowsException x) {
x.rethrowAsIOException(file);
return null; // keep compiler happy
@@ -100,14 +96,6 @@ class WindowsFileStore
VolumeInformation volumeInformation() {
return info;
- }
-
- void checkAttributeAccess() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkRead(pathForPermissionCheck);
- sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
- }
}
@Override
@@ -207,14 +195,12 @@ class WindowsFileStore
public FileStoreSpaceAttributes readAttributes()
throws IOException
{
- fs.checkAttributeAccess();
-
// read the free space info
DiskFreeSpace info = null;
try {
info = GetDiskFreeSpaceEx(fs.root);
} catch (WindowsException x) {
- x.rethrowAsIOException(fs.pathForPermissionCheck);
+ x.rethrowAsIOException(fs.root);
}
final DiskFreeSpace result = info;
@@ -256,12 +242,10 @@ class WindowsFileStore
}
private int vsn() {
- fs.checkAttributeAccess();
return fs.volumeInformation().volumeSerialNumber();
}
private boolean isCompressed() {
- fs.checkAttributeAccess();
return (fs.volumeInformation().flags() &
FILE_VOLUME_IS_COMPRESSED) > 0;
}
--- a/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Wed Jan 21 15:09:31 2009 +0000
@@ -116,8 +116,8 @@ class WindowsFileSystem
throw new UnsupportedOperationException();
}
- // return new iterator over root directories
- private Iterator<Path> rootDirectoryIterator() {
+ @Override
+ public Iterable<Path> getRootDirectories() {
int drives = 0;
try {
drives = WindowsNativeDispatcher.GetLogicalDrives();
@@ -145,16 +145,7 @@ class WindowsFileSystem
result.add(WindowsPath.createFromNormalizedPath(this, root));
}
}
- return Collections.unmodifiableList(result).iterator();
- }
-
- @Override
- public Iterable<Path> getRootDirectories() {
- return new Iterable<Path>() {
- public Iterator<Path> iterator() {
- return rootDirectoryIterator();
- }
- };
+ return Collections.unmodifiableList(result);
}
/**
@@ -219,6 +210,14 @@ class WindowsFileSystem
@Override
public Iterable<FileStore> getFileStores() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+ } catch (SecurityException se) {
+ return Collections.emptyList();
+ }
+ }
return new Iterable<FileStore>() {
public Iterator<FileStore> iterator() {
return new FileStoreIterator();
--- a/src/windows/classes/sun/nio/fs/WindowsPath.java Tue Jan 20 15:25:51 2009 +0000
+++ b/src/windows/classes/sun/nio/fs/WindowsPath.java Wed Jan 21 15:09:31 2009 +0000
@@ -749,7 +749,11 @@ class WindowsPath extends AbstractPath {
public FileStore getFileStore()
throws IOException
{
- checkRead();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
+ checkRead();
+ }
return WindowsFileStore.create(this);
}
--- a/test/java/nio/file/FileStore/Basic.java Tue Jan 20 15:25:51 2009 +0000
+++ b/test/java/nio/file/FileStore/Basic.java Wed Jan 21 15:09:31 2009 +0000
@@ -30,6 +30,7 @@ import java.nio.file.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
+import java.util.*;
public class Basic {
@@ -70,10 +71,17 @@ public class Basic {
/**
* Test: Enumerate all FileStores
*/
+ FileStore prev = null;
for (FileStore store: FileSystems.getDefault().getFileStores()) {
System.out.format("%s (name=%s type=%s)\n", store, store.name(),
store.type());
+
+ // check space attributes
Attributes.readFileStoreSpaceAttributes(store);
+
+ // two distinct FileStores should not be equal
+ assertTrue(!store.equals(prev));
+ prev = store;
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/EPoll.java Wed Jan 21 15:09:31 2009 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.nio.ch;
+
+import java.io.IOException;
+import sun.misc.Unsafe;
+
+/**
+ * Provides access to the Linux epoll facility.
+ */
+
+class EPoll {
+ private EPoll() { }
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+ /**
+ * typedef union epoll_data {
+ * void *ptr;
+ * int fd;
+ * __uint32_t u32;
+ * __uint64_t u64;
+ * } epoll_data_t;
+ *
+ * struct epoll_event {
+ * __uint32_t events;
+ * epoll_data_t data;
+ * }
+ */
+ private static final int SIZEOF_EPOLLEVENT = eventSize();
+ private static final int OFFSETOF_EVENTS = eventsOffset();
+ private static final int OFFSETOF_FD = dataOffset();
+
+ // opcodes
+ static final int EPOLL_CTL_ADD = 1;
+ static final int EPOLL_CTL_DEL = 2;
+ static final int EPOLL_CTL_MOD = 3;
+
+ // flags
+ static final int EPOLLONESHOT = (1 << 30);
+
+ /**
+ * Allocates a poll array to handle up to {@code count} events.
+ */
+ static long allocatePollArray(int count) {
+ return unsafe.allocateMemory(count * SIZEOF_EPOLLEVENT);
+ }
+
+ /**
+ * Free a poll array
+ */
+ static void freePollArray(long address) {
+ unsafe.freeMemory(address);
+ }
+
+ /**
+ * Returns event[i];
+ */
+ static long getEvent(long address, int i) {
+ return address + (SIZEOF_EPOLLEVENT*i);
+ }
+
+ /**
+ * Returns event->data.fd
+ */
+ static int getDescriptor(long eventAddress) {
+ return unsafe.getInt(eventAddress + OFFSETOF_FD);
+ }
+
+ /**
+ * Returns event->events
+ */
+ static int getEvents(long eventAddress) {
+ return unsafe.getInt(eventAddress + OFFSETOF_EVENTS);
+ }
+
+ // -- Native methods --
+
+ private static native void init();
+
+ private static native int eventSize();
+
+ private static native int eventsOffset();
+
+ private static native int dataOffset();
+
+ static native int epollCreate() throws IOException;
+
+ static native int epollCtl(int epfd, int opcode, int fd, int events);
+
+ static native int epollWait(int epfd, long pollAddress, int numfds)
+ throws IOException;
+
+ static {
+ Util.load();
+ init();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/native/sun/nio/ch/EPoll.c Wed Jan 21 15:09:31 2009 +0000
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_EPoll.h"
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* epoll_wait(2) man page */
+
+typedef union epoll_data {
+ void *ptr;
+ int fd;
+ __uint32_t u32;
+ __uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event {
+ __uint32_t events; /* Epoll events */
+ epoll_data_t data; /* User data variable */
+} __attribute__ ((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * epoll event notification is new in 2.6 kernel. As the offical build
+ * platform for the JDK is on a 2.4-based distribution then we must
+ * obtain the addresses of the epoll functions dynamically.
+ */
+typedef int (*epoll_create_t)(int size);
+typedef int (*epoll_ctl_t) (int epfd, int op, int fd, struct epoll_event *event);
+typedef int (*epoll_wait_t) (int epfd, struct epoll_event *events, int maxevents, int timeout);
+
+static epoll_create_t epoll_create_func;
+static epoll_ctl_t epoll_ctl_func;
+static epoll_wait_t epoll_wait_func;
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPoll_init(JNIEnv *env, jclass this)
+{
+ epoll_create_func = (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create");
+ epoll_ctl_func = (epoll_ctl_t) dlsym(RTLD_DEFAULT, "epoll_ctl");
+ epoll_wait_func = (epoll_wait_t) dlsym(RTLD_DEFAULT, "epoll_wait");
+
+ if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) ||
+ (epoll_wait_func == NULL)) {
+ JNU_ThrowInternalError(env, "unable to get address of epoll functions, pre-2.6 kernel?");
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass this)
+{
+ return sizeof(struct epoll_event);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass this)
+{
+ return offsetof(struct epoll_event, events);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass this)
+{
+ return offsetof(struct epoll_event, data);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) {
+ /*
+ * epoll_create expects a size as a hint to the kernel about how to
+ * dimension internal structures. We can't predict the size in advance.
+ */
+ int epfd = (*epoll_create_func)(256);
+ if (epfd < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
+ }
+ return epfd;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
+ jint opcode, jint fd, jint events)
+{
+ struct epoll_event event;
+ int res;
+
+ event.events = events;
+ event.data.fd = fd;
+
+ RESTARTABLE((*epoll_ctl_func)(epfd, (int)opcode, (int)fd, &event), res);
+
+ return (res == 0) ? 0 : errno;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_EPoll_epollWait(JNIEnv *env, jclass c,
+ jint epfd, jlong address, jint numfds)
+{
+ struct epoll_event *events = jlong_to_ptr(address);
+ int res;
+
+ RESTARTABLE((*epoll_wait_func)(epfd, events, numfds, -1), res);
+ if (res < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+ }
+ return res;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_EPoll_close0(JNIEnv *env, jclass c, jint epfd) {
+ int res;
+ RESTARTABLE(close(epfd), res);
+}