summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/java/nio
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-09 19:58:05 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-09 19:58:05 +0000
commit65bf3316cf384588453604be6b4f0ed3751a8b0f (patch)
tree996a5f57d4a68c53473382e45cb22f574cb3e4db /libjava/classpath/gnu/java/nio
parent8fc56618a84446beccd45b80381cdfe0e94050df (diff)
downloadppe42-gcc-65bf3316cf384588453604be6b4f0ed3751a8b0f.tar.gz
ppe42-gcc-65bf3316cf384588453604be6b4f0ed3751a8b0f.zip
Merged gcj-eclipse branch to trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120621 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/classpath/gnu/java/nio')
-rw-r--r--libjava/classpath/gnu/java/nio/DatagramChannelImpl.java165
-rw-r--r--libjava/classpath/gnu/java/nio/DatagramChannelSelectionKey.java13
-rw-r--r--libjava/classpath/gnu/java/nio/EpollSelectionKeyImpl.java122
-rw-r--r--libjava/classpath/gnu/java/nio/EpollSelectorImpl.java399
-rw-r--r--libjava/classpath/gnu/java/nio/FileChannelImpl.java (renamed from libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java)173
-rw-r--r--libjava/classpath/gnu/java/nio/FileLockImpl.java2
-rw-r--r--libjava/classpath/gnu/java/nio/KqueueSelectionKeyImpl.java189
-rw-r--r--libjava/classpath/gnu/java/nio/KqueueSelectorImpl.java527
-rw-r--r--libjava/classpath/gnu/java/nio/NIOSocket.java29
-rw-r--r--libjava/classpath/gnu/java/nio/NIOSocketImpl.java110
-rw-r--r--libjava/classpath/gnu/java/nio/PipeImpl.java34
-rw-r--r--libjava/classpath/gnu/java/nio/SelectionKeyImpl.java1
-rw-r--r--libjava/classpath/gnu/java/nio/SelectorImpl.java20
-rw-r--r--libjava/classpath/gnu/java/nio/SelectorProviderImpl.java37
-rw-r--r--libjava/classpath/gnu/java/nio/ServerSocketChannelImpl.java39
-rw-r--r--libjava/classpath/gnu/java/nio/ServerSocketChannelSelectionKey.java13
-rw-r--r--libjava/classpath/gnu/java/nio/SocketChannelImpl.java262
-rw-r--r--libjava/classpath/gnu/java/nio/SocketChannelSelectionKey.java13
-rw-r--r--libjava/classpath/gnu/java/nio/SocketChannelSelectionKeyImpl.java11
-rw-r--r--libjava/classpath/gnu/java/nio/VMChannelOwner.java57
20 files changed, 1792 insertions, 424 deletions
diff --git a/libjava/classpath/gnu/java/nio/DatagramChannelImpl.java b/libjava/classpath/gnu/java/nio/DatagramChannelImpl.java
index 4687bf3f59e..268ee0a8aa7 100644
--- a/libjava/classpath/gnu/java/nio/DatagramChannelImpl.java
+++ b/libjava/classpath/gnu/java/nio/DatagramChannelImpl.java
@@ -55,8 +55,10 @@ import java.nio.channels.spi.SelectorProvider;
* @author Michael Koch
*/
public final class DatagramChannelImpl extends DatagramChannel
+ implements VMChannelOwner
{
private NIODatagramSocket socket;
+ private VMChannel channel;
/**
* Indicates whether this channel initiated whatever operation
@@ -64,6 +66,16 @@ public final class DatagramChannelImpl extends DatagramChannel
*/
private boolean inChannelOperation;
+ protected DatagramChannelImpl (SelectorProvider provider)
+ throws IOException
+ {
+ super (provider);
+ socket = new NIODatagramSocket (new PlainDatagramSocketImpl(), this);
+ channel = new VMChannel();
+ channel.initSocket(false);
+ configureBlocking(true);
+ }
+
/**
* Indicates whether our datagram socket should ignore whether
* we are set to non-blocking mode. Certain operations on our
@@ -85,14 +97,6 @@ public final class DatagramChannelImpl extends DatagramChannel
inChannelOperation = b;
}
- protected DatagramChannelImpl (SelectorProvider provider)
- throws IOException
- {
- super (provider);
- socket = new NIODatagramSocket (new PlainDatagramSocketImpl(), this);
- configureBlocking(true);
- }
-
public DatagramSocket socket ()
{
return socket;
@@ -101,13 +105,13 @@ public final class DatagramChannelImpl extends DatagramChannel
protected void implCloseSelectableChannel ()
throws IOException
{
- socket.close ();
+ channel.close();
}
protected void implConfigureBlocking (boolean blocking)
throws IOException
{
- socket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
+ channel.setBlocking(blocking);
}
public DatagramChannel connect (SocketAddress remote)
@@ -116,20 +120,34 @@ public final class DatagramChannelImpl extends DatagramChannel
if (!isOpen())
throw new ClosedChannelException();
- socket.connect (remote);
+ try
+ {
+ channel.connect((InetSocketAddress) remote, 0);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new IOException("unsupported socked address type");
+ }
return this;
}
public DatagramChannel disconnect ()
throws IOException
{
- socket.disconnect ();
+ channel.disconnect();
return this;
}
- public boolean isConnected ()
+ public boolean isConnected()
{
- return socket.isConnected ();
+ try
+ {
+ return channel.getPeerAddress() != null;
+ }
+ catch (IOException ioe)
+ {
+ return false;
+ }
}
public int write (ByteBuffer src)
@@ -138,7 +156,7 @@ public final class DatagramChannelImpl extends DatagramChannel
if (!isConnected ())
throw new NotYetConnectedException ();
- return send (src, socket.getRemoteSocketAddress());
+ return channel.write(src);
}
public long write (ByteBuffer[] srcs, int offset, int length)
@@ -152,13 +170,11 @@ public final class DatagramChannelImpl extends DatagramChannel
|| (length < 0)
|| (length > (srcs.length - offset)))
throw new IndexOutOfBoundsException();
-
- long result = 0;
-
- for (int index = offset; index < offset + length; index++)
- result += write (srcs [index]);
- return result;
+ /* We are connected, meaning we will write these bytes to
+ * the host we connected to, so we don't need to explicitly
+ * give the host. */
+ return channel.writeGathering(srcs, offset, length);
}
public int read (ByteBuffer dst)
@@ -167,9 +183,7 @@ public final class DatagramChannelImpl extends DatagramChannel
if (!isConnected ())
throw new NotYetConnectedException ();
- int remaining = dst.remaining();
- receive (dst);
- return remaining - dst.remaining();
+ return channel.read(dst);
}
public long read (ByteBuffer[] dsts, int offset, int length)
@@ -184,12 +198,8 @@ public final class DatagramChannelImpl extends DatagramChannel
|| (length > (dsts.length - offset)))
throw new IndexOutOfBoundsException();
- long result = 0;
-
- for (int index = offset; index < offset + length; index++)
- result += read (dsts [index]);
-
- return result;
+ /* Likewise, see the comment int write above. */
+ return channel.readScattering(dsts, offset, length);
}
public SocketAddress receive (ByteBuffer dst)
@@ -200,49 +210,12 @@ public final class DatagramChannelImpl extends DatagramChannel
try
{
- DatagramPacket packet;
- int len = dst.remaining();
-
- if (dst.hasArray())
- {
- packet = new DatagramPacket (dst.array(),
- dst.arrayOffset() + dst.position(),
- len);
- }
- else
- {
- packet = new DatagramPacket (new byte [len], len);
- }
-
- boolean completed = false;
-
- try
- {
- begin();
- setInChannelOperation(true);
- socket.receive (packet);
- completed = true;
- }
- finally
- {
- end (completed);
- setInChannelOperation(false);
- }
-
- if (!dst.hasArray())
- {
- dst.put (packet.getData(), packet.getOffset(), packet.getLength());
- }
- else
- {
- dst.position (dst.position() + packet.getLength());
- }
-
- return packet.getSocketAddress();
+ begin();
+ return channel.receive(dst);
}
- catch (SocketTimeoutException e)
+ finally
{
- return null;
+ end(true);
}
}
@@ -252,46 +225,18 @@ public final class DatagramChannelImpl extends DatagramChannel
if (!isOpen())
throw new ClosedChannelException();
- if (target instanceof InetSocketAddress
- && ((InetSocketAddress) target).isUnresolved())
- throw new IOException("Target address not resolved");
-
- byte[] buffer;
- int offset = 0;
- int len = src.remaining();
+ if (!(target instanceof InetSocketAddress))
+ throw new IOException("can only send to inet socket addresses");
- if (src.hasArray())
- {
- buffer = src.array();
- offset = src.arrayOffset() + src.position();
- }
- else
- {
- buffer = new byte [len];
- src.get (buffer);
- }
-
- DatagramPacket packet = new DatagramPacket (buffer, offset, len, target);
-
- boolean completed = false;
- try
- {
- begin();
- setInChannelOperation(true);
- socket.send(packet);
- completed = true;
- }
- finally
- {
- end (completed);
- setInChannelOperation(false);
- }
-
- if (src.hasArray())
- {
- src.position (src.position() + len);
- }
+ InetSocketAddress dst = (InetSocketAddress) target;
+ if (dst.isUnresolved())
+ throw new IOException("Target address not resolved");
- return len;
+ return channel.send(src, dst);
+ }
+
+ public VMChannel getVMChannel()
+ {
+ return channel;
}
}
diff --git a/libjava/classpath/gnu/java/nio/DatagramChannelSelectionKey.java b/libjava/classpath/gnu/java/nio/DatagramChannelSelectionKey.java
index 698e07e348f..f192e5002d4 100644
--- a/libjava/classpath/gnu/java/nio/DatagramChannelSelectionKey.java
+++ b/libjava/classpath/gnu/java/nio/DatagramChannelSelectionKey.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.nio;
+import java.io.IOException;
import java.nio.channels.spi.AbstractSelectableChannel;
/**
@@ -52,10 +53,16 @@ public final class DatagramChannelSelectionKey
super (channel, selector);
}
+ // FIXME don't use file descriptor integers
public int getNativeFD()
{
- NIODatagramSocket socket =
- (NIODatagramSocket) ((DatagramChannelImpl) ch).socket();
- return socket.getPlainDatagramSocketImpl().getNativeFD();
+ try
+ {
+ return ((DatagramChannelImpl) ch).getVMChannel().getState().getNativeFD();
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalStateException(ioe);
+ }
}
}
diff --git a/libjava/classpath/gnu/java/nio/EpollSelectionKeyImpl.java b/libjava/classpath/gnu/java/nio/EpollSelectionKeyImpl.java
new file mode 100644
index 00000000000..11113f3975c
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/EpollSelectionKeyImpl.java
@@ -0,0 +1,122 @@
+/* EpollSelectionKeyImpl.java -- selection key for the epoll selector.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class EpollSelectionKeyImpl extends AbstractSelectionKey
+{
+ final int fd;
+ private final EpollSelectorImpl selector;
+ private final SelectableChannel channel;
+ int interestOps;
+ int selectedOps;
+ int key;
+ boolean valid;
+ boolean cancelled;
+
+ EpollSelectionKeyImpl(EpollSelectorImpl selector,
+ SelectableChannel channel, int fd)
+ {
+ this.selector = selector;
+ this.channel = channel;
+ this.fd = fd;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#channel()
+ */
+ public SelectableChannel channel()
+ {
+ return channel;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#interestOps()
+ */
+ public int interestOps()
+ {
+ return interestOps;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#interestOps(int)
+ */
+ public SelectionKey interestOps(int ops)
+ {
+ if (cancelled)
+ throw new CancelledKeyException();
+ if ((ops & ~(channel.validOps())) != 0)
+ throw new IllegalArgumentException("unsupported channel ops");
+ try
+ {
+ selector.epoll_modify(this, ops);
+ interestOps = ops;
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException(ioe);
+ }
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#readyOps()
+ */
+ public int readyOps()
+ {
+ return selectedOps;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#selector()
+ */
+ public Selector selector()
+ {
+ return selector;
+ }
+}
diff --git a/libjava/classpath/gnu/java/nio/EpollSelectorImpl.java b/libjava/classpath/gnu/java/nio/EpollSelectorImpl.java
new file mode 100644
index 00000000000..2b3c9bbb1b6
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/EpollSelectorImpl.java
@@ -0,0 +1,399 @@
+/* EpollSelectorImpl.java -- selector implementation using epoll
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import gnu.classpath.Configuration;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * An implementation of {@link Selector} that uses the epoll event
+ * notification mechanism on GNU/Linux.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class EpollSelectorImpl extends AbstractSelector
+{
+ // XXX is this reasonable? Does it matter?
+ private static final int DEFAULT_EPOLL_SIZE = 128;
+ private static final int sizeof_struct_epoll_event;
+
+ private static final int OP_ACCEPT = SelectionKey.OP_ACCEPT;
+ private static final int OP_CONNECT = SelectionKey.OP_CONNECT;
+ private static final int OP_READ = SelectionKey.OP_READ;
+ private static final int OP_WRITE = SelectionKey.OP_WRITE;
+
+ /** our epoll file descriptor. */
+ private int epoll_fd;
+
+ private final HashMap keys;
+ private Set selectedKeys;
+ private Thread waitingThread;
+ private ByteBuffer events;
+
+ private static final int INITIAL_CAPACITY;
+ private static final int MAX_DOUBLING_CAPACITY;
+ private static final int CAPACITY_INCREMENT;
+
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ System.loadLibrary("javanio");
+
+ if (epoll_supported())
+ sizeof_struct_epoll_event = sizeof_struct();
+ else
+ sizeof_struct_epoll_event = -1;
+
+ INITIAL_CAPACITY = 64 * sizeof_struct_epoll_event;
+ MAX_DOUBLING_CAPACITY = 1024 * sizeof_struct_epoll_event;
+ CAPACITY_INCREMENT = 128 * sizeof_struct_epoll_event;
+ }
+
+ public EpollSelectorImpl(SelectorProvider provider)
+ throws IOException
+ {
+ super(provider);
+ epoll_fd = epoll_create(DEFAULT_EPOLL_SIZE);
+ keys = new HashMap();
+ selectedKeys = null;
+ events = ByteBuffer.allocateDirect(INITIAL_CAPACITY);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#keys()
+ */
+ public Set keys()
+ {
+ return new HashSet(keys.values());
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#select()
+ */
+ public int select() throws IOException
+ {
+ return doSelect(-1);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#select(long)
+ */
+ public int select(long timeout) throws IOException
+ {
+ if (timeout > Integer.MAX_VALUE)
+ throw new IllegalArgumentException("timeout is too large");
+ if (timeout < 0)
+ throw new IllegalArgumentException("invalid timeout");
+ return doSelect((int) timeout);
+ }
+
+ private int doSelect(int timeout) throws IOException
+ {
+ synchronized (keys)
+ {
+ Set cancelledKeys = cancelledKeys();
+ synchronized (cancelledKeys)
+ {
+ for (Iterator it = cancelledKeys.iterator(); it.hasNext(); )
+ {
+ EpollSelectionKeyImpl key = (EpollSelectionKeyImpl) it.next();
+ epoll_delete(epoll_fd, key.fd);
+ key.valid = false;
+ keys.remove(Integer.valueOf(key.fd));
+ it.remove();
+ deregister(key);
+ }
+
+ // Clear out closed channels. The fds are removed from the epoll
+ // fd when closed, so there is no need to remove them manually.
+ for (Iterator it = keys.values().iterator(); it.hasNext(); )
+ {
+ EpollSelectionKeyImpl key = (EpollSelectionKeyImpl) it.next();
+ SelectableChannel ch = key.channel();
+ if (ch instanceof VMChannelOwner)
+ {
+ if (!((VMChannelOwner) ch).getVMChannel().getState().isValid())
+ it.remove();
+ }
+ }
+
+ // Don't bother if we have nothing to select.
+ if (keys.isEmpty())
+ return 0;
+
+ int ret;
+ try
+ {
+ begin();
+ waitingThread = Thread.currentThread();
+ ret = epoll_wait(epoll_fd, events, keys.size(), timeout);
+ }
+ finally
+ {
+ Thread.interrupted();
+ waitingThread = null;
+ end();
+ }
+
+ HashSet s = new HashSet(ret);
+ for (int i = 0; i < ret; i++)
+ {
+ events.position(i * sizeof_struct_epoll_event);
+ ByteBuffer b = events.slice();
+ int fd = selected_fd(b);
+ EpollSelectionKeyImpl key
+ = (EpollSelectionKeyImpl) keys.get(Integer.valueOf(fd));
+ if (key == null)
+ throw new IOException("fd was selected, but no key found");
+ key.selectedOps = selected_ops(b) & key.interestOps;
+ s.add(key);
+ }
+
+ reallocateBuffer();
+
+ selectedKeys = s;
+ return ret;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#selectedKeys()
+ */
+ public Set selectedKeys()
+ {
+ if (selectedKeys == null)
+ return Collections.EMPTY_SET;
+ return selectedKeys;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#selectNow()
+ */
+ public int selectNow() throws IOException
+ {
+ return doSelect(0);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#wakeup()
+ */
+ public Selector wakeup()
+ {
+ try
+ {
+ waitingThread.interrupt();
+ }
+ catch (NullPointerException npe)
+ {
+ // Ignored, thrown if we are not in a blocking op.
+ }
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.spi.AbstractSelector#implCloseSelector()
+ */
+ protected void implCloseSelector() throws IOException
+ {
+ VMChannel.close(epoll_fd);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.spi.AbstractSelector#register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object)
+ */
+ protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att)
+ {
+ if (!(ch instanceof VMChannelOwner))
+ throw new IllegalArgumentException("unsupported channel type");
+
+ VMChannel channel = ((VMChannelOwner) ch).getVMChannel();
+ try
+ {
+ int native_fd = channel.getState().getNativeFD();
+ synchronized (keys)
+ {
+ if (keys.containsKey(Integer.valueOf(native_fd)))
+ throw new IllegalArgumentException("channel already registered");
+ EpollSelectionKeyImpl result =
+ new EpollSelectionKeyImpl(this, ch, native_fd);
+ if ((ops & ~(ch.validOps())) != 0)
+ throw new IllegalArgumentException("invalid ops for channel");
+ result.interestOps = ops;
+ result.selectedOps = 0;
+ result.valid = true;
+ result.attach(att);
+ result.key = System.identityHashCode(result);
+ epoll_add(epoll_fd, result.fd, ops);
+ keys.put(Integer.valueOf(native_fd), result);
+ reallocateBuffer();
+ return result;
+ }
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException(ioe);
+ }
+ }
+
+ private void reallocateBuffer()
+ {
+ // Ensure we have enough space for all potential events that may be
+ // returned.
+ if (events.capacity() < keys.size() * sizeof_struct_epoll_event)
+ {
+ int cap = events.capacity();
+ if (cap < MAX_DOUBLING_CAPACITY)
+ cap <<= 1;
+ else
+ cap += CAPACITY_INCREMENT;
+ events = ByteBuffer.allocateDirect(cap);
+ }
+ // Ensure that the events buffer is not too large, given the number of
+ // events registered.
+ else if (events.capacity() > keys.size() * sizeof_struct_epoll_event * 2 + 1
+ && events.capacity() > INITIAL_CAPACITY)
+ {
+ int cap = events.capacity() >>> 1;
+ events = ByteBuffer.allocateDirect(cap);
+ }
+ }
+
+ void epoll_modify(EpollSelectionKeyImpl key, int ops) throws IOException
+ {
+ epoll_modify(epoll_fd, key.fd, ops);
+ }
+
+ /**
+ * Tell if epoll is supported by this system, and support was compiled in.
+ *
+ * @return True if this system supports event notification with epoll.
+ */
+ public static native boolean epoll_supported();
+
+
+ /**
+ * Returns the size of `struct epoll_event'.
+ *
+ * @return The size of `struct epoll_event'.
+ */
+ private static native int sizeof_struct();
+
+
+ /**
+ * Open a new epoll file descriptor.
+ *
+ * @param size The size hint for the new epoll descriptor.
+ * @return The new file descriptor integer.
+ * @throws IOException If allocating a new epoll descriptor fails.
+ */
+ private static native int epoll_create(int size) throws IOException;
+
+ /**
+ * Add a file descriptor to this selector.
+ *
+ * @param efd The epoll file descriptor.
+ * @param fd The file descriptor to add (or modify).
+ * @param ops The interest opts.
+ */
+ private static native void epoll_add(int efd, int fd, int ops)
+ throws IOException;
+
+ /**
+ * Modify the interest ops of the key selecting for the given FD.
+ *
+ * @param efd The epoll file descriptor.
+ * @param fd The file descriptor to modify.
+ * @param ops The ops.
+ * @throws IOException
+ */
+ private static native void epoll_modify(int efd, int fd, int ops)
+ throws IOException;
+
+ /**
+ * Remove a file descriptor from this selector.
+ *
+ * @param efd The epoll file descriptor.
+ * @param fd The file descriptor.
+ * @throws IOException
+ */
+ private static native void epoll_delete(int efd, int fd) throws IOException;
+
+ /**
+ * Select events.
+ *
+ * @param efd The epoll file descriptor.
+ * @param state The buffer to hold selected events.
+ * @param n The number of events that may be put in `state'.
+ * @param timeout The timeout.
+ * @return The number of events selected.
+ * @throws IOException
+ */
+ private static native int epoll_wait(int efd, ByteBuffer state, int n, int timeout)
+ throws IOException;
+
+ /**
+ * Fetch the fd value from a selected struct epoll_event.
+ *
+ * @param struct The direct buffer holding the struct.
+ * @return The fd value.
+ */
+ private static native int selected_fd(ByteBuffer struct);
+
+ /**
+ * Fetch the enabled operations from a selected struct epoll_event.
+ *
+ * @param struct The direct buffer holding the struct.
+ * @return The selected operations.
+ */
+ private static native int selected_ops(ByteBuffer struct);
+}
diff --git a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java b/libjava/classpath/gnu/java/nio/FileChannelImpl.java
index ed439e141ef..41912405078 100644
--- a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java
+++ b/libjava/classpath/gnu/java/nio/FileChannelImpl.java
@@ -36,7 +36,7 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.java.nio.channels;
+package gnu.java.nio;
import gnu.classpath.Configuration;
import gnu.java.nio.FileLockImpl;
@@ -74,11 +74,11 @@ public final class FileChannelImpl extends FileChannel
public static final int SYNC = 16;
public static final int DSYNC = 32;
- public static FileChannelImpl in;
- public static FileChannelImpl out;
- public static FileChannelImpl err;
+ public static final FileChannelImpl in;
+ public static final FileChannelImpl out;
+ public static final FileChannelImpl err;
- private static native void init();
+ //private static native void init();
static
{
@@ -87,22 +87,45 @@ public final class FileChannelImpl extends FileChannel
System.loadLibrary("javanio");
}
- init();
+ //init();
- in = new FileChannelImpl(0, READ);
- out = new FileChannelImpl(1, WRITE);
- err = new FileChannelImpl(2, WRITE);
+ FileChannelImpl ch = null;
+ try
+ {
+ ch = new FileChannelImpl(VMChannel.getStdin(), READ);
+ }
+ catch (IOException ioe)
+ {
+ throw new Error(ioe);
+ }
+ in = ch;
+
+ ch = null;
+ try
+ {
+ ch = new FileChannelImpl(VMChannel.getStdout(), WRITE);
+ }
+ catch (IOException ioe)
+ {
+ throw new Error(ioe);
+ }
+ out = ch;
+
+ ch = null;
+ try
+ {
+ ch = new FileChannelImpl(VMChannel.getStderr(), WRITE);
+ }
+ catch (IOException ioe)
+ {
+ throw new Error(ioe);
+ }
+ err = ch;
}
/**
* This is the actual native file descriptor value
*/
- // System's notion of file descriptor. It might seem redundant to
- // initialize this given that it is reassigned in the constructors.
- // However, this is necessary because if open() throws an exception
- // we want to make sure this has the value -1. This is the most
- // efficient way to accomplish that.
- private int fd = -1;
private VMChannel ch;
private int mode;
@@ -113,19 +136,19 @@ public final class FileChannelImpl extends FileChannel
/* This is a static factory method, so that VM implementors can decide
* substitute subclasses of FileChannelImpl. */
public static FileChannelImpl create(File file, int mode)
- throws FileNotFoundException
+ throws IOException
{
return new FileChannelImpl(file, mode);
}
private FileChannelImpl(File file, int mode)
- throws FileNotFoundException
+ throws IOException
{
String path = file.getPath();
description = path;
- fd = open (path, mode);
this.mode = mode;
- this.ch = VMChannel.getVMChannel(this);
+ this.ch = new VMChannel();
+ ch.openFile(path, mode);
// First open the file and then check if it is a a directory
// to avoid race condition.
@@ -133,11 +156,11 @@ public final class FileChannelImpl extends FileChannel
{
try
{
- close();
+ close();
}
catch (IOException e)
{
- /* ignore it */
+ /* ignore it */
}
throw new FileNotFoundException(description + " is a directory");
@@ -153,49 +176,59 @@ public final class FileChannelImpl extends FileChannel
*
* @param mode READ or WRITE
*/
- FileChannelImpl (int fd, int mode)
+ FileChannelImpl (VMChannel ch, int mode)
{
- this.fd = fd;
this.mode = mode;
- this.description = "descriptor(" + fd + ")";
- this.ch = VMChannel.getVMChannel(this);
+ this.description = "descriptor(" + ch.getState() + ")";
+ this.ch = ch;
}
- private native int open (String path, int mode) throws FileNotFoundException;
+ public int available() throws IOException
+ {
+ return ch.available();
+ }
+
+ private long implPosition() throws IOException
+ {
+ return ch.position();
+ }
- public native int available () throws IOException;
- private native long implPosition () throws IOException;
- private native void seek (long newPosition) throws IOException;
- private native void implTruncate (long size) throws IOException;
+ private void seek(long newPosition) throws IOException
+ {
+ ch.seek(newPosition);
+ }
+
+ private void implTruncate(long size) throws IOException
+ {
+ ch.truncate(size);
+ }
- public native void unlock (long pos, long len) throws IOException;
+ public void unlock(long pos, long len) throws IOException
+ {
+ ch.unlock(pos, len);
+ }
- public native long size () throws IOException;
+ public long size () throws IOException
+ {
+ return ch.size();
+ }
- protected native void implCloseChannel() throws IOException;
+ protected void implCloseChannel() throws IOException
+ {
+ ch.close();
+ }
/**
* Makes sure the Channel is properly closed.
*/
protected void finalize() throws IOException
{
- if (fd != -1)
+ if (ch.getState().isValid())
close();
}
public int read (ByteBuffer dst) throws IOException
{
- /*
- int result;
- byte[] buffer = new byte [dst.remaining ()];
-
- result = read (buffer, 0, buffer.length);
-
- if (result > 0)
- dst.put (buffer, 0, result);
-
- return result;
- */
return ch.read(dst);
}
@@ -212,11 +245,10 @@ public final class FileChannelImpl extends FileChannel
return result;
}
- public native int read ()
- throws IOException;
-
- public native int read (byte[] buffer, int offset, int length)
- throws IOException;
+ public int read() throws IOException
+ {
+ return ch.read();
+ }
public long read (ByteBuffer[] dsts, int offset, int length)
throws IOException
@@ -252,19 +284,16 @@ public final class FileChannelImpl extends FileChannel
return result;
}
- public native void write (byte[] buffer, int offset, int length)
- throws IOException;
-
- public native void write (int b) throws IOException;
+ public void write (int b) throws IOException
+ {
+ ch.write(b);
+ }
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
return ch.writeGathering(srcs, offset, length);
}
-
- public native MappedByteBuffer mapImpl (char mode, long position, int size)
- throws IOException;
public MappedByteBuffer map (FileChannel.MapMode mode,
long position, long size)
@@ -291,7 +320,7 @@ public final class FileChannelImpl extends FileChannel
if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
throw new IllegalArgumentException ("position: " + position
+ ", size: " + size);
- return mapImpl(nmode, position, (int) size);
+ return ch.map(nmode, position, (int) size);
}
/**
@@ -302,11 +331,9 @@ public final class FileChannelImpl extends FileChannel
if (!isOpen ())
throw new ClosedChannelException ();
- force ();
+ ch.flush(metaData);
}
- private native void force ();
-
// like transferTo, but with a count of less than 2Gbytes
private int smallTransferTo (long position, int count,
WritableByteChannel target)
@@ -453,7 +480,7 @@ public final class FileChannelImpl extends FileChannel
try
{
begin();
- boolean lockable = lock(position, size, shared, false);
+ boolean lockable = ch.lock(position, size, shared, false);
completed = true;
return (lockable
? new FileLockImpl(this, position, size, shared)
@@ -464,14 +491,6 @@ public final class FileChannelImpl extends FileChannel
end(completed);
}
}
-
- /** Try to acquire a lock at the given position and size.
- * On success return true.
- * If wait as specified, block until we can get it.
- * Otherwise return false.
- */
- private native boolean lock(long position, long size,
- boolean shared, boolean wait) throws IOException;
public FileLock lock (long position, long size, boolean shared)
throws IOException
@@ -481,7 +500,7 @@ public final class FileChannelImpl extends FileChannel
boolean completed = false;
try
{
- boolean lockable = lock(position, size, shared, true);
+ boolean lockable = ch.lock(position, size, shared, true);
completed = true;
return (lockable
? new FileLockImpl(this, position, size, shared)
@@ -537,17 +556,17 @@ public final class FileChannelImpl extends FileChannel
public String toString()
{
- return (this.getClass()
- + "[fd=" + fd
- + ",mode=" + mode + ","
- + description + "]");
+ return (super.toString()
+ + "[ fd: " + ch.getState()
+ + "; mode: " + Integer.toOctalString(mode)
+ + "; " + description + " ]");
}
/**
* @return The native file descriptor.
- */
+ * /
public int getNativeFD()
{
return fd;
- }
+ }*/
}
diff --git a/libjava/classpath/gnu/java/nio/FileLockImpl.java b/libjava/classpath/gnu/java/nio/FileLockImpl.java
index 673ca2522df..768906ce973 100644
--- a/libjava/classpath/gnu/java/nio/FileLockImpl.java
+++ b/libjava/classpath/gnu/java/nio/FileLockImpl.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package gnu.java.nio;
-import gnu.java.nio.channels.FileChannelImpl;
-
import java.io.IOException;
import java.nio.channels.FileLock;
diff --git a/libjava/classpath/gnu/java/nio/KqueueSelectionKeyImpl.java b/libjava/classpath/gnu/java/nio/KqueueSelectionKeyImpl.java
new file mode 100644
index 00000000000..2f93c50cc19
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/KqueueSelectionKeyImpl.java
@@ -0,0 +1,189 @@
+/* KqueueSelectionKeyImpl.java -- selection key for kqueue/kevent.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class KqueueSelectionKeyImpl extends AbstractSelectionKey
+{
+ int interestOps;
+ int readyOps;
+ int activeOps = 0;
+ int key;
+ int fd;
+
+ /** The selector we were created for. */
+ private final KqueueSelectorImpl selector;
+
+ /** The channel we are attached to. */
+ private final SelectableChannel channel;
+
+ private final VMChannelOwner natChannel;
+
+ public KqueueSelectionKeyImpl(KqueueSelectorImpl selector,
+ SelectableChannel channel)
+ {
+ this.selector = selector;
+ this.channel = channel;
+ natChannel = (VMChannelOwner) channel;
+ interestOps = 0;
+ readyOps = 0;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#channel()
+ */
+ //@Override
+ public SelectableChannel channel()
+ {
+ return channel;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#interestOps()
+ */
+ //@Override
+ public int interestOps()
+ {
+ return interestOps;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#interestOps(int)
+ */
+ //@Override
+ public SelectionKey interestOps(int ops)
+ {
+ if (!isValid())
+ throw new IllegalStateException("key is invalid");
+ if ((ops & ~channel.validOps()) != 0)
+ throw new IllegalArgumentException("channel does not support all operations");
+
+ selector.setInterestOps(this, ops);
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#readyOps()
+ */
+ //@Override
+ public int readyOps()
+ {
+ return readyOps;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#selector()
+ */
+ //@Override
+ public Selector selector()
+ {
+ return selector;
+ }
+
+ public String toString()
+ {
+ if (!isValid())
+ return super.toString() + " [ fd: " + fd + " <<invalid>> ]";
+ return super.toString() + " [ fd: " + fd + " interest ops: {"
+ + ((interestOps & OP_ACCEPT) != 0 ? " OP_ACCEPT" : "")
+ + ((interestOps & OP_CONNECT) != 0 ? " OP_CONNECT" : "")
+ + ((interestOps & OP_READ) != 0 ? " OP_READ" : "")
+ + ((interestOps & OP_WRITE) != 0 ? " OP_WRITE" : "")
+ + " }; ready ops: {"
+ + ((readyOps & OP_ACCEPT) != 0 ? " OP_ACCEPT" : "")
+ + ((readyOps & OP_CONNECT) != 0 ? " OP_CONNECT" : "")
+ + ((readyOps & OP_READ) != 0 ? " OP_READ" : "")
+ + ((readyOps & OP_WRITE) != 0 ? " OP_WRITE" : "")
+ + " } ]";
+ }
+
+ public int hashCode()
+ {
+ return fd;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof KqueueSelectionKeyImpl))
+ return false;
+ KqueueSelectionKeyImpl that = (KqueueSelectionKeyImpl) o;
+ return that.fd == this.fd && that.channel.equals(this.channel);
+ }
+
+
+ boolean isReadActive()
+ {
+ return (activeOps & (OP_READ | OP_ACCEPT)) != 0;
+ }
+
+ boolean isReadInterested()
+ {
+ return (interestOps & (OP_READ | OP_ACCEPT)) != 0;
+ }
+
+ boolean isWriteActive()
+ {
+ return (activeOps & (OP_WRITE | OP_CONNECT)) != 0;
+ }
+
+ boolean isWriteInterested()
+ {
+ return (interestOps & (OP_WRITE | OP_CONNECT)) != 0;
+ }
+
+ boolean needCommitRead()
+ {
+ return isReadActive() == (!isReadInterested());
+ }
+
+ boolean needCommitWrite()
+ {
+ return isWriteActive() == (!isWriteInterested());
+ }
+}
diff --git a/libjava/classpath/gnu/java/nio/KqueueSelectorImpl.java b/libjava/classpath/gnu/java/nio/KqueueSelectorImpl.java
new file mode 100644
index 00000000000..34ca1dc596d
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/KqueueSelectorImpl.java
@@ -0,0 +1,527 @@
+/* KqueueSelectorImpl.java -- Selector for systems with kqueue event notification.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A {@link Selector} implementation that uses the <code>kqueue</code>
+ * event notification facility.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class KqueueSelectorImpl extends AbstractSelector
+{
+ // Prepended underscore to field name to make it distinct
+ // from the method with the similar name.
+ private static final int _sizeof_struct_kevent;
+
+ private static final int MAX_DOUBLING_CAPACITY = 16384;
+ private static final int CAP_INCREMENT = 1024;
+ private static final int INITIAL_CAPACITY;
+
+ static
+ {
+ try
+ {
+ System.loadLibrary("javanio");
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ }
+
+ if (kqueue_supported ())
+ _sizeof_struct_kevent = sizeof_struct_kevent();
+ else
+ _sizeof_struct_kevent = -1;
+ INITIAL_CAPACITY = 16 * _sizeof_struct_kevent;
+ }
+
+ /**
+ * Tell if kqueue-based selectors are supported on this system.
+ *
+ * @return True if this system has kqueue support, and support for it was
+ * compiled in to Classpath.
+ */
+ public static native boolean kqueue_supported();
+
+ /* Our native file descriptor. */
+ private int kq;
+
+ private HashMap/*<Integer,KqueueSelectionKeyImpl>*/ keys;
+ private HashSet/*<KqueueSelectionKeyImpl>*/ selected;
+ private Thread blockedThread;
+ private ByteBuffer events;
+
+ private static final int OP_ACCEPT = SelectionKey.OP_ACCEPT;
+ private static final int OP_CONNECT = SelectionKey.OP_CONNECT;
+ private static final int OP_READ = SelectionKey.OP_READ;
+ private static final int OP_WRITE = SelectionKey.OP_WRITE;
+
+ public KqueueSelectorImpl(SelectorProvider provider) throws IOException
+ {
+ super(provider);
+ kq = implOpen();
+ keys = new HashMap/*<KqueueSelectionKeyImpl>*/();
+ events = ByteBuffer.allocateDirect(INITIAL_CAPACITY);
+ }
+
+ protected void implCloseSelector() throws IOException
+ {
+ implClose(kq);
+ kq = -1;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#keys()
+ */
+ public Set keys()
+ {
+ if (!isOpen())
+ throw new ClosedSelectorException();
+
+ return new HashSet(keys.values());
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#select()
+ */
+ public int select() throws IOException
+ {
+ return doSelect(-1);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#select(long)
+ */
+ public int select(long timeout) throws IOException
+ {
+ if (timeout == 0)
+ timeout = -1;
+ return doSelect(timeout);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#selectedKeys()
+ */
+ public Set selectedKeys()
+ {
+ if (!isOpen())
+ throw new ClosedSelectorException();
+
+ return selected;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#selectNow()
+ */
+ public int selectNow() throws IOException
+ {
+ return doSelect(0);
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.Selector#wakeup()
+ */
+ public Selector wakeup()
+ {
+ if (blockedThread != null)
+ blockedThread.interrupt();
+ return this;
+ }
+
+ public String toString()
+ {
+ return super.toString() + " [ fd: " + kq + " ]";
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof KqueueSelectorImpl))
+ return false;
+
+ return ((KqueueSelectorImpl) o).kq == kq;
+ }
+
+ int doSelect(long timeout) throws IOException
+ {
+ Set cancelled = cancelledKeys();
+ synchronized (cancelled)
+ {
+ synchronized (keys)
+ {
+ for (Iterator it = cancelled.iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ key.interestOps = 0;
+ }
+
+ int events_size = (2 * _sizeof_struct_kevent) * keys.size();
+ int num_events = 0;
+
+ for (Iterator it = keys.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) e.getValue();
+
+ SelectableChannel ch = key.channel();
+ if (ch instanceof VMChannelOwner)
+ {
+ if (!((VMChannelOwner) ch).getVMChannel().getState().isValid())
+ {
+ // closed channel; removed from kqueue automatically.
+ it.remove();
+ continue;
+ }
+ }
+
+ // If this key is registering a read filter, add it to the buffer.
+ if (key.needCommitRead())
+ {
+ kevent_set(events, num_events, key.fd,
+ key.interestOps & (OP_READ | OP_ACCEPT),
+ key.activeOps & (OP_READ | OP_ACCEPT), key.key);
+ num_events++;
+ }
+
+ // If this key is registering a write filter, add it to the buffer.
+ if (key.needCommitWrite())
+ {
+ kevent_set(events, num_events, key.fd,
+ key.interestOps & (OP_WRITE | OP_CONNECT),
+ key.activeOps & (OP_WRITE | OP_CONNECT), key.key);
+ num_events++;
+ }
+ }
+ events.rewind().limit(events.capacity());
+
+ //System.out.println("dump of keys to select:");
+ //dump_selection_keys(events.duplicate());
+
+ int n = 0;
+ try
+ {
+ //System.out.println("[" + kq + "] kevent enter selecting from " + keys.size());
+ begin();
+ blockedThread = Thread.currentThread();
+ if (blockedThread.isInterrupted())
+ timeout = 0;
+ n = kevent(kq, events, num_events,
+ events.capacity() / _sizeof_struct_kevent, timeout);
+ }
+ finally
+ {
+ end();
+ blockedThread = null;
+ Thread.interrupted();
+ //System.out.println("[" + kq + "kevent exit selected " + n);
+ }
+
+ //System.out.println("dump of keys selected:");
+ //dump_selection_keys((ByteBuffer) events.duplicate().limit(n * _sizeof_struct_kevent));
+
+ // Commit the operations we've just added in the call to kevent.
+ for (Iterator it = keys.values().iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ key.activeOps = key.interestOps;
+ }
+
+ selected = new HashSet/*<KqueueSelectionKeyImpl>*/(n);
+ int x = 0;
+ for (int i = 0; i < n; i++)
+ {
+ events.position(x).limit(x + _sizeof_struct_kevent);
+ x += _sizeof_struct_kevent;
+ int y = fetch_key(events.slice());
+ KqueueSelectionKeyImpl key =
+ (KqueueSelectionKeyImpl) keys.get(new Integer(y));
+
+ if (key == null)
+ {
+ System.out.println("WARNING! no key found for selected key " + y);
+ continue;
+ }
+ // Keys that have been cancelled may be returned here; don't
+ // add them to the selected set.
+ if (!key.isValid())
+ continue;
+ key.readyOps = ready_ops(events.slice(), key.interestOps);
+ selected.add(key);
+ }
+
+ // Finally, remove the cancelled keys.
+ for (Iterator it = cancelled.iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ keys.remove(new Integer(key.key));
+ deregister(key);
+ it.remove();
+ }
+
+ reallocateBuffer();
+
+ return selected.size();
+ }
+ }
+ }
+
+ protected SelectionKey register(AbstractSelectableChannel channel,
+ int interestOps,
+ Object attachment)
+ {
+ int native_fd = -1;
+ try
+ {
+ if (channel instanceof VMChannelOwner)
+ native_fd = ((VMChannelOwner) channel).getVMChannel()
+ .getState().getNativeFD();
+ else
+ throw new IllegalArgumentException("cannot handle channel type " +
+ channel.getClass().getName());
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("channel is closed or invalid");
+ }
+
+ KqueueSelectionKeyImpl result = new KqueueSelectionKeyImpl(this, channel);
+ result.interestOps = interestOps;
+ result.attach(attachment);
+ result.fd = native_fd;
+ result.key = System.identityHashCode(result);
+ synchronized (keys)
+ {
+ while (keys.containsKey(new Integer(result.key)))
+ result.key++;
+ keys.put(new Integer(result.key), result);
+ reallocateBuffer();
+ }
+ return result;
+ }
+
+ void setInterestOps(KqueueSelectionKeyImpl key, int ops)
+ {
+ synchronized (keys)
+ {
+ key.interestOps = ops;
+ }
+ }
+
+ /**
+ * Reallocate the events buffer. This is the destination buffer for
+ * events returned by kevent. This method will:
+ *
+ * * Grow the buffer if there is insufficent space for all registered
+ * events.
+ * * Shrink the buffer if it is more than twice the size needed.
+ *
+ */
+ private void reallocateBuffer()
+ {
+ synchronized (keys)
+ {
+ if (events.capacity() < (2 * _sizeof_struct_kevent) * keys.size())
+ {
+ int cap = events.capacity();
+ if (cap >= MAX_DOUBLING_CAPACITY)
+ cap += CAP_INCREMENT;
+ else
+ cap = cap << 1;
+
+ events = ByteBuffer.allocateDirect(cap);
+ }
+ else if (events.capacity() > 4 * (_sizeof_struct_kevent) * keys.size() + 1
+ && events.capacity() > INITIAL_CAPACITY)
+ {
+ int cap = events.capacity();
+ cap = cap >>> 1;
+ events = ByteBuffer.allocateDirect(cap);
+ }
+ }
+ }
+
+ //synchronized void updateOps(KqueueSelectionKeyImpl key, int interestOps)
+ //{
+ // updateOps(key, interestOps, 0, false);
+ //}
+
+ /*void updateOps(KqueueSelectionKeyImpl key, int interestOps,
+ int activeOps, int fd)
+ {
+ //System.out.println(">> updating kqueue selection key:");
+ //dump_selection_keys(key.nstate.duplicate());
+ //System.out.println("<<");
+ synchronized (keys)
+ {
+ kevent_set(key.nstate, fd, interestOps, activeOps, key.key);
+ }
+ //System.out.println(">> updated kqueue selection key:");
+ //dump_selection_keys(key.nstate.duplicate());
+ //System.out.println("<<");
+ }*/
+
+ private void dump_selection_keys(ByteBuffer keys)
+ {
+ // WARNING! This method is not guaranteed to be portable! This works
+ // on darwin/x86, but the sizeof and offsetof these fields may be
+ // different on other platforms!
+ int i = 0;
+ keys.order(ByteOrder.nativeOrder());
+ while (keys.hasRemaining())
+ {
+ System.out.println("struct kevent { ident: "
+ + Integer.toString(keys.getInt())
+ + " filter: "
+ + Integer.toHexString(keys.getShort() & 0xFFFF)
+ + " flags: "
+ + Integer.toHexString(keys.getShort() & 0xFFFF)
+ + " fflags: "
+ + Integer.toHexString(keys.getInt())
+ + " data: "
+ + Integer.toHexString(keys.getInt())
+ + " udata: "
+ + Integer.toHexString(keys.getInt())
+ + " }");
+ }
+ }
+
+ /**
+ * Return the size of a <code>struct kevent</code> on this system.
+ *
+ * @return The size of <code>struct kevent</code>.
+ */
+ private static native int sizeof_struct_kevent();
+
+ /**
+ * Opens a kqueue descriptor.
+ *
+ * @return The new kqueue descriptor.
+ * @throws IOException If opening fails.
+ */
+ private static native int implOpen() throws IOException;
+
+ /**
+ * Closes the kqueue file descriptor.
+ *
+ * @param kq The kqueue file descriptor.
+ * @throws IOException
+ */
+ private static native void implClose(int kq) throws IOException;
+
+ /**
+ * Initialize the specified native state for the given interest ops.
+ *
+ * @param nstate The native state structures; in this buffer should be
+ * the <code>struct kevent</code>s created for a key.
+ * @param fd The file descriptor. If 0, the native FD is unmodified.
+ * @param interestOps The operations to enable.
+ * @param key A unique key that will reference the associated key later.
+ * @param delete Set to true if this event should be deleted from the
+ * kqueue (if false, this event is added/updated).
+ */
+ private static native void kevent_set(ByteBuffer nstate, int i, int fd,
+ int interestOps, int activeOps, int key);
+
+ /**
+ * Poll for events. The source events are stored in <code>events</code>,
+ * which is also where polled events will be placed.
+ *
+ * @param events The events to poll. This buffer is also the destination
+ * for events read from the queue.
+ * @param nevents The number of events to poll (that is, the number of
+ * events in the <code>events</code> buffer).
+ * @param nout The maximum number of events that may be returned.
+ * @param timeout The timeout. A timeout of -1 returns immediately; a timeout
+ * of 0 waits indefinitely.
+ * @return The number of events read.
+ */
+ private static native int kevent(int kq, ByteBuffer events, int nevents,
+ int nout, long timeout);
+
+ /**
+ * Fetch a polled key from a native state buffer. For each kevent key we
+ * create, we put the native state info (one or more <code>struct
+ * kevent</code>s) in that key's {@link KqueueSelectionKeyImpl#nstate}
+ * buffer, and place the pointer of the key in the <code>udata</code> field
+ * of that structure. This method fetches that pointer from the given
+ * buffer (assumed to be a <code>struct kqueue</code>) and returns it.
+ *
+ * @param nstate The buffer containing the <code>struct kqueue</code> to read.
+ * @return The key object.
+ */
+ private static native int fetch_key(ByteBuffer nstate);
+
+ /**
+ * Fetch the ready ops of the associated native state. That is, this
+ * inspects the first argument as a <code>struct kevent</code>, looking
+ * at its operation (the input is assumed to have been returned via a
+ * previous call to <code>kevent</code>), and translating that to the
+ * appropriate Java bit set, based on the second argument.
+ *
+ * @param nstate The native state.
+ * @param interestOps The enabled operations for the key.
+ * @return The bit set representing the ready operations.
+ */
+ private static native int ready_ops(ByteBuffer nstate, int interestOps);
+
+ /**
+ * Check if kevent returned EV_EOF for a selection key.
+ *
+ * @param nstate The native state.
+ * @return True if the kevent call returned EOF.
+ */
+ private static native boolean check_eof(ByteBuffer nstate);
+}
diff --git a/libjava/classpath/gnu/java/nio/NIOSocket.java b/libjava/classpath/gnu/java/nio/NIOSocket.java
index 4d812bf44ba..060a3a89c1c 100644
--- a/libjava/classpath/gnu/java/nio/NIOSocket.java
+++ b/libjava/classpath/gnu/java/nio/NIOSocket.java
@@ -48,30 +48,33 @@ import java.nio.channels.SocketChannel;
*/
public final class NIOSocket extends Socket
{
- private PlainSocketImpl impl;
private SocketChannelImpl channel;
- protected NIOSocket (PlainSocketImpl impl, SocketChannelImpl channel)
+ protected NIOSocket (SocketChannelImpl channel)
throws IOException
{
- super (impl);
- this.impl = impl;
+ super (new NIOSocketImpl(channel));
this.channel = channel;
}
- public final PlainSocketImpl getPlainSocketImpl()
- {
- return impl;
- }
+ //public final PlainSocketImpl getPlainSocketImpl()
+ //{
+ // return impl;
+ //}
- final void setChannel (SocketChannelImpl channel)
- {
- this.impl = channel.getPlainSocketImpl();
- this.channel = channel;
- }
+ //final void setChannel (SocketChannelImpl channel)
+ //{
+ // this.impl = channel.getPlainSocketImpl();
+ // this.channel = channel;
+ //}
public final SocketChannel getChannel()
{
return channel;
}
+
+ public boolean isConnected()
+ {
+ return channel.isConnected();
+ }
}
diff --git a/libjava/classpath/gnu/java/nio/NIOSocketImpl.java b/libjava/classpath/gnu/java/nio/NIOSocketImpl.java
new file mode 100644
index 00000000000..4b26561a212
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/NIOSocketImpl.java
@@ -0,0 +1,110 @@
+/* NIOSocketImpl.java -- subclass of PlainSocketImpl for NIO.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import gnu.java.net.PlainSocketImpl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class NIOSocketImpl extends PlainSocketImpl
+{
+
+ private final SocketChannelImpl channel;
+
+ NIOSocketImpl(SocketChannelImpl channel) throws IOException
+ {
+ this.channel = channel;
+ impl.getState().setChannelFD(channel.getVMChannel().getState());
+ }
+
+ /* (non-Javadoc)
+ * @see java.net.SocketImpl#getInetAddress()
+ */
+ //@Override
+ protected InetAddress getInetAddress()
+ {
+ try
+ {
+ return channel.getVMChannel().getPeerAddress().getAddress();
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+ catch (NullPointerException npe)
+ {
+ // Socket is not connected yet.
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.net.SocketImpl#getPort()
+ */
+ //@Override
+ protected int getPort()
+ {
+ try
+ {
+ return channel.getVMChannel().getPeerAddress().getPort();
+ }
+ catch (IOException ioe)
+ {
+ return -1;
+ }
+ catch (NullPointerException npe)
+ {
+ // Socket is not connected yet.
+ return -1;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.java.net.PlainSocketImpl#create(boolean)
+ */
+ //@Override
+ protected synchronized void create(boolean stream)
+ {
+ // Ignored; the socket has already been created.
+ }
+}
diff --git a/libjava/classpath/gnu/java/nio/PipeImpl.java b/libjava/classpath/gnu/java/nio/PipeImpl.java
index cccaa39885f..8a95b9622ae 100644
--- a/libjava/classpath/gnu/java/nio/PipeImpl.java
+++ b/libjava/classpath/gnu/java/nio/PipeImpl.java
@@ -46,22 +46,21 @@ import java.nio.channels.spi.SelectorProvider;
class PipeImpl extends Pipe
{
public static final class SourceChannelImpl extends Pipe.SourceChannel
+ implements VMChannelOwner
{
- private int native_fd;
private VMChannel vmch;
public SourceChannelImpl (SelectorProvider selectorProvider,
- int native_fd)
+ VMChannel channel)
{
super (selectorProvider);
- this.native_fd = native_fd;
- vmch = VMChannel.getVMChannel(this);
+ vmch = channel;
}
protected final void implCloseSelectableChannel()
throws IOException
{
- throw new Error ("Not implemented");
+ vmch.close();
}
protected void implConfigureBlocking (boolean blocking)
@@ -94,30 +93,29 @@ class PipeImpl extends Pipe
return vmch.readScattering(srcs, offset, len);
}
-
- public final int getNativeFD()
+
+ public VMChannel getVMChannel()
{
- return native_fd;
+ return vmch;
}
}
public static final class SinkChannelImpl extends Pipe.SinkChannel
+ implements VMChannelOwner
{
- private int native_fd;
private VMChannel vmch;
public SinkChannelImpl (SelectorProvider selectorProvider,
- int native_fd)
+ VMChannel channel)
{
super (selectorProvider);
- this.native_fd = native_fd;
- vmch = VMChannel.getVMChannel(this);
+ vmch = channel;
}
protected final void implCloseSelectableChannel()
throws IOException
{
- throw new Error ("Not implemented");
+ vmch.close();
}
protected final void implConfigureBlocking (boolean blocking)
@@ -149,10 +147,10 @@ class PipeImpl extends Pipe
return vmch.writeGathering(srcs, offset, len);
}
-
- public final int getNativeFD()
+
+ public VMChannel getVMChannel()
{
- return native_fd;
+ return vmch;
}
}
@@ -163,7 +161,9 @@ class PipeImpl extends Pipe
throws IOException
{
super();
- VMPipe.init (this, provider);
+ VMChannel[] pipe = VMPipe.pipe();
+ sink = new SinkChannelImpl(provider, pipe[0]);
+ source = new SourceChannelImpl(provider, pipe[1]);
}
public Pipe.SinkChannel sink()
diff --git a/libjava/classpath/gnu/java/nio/SelectionKeyImpl.java b/libjava/classpath/gnu/java/nio/SelectionKeyImpl.java
index 8745377c58f..c927f319644 100644
--- a/libjava/classpath/gnu/java/nio/SelectionKeyImpl.java
+++ b/libjava/classpath/gnu/java/nio/SelectionKeyImpl.java
@@ -106,5 +106,6 @@ public abstract class SelectionKeyImpl extends AbstractSelectionKey
return impl;
}
+ /* @deprecated */
public abstract int getNativeFD();
}
diff --git a/libjava/classpath/gnu/java/nio/SelectorImpl.java b/libjava/classpath/gnu/java/nio/SelectorImpl.java
index d0ec4871367..c08478c9968 100644
--- a/libjava/classpath/gnu/java/nio/SelectorImpl.java
+++ b/libjava/classpath/gnu/java/nio/SelectorImpl.java
@@ -54,8 +54,8 @@ import java.util.Set;
public class SelectorImpl extends AbstractSelector
{
- private Set keys;
- private Set selected;
+ private Set<SelectionKey> keys;
+ private Set<SelectionKey> selected;
/**
* A dummy object whose monitor regulates access to both our
@@ -83,8 +83,8 @@ public class SelectorImpl extends AbstractSelector
{
super (provider);
- keys = new HashSet ();
- selected = new HashSet ();
+ keys = new HashSet<SelectionKey> ();
+ selected = new HashSet<SelectionKey> ();
}
protected void finalize() throws Throwable
@@ -110,7 +110,7 @@ public class SelectorImpl extends AbstractSelector
}
}
- public final Set keys()
+ public final Set<SelectionKey> keys()
{
if (!isOpen())
throw new ClosedSelectorException();
@@ -136,7 +136,7 @@ public class SelectorImpl extends AbstractSelector
{
int[] result;
int counter = 0;
- Iterator it = keys.iterator ();
+ Iterator<SelectionKey> it = keys.iterator ();
// Count the number of file descriptors needed
while (it.hasNext ())
@@ -253,7 +253,7 @@ public class SelectorImpl extends AbstractSelector
selectThread = null;
}
- Iterator it = keys.iterator ();
+ Iterator<SelectionKey> it = keys.iterator ();
while (it.hasNext ())
{
@@ -317,7 +317,7 @@ public class SelectorImpl extends AbstractSelector
}
}
- public final Set selectedKeys()
+ public final Set<SelectionKey> selectedKeys()
{
if (!isOpen())
throw new ClosedSelectorException();
@@ -350,10 +350,10 @@ public class SelectorImpl extends AbstractSelector
private final void deregisterCancelledKeys()
{
- Set ckeys = cancelledKeys ();
+ Set<SelectionKey> ckeys = cancelledKeys ();
synchronized (ckeys)
{
- Iterator it = ckeys.iterator();
+ Iterator<SelectionKey> it = ckeys.iterator();
while (it.hasNext ())
{
diff --git a/libjava/classpath/gnu/java/nio/SelectorProviderImpl.java b/libjava/classpath/gnu/java/nio/SelectorProviderImpl.java
index 47521107e90..56167b69ea8 100644
--- a/libjava/classpath/gnu/java/nio/SelectorProviderImpl.java
+++ b/libjava/classpath/gnu/java/nio/SelectorProviderImpl.java
@@ -37,6 +37,9 @@ exception statement from your version. */
package gnu.java.nio;
+
+import gnu.classpath.SystemProperties;
+
import java.io.IOException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Pipe;
@@ -47,6 +50,11 @@ import java.nio.channels.spi.SelectorProvider;
public class SelectorProviderImpl extends SelectorProvider
{
+ private static final String SELECTOR_IMPL_KQUEUE = "kqueue";
+ private static final String SELECTOR_IMPL_EPOLL = "epoll";
+ private static final String SELECTOR_IMPL = "gnu.java.nio.selectorImpl";
+ private static boolean epoll_failed = false;
+
public SelectorProviderImpl ()
{
}
@@ -66,6 +74,35 @@ public class SelectorProviderImpl extends SelectorProvider
public AbstractSelector openSelector ()
throws IOException
{
+ String selectorImpl = "default";
+ if (KqueueSelectorImpl.kqueue_supported())
+ selectorImpl = SELECTOR_IMPL_KQUEUE;
+ if (EpollSelectorImpl.epoll_supported() && !epoll_failed)
+ selectorImpl = SELECTOR_IMPL_EPOLL;
+ selectorImpl = SystemProperties.getProperty(SELECTOR_IMPL, selectorImpl);
+
+ if (selectorImpl.equals(SELECTOR_IMPL_KQUEUE))
+ return new KqueueSelectorImpl(this);
+
+ if (selectorImpl.equals(SELECTOR_IMPL_EPOLL))
+ {
+ // We jump through these hoops because even though epoll may look
+ // like it's available (sys/epoll.h exists, and you can link against
+ // all the epoll functions) it may not be available in the kernel
+ // (especially 2.4 kernels), meaning you will get ENOSYS at run time.
+ //
+ // Madness!
+ try
+ {
+ return new EpollSelectorImpl(this);
+ }
+ catch (InternalError e)
+ {
+ // epoll_create throws this on ENOSYS.
+ epoll_failed = true;
+ }
+ }
+
return new SelectorImpl (this);
}
diff --git a/libjava/classpath/gnu/java/nio/ServerSocketChannelImpl.java b/libjava/classpath/gnu/java/nio/ServerSocketChannelImpl.java
index c538ea802e1..1e8e0901d7c 100644
--- a/libjava/classpath/gnu/java/nio/ServerSocketChannelImpl.java
+++ b/libjava/classpath/gnu/java/nio/ServerSocketChannelImpl.java
@@ -48,7 +48,9 @@ import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
public final class ServerSocketChannelImpl extends ServerSocketChannel
+ implements VMChannelOwner
{
+ private VMChannel channel;
private NIOServerSocket serverSocket;
private boolean connected;
@@ -56,13 +58,15 @@ public final class ServerSocketChannelImpl extends ServerSocketChannel
throws IOException
{
super (provider);
- serverSocket = new NIOServerSocket (this);
+ serverSocket = new NIOServerSocket(this);
+ channel = serverSocket.getPlainSocketImpl().getVMChannel();
configureBlocking(true);
}
+ // XXX do we need this?
public void finalizer()
{
- if (connected)
+ if (channel.getState().isValid())
{
try
{
@@ -77,12 +81,12 @@ public final class ServerSocketChannelImpl extends ServerSocketChannel
protected void implCloseSelectableChannel () throws IOException
{
connected = false;
- serverSocket.close();
+ channel.close();
}
protected void implConfigureBlocking (boolean blocking) throws IOException
{
- serverSocket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
+ channel.setBlocking(blocking);
}
public SocketChannel accept () throws IOException
@@ -98,27 +102,28 @@ public final class ServerSocketChannelImpl extends ServerSocketChannel
try
{
begin();
- serverSocket.getPlainSocketImpl().setInChannelOperation(true);
- // indicate that a channel is initiating the accept operation
- // so that the socket ignores the fact that we might be in
- // non-blocking mode.
- NIOSocket socket = (NIOSocket) serverSocket.accept();
- completed = true;
- return socket.getChannel();
- }
- catch (SocketTimeoutException e)
- {
- return null;
+ VMChannel client = channel.accept();
+ if (client == null)
+ return null;
+ else
+ {
+ completed = true;
+ return new SocketChannelImpl(provider(), client, false);
+ }
}
finally
{
- serverSocket.getPlainSocketImpl().setInChannelOperation(false);
end (completed);
}
}
- public ServerSocket socket ()
+ public ServerSocket socket()
{
return serverSocket;
}
+
+ public VMChannel getVMChannel()
+ {
+ return channel;
+ }
}
diff --git a/libjava/classpath/gnu/java/nio/ServerSocketChannelSelectionKey.java b/libjava/classpath/gnu/java/nio/ServerSocketChannelSelectionKey.java
index d00c2b7482a..5b510cb6f4d 100644
--- a/libjava/classpath/gnu/java/nio/ServerSocketChannelSelectionKey.java
+++ b/libjava/classpath/gnu/java/nio/ServerSocketChannelSelectionKey.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.nio;
+import java.io.IOException;
import java.nio.channels.spi.AbstractSelectableChannel;
public final class ServerSocketChannelSelectionKey
@@ -49,10 +50,16 @@ public final class ServerSocketChannelSelectionKey
super (channel, selector);
}
+ // FIXME don't use file descriptor integers
public int getNativeFD()
{
- NIOServerSocket socket =
- (NIOServerSocket) ((ServerSocketChannelImpl) ch).socket();
- return socket.getPlainSocketImpl().getNativeFD();
+ try
+ {
+ return ((ServerSocketChannelImpl) ch).getVMChannel().getState().getNativeFD();
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalStateException(ioe);
+ }
}
}
diff --git a/libjava/classpath/gnu/java/nio/SocketChannelImpl.java b/libjava/classpath/gnu/java/nio/SocketChannelImpl.java
index 680eba2f92b..1c563ac097c 100644
--- a/libjava/classpath/gnu/java/nio/SocketChannelImpl.java
+++ b/libjava/classpath/gnu/java/nio/SocketChannelImpl.java
@@ -39,15 +39,20 @@ exception statement from your version. */
package gnu.java.nio;
import gnu.java.net.PlainSocketImpl;
+import gnu.java.net.VMPlainSocketImpl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
+import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ConnectionPendingException;
@@ -61,28 +66,57 @@ import java.nio.channels.UnsupportedAddressTypeException;
import java.nio.channels.spi.SelectorProvider;
public final class SocketChannelImpl extends SocketChannel
+ implements VMChannelOwner
{
- private PlainSocketImpl impl;
+ private VMChannel channel;
+ //private PlainSocketImpl impl;
private NIOSocket socket;
private boolean connectionPending;
+ private boolean connected;
+ private InetSocketAddress connectAddress;
+
+ public SocketChannelImpl(boolean create) throws IOException
+ {
+ // XXX consider adding security check; this is used by
+ // PlainSocketImpl.
+ this(new SelectorProviderImpl(), create);
+ }
+
+ public SocketChannelImpl(VMChannel channel) throws IOException
+ {
+ this(new SelectorProviderImpl(), channel, false);
+ }
+
+ SocketChannelImpl(SelectorProvider provider) throws IOException
+ {
+ this(provider, true);
+ }
- SocketChannelImpl (SelectorProvider provider)
+ SocketChannelImpl(SelectorProvider provider, boolean create)
+ throws IOException
+ {
+ this(provider, new VMChannel(), create);
+ }
+
+ SocketChannelImpl(SelectorProvider provider, VMChannel channel, boolean create)
throws IOException
{
super (provider);
- impl = new PlainSocketImpl();
- socket = new NIOSocket (impl, this);
+ this.channel = channel;
+ if (create)
+ channel.initSocket(true);
+ socket = new NIOSocket(this);
configureBlocking(true);
}
- SocketChannelImpl (SelectorProvider provider,
+ /*SocketChannelImpl (SelectorProvider provider,
NIOSocket socket)
throws IOException
{
super (provider);
this.impl = socket.getPlainSocketImpl();
this.socket = socket;
- }
+ }*/
public void finalizer()
{
@@ -98,23 +132,28 @@ public final class SocketChannelImpl extends SocketChannel
}
}
- PlainSocketImpl getPlainSocketImpl()
- {
- return impl;
- }
+ //PlainSocketImpl getPlainSocketImpl()
+ //{
+ // return null; // XXX
+ //}
- protected void implCloseSelectableChannel () throws IOException
+ protected void implCloseSelectableChannel() throws IOException
{
- socket.close();
+ channel.close();
}
protected void implConfigureBlocking (boolean blocking) throws IOException
{
- socket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
+ channel.setBlocking(blocking);
}
public boolean connect (SocketAddress remote) throws IOException
{
+ return connect(remote, 0);
+ }
+
+ public boolean connect (SocketAddress remote, int timeout) throws IOException
+ {
if (!isOpen())
throw new ClosedChannelException();
@@ -126,79 +165,52 @@ public final class SocketChannelImpl extends SocketChannel
if (!(remote instanceof InetSocketAddress))
throw new UnsupportedAddressTypeException();
+
+ connectAddress = (InetSocketAddress) remote;
- if (((InetSocketAddress) remote).isUnresolved())
+ if (connectAddress.isUnresolved())
throw new UnresolvedAddressException();
- try
- {
- socket.getPlainSocketImpl().setInChannelOperation(true);
- // indicate that a channel is initiating the accept operation
- // so that the socket ignores the fact that we might be in
- // non-blocking mode.
-
- if (isBlocking())
- {
- // Do blocking connect.
- socket.connect (remote);
- return true;
- }
-
- // Do non-blocking connect.
- try
- {
- socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
- return true;
- }
- catch (SocketTimeoutException e)
- {
- connectionPending = true;
- return false;
- }
- }
- finally
- {
- socket.getPlainSocketImpl().setInChannelOperation(false);
- }
+ connected = channel.connect(connectAddress, timeout);
+ connectionPending = !connected;
+ return connected;
}
-
- public boolean finishConnect ()
+
+ public boolean finishConnect()
throws IOException
{
if (!isOpen())
throw new ClosedChannelException();
-
- if (!isConnected() && !connectionPending)
- throw new NoConnectionPendingException();
-
- if (isConnected())
- return true;
- // FIXME: Handle blocking/non-blocking mode.
-
- Selector selector = provider().openSelector();
- register(selector, SelectionKey.OP_CONNECT);
-
- if (isBlocking())
+ InetSocketAddress remote = channel.getPeerAddress();
+ if (remote != null)
{
- selector.select(); // blocking until channel is connected.
connectionPending = false;
return true;
}
-
- int ready = selector.selectNow(); // non-blocking
- if (ready == 1)
- {
- connectionPending = false;
- return true;
- }
-
+
+ if (!connectionPending)
+ throw new NoConnectionPendingException();
+
return false;
}
- public boolean isConnected ()
+ public boolean isConnected()
{
- return socket.isConnected();
+ // Wait until finishConnect is called before transitioning to
+ // connected.
+ if (connectionPending)
+ return false;
+ try
+ {
+ InetSocketAddress remote = channel.getPeerAddress();
+ return remote != null;
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace(System.out);
+ return false;
+ }
}
public boolean isConnectionPending ()
@@ -216,52 +228,7 @@ public final class SocketChannelImpl extends SocketChannel
if (!isConnected())
throw new NotYetConnectedException();
- byte[] data;
- int offset = 0;
- InputStream input = socket.getInputStream();
- int available = input.available();
- int len = dst.remaining();
-
- if ((! isBlocking()) && available == 0)
- return 0;
-
- if (dst.hasArray())
- {
- offset = dst.arrayOffset() + dst.position();
- data = dst.array();
- }
- else
- {
- data = new byte [len];
- }
-
- int readBytes = 0;
- boolean completed = false;
-
- try
- {
- begin();
- socket.getPlainSocketImpl().setInChannelOperation(true);
- readBytes = input.read (data, offset, len);
- completed = true;
- }
- finally
- {
- end (completed);
- socket.getPlainSocketImpl().setInChannelOperation(false);
- }
-
- if (readBytes > 0)
- if (dst.hasArray())
- {
- dst.position (dst.position() + readBytes);
- }
- else
- {
- dst.put (data, offset, readBytes);
- }
-
- return readBytes;
+ return channel.read(dst);
}
public long read (ByteBuffer[] dsts, int offset, int length)
@@ -275,61 +242,19 @@ public final class SocketChannelImpl extends SocketChannel
|| (length < 0)
|| (length > (dsts.length - offset)))
throw new IndexOutOfBoundsException();
-
- long readBytes = 0;
-
- for (int index = offset; index < length; index++)
- readBytes += read (dsts [index]);
-
- return readBytes;
+
+ return channel.readScattering(dsts, offset, length);
}
- public int write (ByteBuffer src)
- throws IOException
+ public int write(ByteBuffer src) throws IOException
{
if (!isConnected())
throw new NotYetConnectedException();
-
- byte[] data;
- int offset = 0;
- int len = src.remaining();
-
- if (!src.hasArray())
- {
- data = new byte [len];
- src.get (data, 0, len);
- }
- else
- {
- offset = src.arrayOffset() + src.position();
- data = src.array();
- }
- OutputStream output = socket.getOutputStream();
- boolean completed = false;
-
- try
- {
- begin();
- socket.getPlainSocketImpl().setInChannelOperation(true);
- output.write (data, offset, len);
- completed = true;
- }
- finally
- {
- end (completed);
- socket.getPlainSocketImpl().setInChannelOperation(false);
- }
-
- if (src.hasArray())
- {
- src.position (src.position() + len);
- }
-
- return len;
+ return channel.write(src);
}
- public long write (ByteBuffer[] srcs, int offset, int length)
+ public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if (!isConnected())
@@ -340,12 +265,13 @@ public final class SocketChannelImpl extends SocketChannel
|| (length < 0)
|| (length > (srcs.length - offset)))
throw new IndexOutOfBoundsException();
-
- long writtenBytes = 0;
-
- for (int index = offset; index < length; index++)
- writtenBytes += write (srcs [index]);
- return writtenBytes;
+ return channel.writeGathering(srcs, offset, length);
+ }
+
+ public VMChannel getVMChannel()
+ {
+ // XXX security check?
+ return channel;
}
}
diff --git a/libjava/classpath/gnu/java/nio/SocketChannelSelectionKey.java b/libjava/classpath/gnu/java/nio/SocketChannelSelectionKey.java
index 75b4dfd87e5..9ceebdec90f 100644
--- a/libjava/classpath/gnu/java/nio/SocketChannelSelectionKey.java
+++ b/libjava/classpath/gnu/java/nio/SocketChannelSelectionKey.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.nio;
+import java.io.IOException;
import java.nio.channels.spi.AbstractSelectableChannel;
public final class SocketChannelSelectionKey
@@ -49,10 +50,16 @@ public final class SocketChannelSelectionKey
super (channel, selector);
}
+ // FIXME don't use file descriptor integers
public int getNativeFD()
{
- NIOSocket socket =
- (NIOSocket) ((SocketChannelImpl) ch).socket();
- return socket.getPlainSocketImpl().getNativeFD();
+ try
+ {
+ return ((SocketChannelImpl) ch).getVMChannel().getState().getNativeFD();
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalStateException(ioe);
+ }
}
}
diff --git a/libjava/classpath/gnu/java/nio/SocketChannelSelectionKeyImpl.java b/libjava/classpath/gnu/java/nio/SocketChannelSelectionKeyImpl.java
index 30fb2dfba44..31a96ed7d88 100644
--- a/libjava/classpath/gnu/java/nio/SocketChannelSelectionKeyImpl.java
+++ b/libjava/classpath/gnu/java/nio/SocketChannelSelectionKeyImpl.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.nio;
+import java.io.IOException;
+
/**
* @author Michael Barker <mike@middlesoft.co.uk>
@@ -63,7 +65,14 @@ public class SocketChannelSelectionKeyImpl extends SelectionKeyImpl
*/
public int getNativeFD()
{
- return ch.getPlainSocketImpl().getNativeFD();
+ try
+ {
+ return ch.getVMChannel().getState().getNativeFD();
+ }
+ catch (IOException ioe)
+ {
+ return 0; // FIXME
+ }
}
}
diff --git a/libjava/classpath/gnu/java/nio/VMChannelOwner.java b/libjava/classpath/gnu/java/nio/VMChannelOwner.java
new file mode 100644
index 00000000000..363dea2b214
--- /dev/null
+++ b/libjava/classpath/gnu/java/nio/VMChannelOwner.java
@@ -0,0 +1,57 @@
+/* NativeFD.java -- interface for Channels that have an underlying file descriptor.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+/**
+ * This interface is meant to be implemented by any {@link Channel}
+ * implementation we support that uses a platform-specific {@link VMChannel}
+ * at their core. This is primarily used by {@link Selector} implementations,
+ * for easier access to the native state.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+interface VMChannelOwner
+{
+ /**
+ * Return the underlying platform-specific Channel instance.
+ *
+ * @return The platform channel object.
+ */
+ VMChannel getVMChannel();
+}
OpenPOWER on IntegriCloud