summaryrefslogtreecommitdiff
path: root/gnu/java/nio
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-09-17 07:31:39 +0000
committerCasey Marshall <csm@gnu.org>2006-09-17 07:31:39 +0000
commit133e014be0604b45f8ccede687acf1ea979d4955 (patch)
tree03bfec201e509081586497b0e4db7944e633cab7 /gnu/java/nio
parenta344c95abdd44f1c697d0520bf97ac3c8403a3b6 (diff)
downloadclasspath-133e014be0604b45f8ccede687acf1ea979d4955.tar.gz
2006-09-16 Casey Marshall <csm@gnu.org>
* NEWS: updated. * configure.ac (AC_CHECK_HEADERS): check for `sys/event.h'. (AC_CHECK_FUNCS): add checks for readv, writev, getifaddrs, kqueue, and kevent. (HAVE_INET6): define if IPv6 is supported. * gnu/java/net/PlainDatagramSocketImpl.java (channel): new field. (native_fd): removed. (impl): new field. (<init>): throw IOException; initialize fields. (finalize): removed. (getNativeFD): removed. (bind): use `PlainSocketImpl.bind.' (create): use `PlainSocketImpl.initSocket.' (disconnect): use `PlainSocketImpl.disconnect.' (getLocalPort): new method. (send): use `VMChannel.send.' (receive): use `VMChannel.receive.' (setOption): use `PlainSocketImpl.setOption.' (getOption): use `PlainSocketImpl.getOption.' (close): use `VMChannel.State.close.' (join): use `PlainSocketImpl.join.' (leave): use `PlainSocketImpl.leave.' (joinGroup, leaveGroup): implemented. * gnu/java/net/PlainSocketImpl.java: make non-final. (native_fd): removed. (impl): new field. (channel): new field. (<init>): initialize `impl.' (finalize, getNativeFD): removed. (setOption): use `PlainSocketImpl.setOption.' (getOption): use `PlainSocketImpl.getOption.' (shutdownInput): use `PlainSocketImpl.shutdownInput.' (shutdownOutput): use `PlainSocketImpl.shutdownOutput.' (create): create `channel,' initialize `impl's native state. (connect): use `connect(SocketAddress, int).' (connect): use `SocketChannelImpl.connect;' initialize `address' and `port.' (bind): use `VMPlainSocketImpl.bind.' (listen): use `VMPlainSocketImpl.listen.' (accept): use `SocketChannelImpl.accept.' (available): use `VMChannel.available.' (close): use `PlainSocketImpl.close.' (sendUrgentData): use `PlainSocketImpl.sendUrgentData.' (getVMChannel, getInetAddress, getLocalPort, getLocalAddress, getPort): new methods. (SocketInputStream.read): use `VMChannel.read.' (SocketInputStream.read): use `SocketChannel.read.' (SocketOutputStream.write): use `VMChannel.write.' (SocketOutputStream.write): use `SocketChannel.write.' * gnu/java/nio/DatagramChannelImpl.java: implement VMChannel. (channel): new field. (<init>): initialize `channel.' (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (connect): use `VMChannel.connect.' (disconnect): use `VMChannel.disconnect.' (isConnected): use `VMChannel.getPeerAddress.' (write): use `VMChannel.write.' (write): use `VMChannel.writeGathering.' (read): use `VMChannel.read.' (read): use `VMChannel.readScattering.' (receive): use `VMChannel.receive.' (send): use `VMChannel.send.' (getVMChannel): new method. * gnu/java/nio/DatagramChannelSelectionKey.java (getNativeFD): access native FD through VMChannel.State. * gnu/java/nio/FileChannelImpl.java: moved from gnu/java/nio/channels/FileChannelImpl.java. * gnu/java/nio/FileLockImpl.java: fix imports. * gnu/java/nio/KqueueSelectionKeyImpl.java: new file. * gnu/java/nio/KqueueSelectorImpl.java: new file. * gnu/java/nio/NIOSocket.java (impl): removed. (channel): new field. (<init>): init superclass with a `NIOSocketImpl;' init `channel.' (getPlainSocketImpl, setChannel): removed. (isConnected): new method. * gnu/java/nio/NIOSocketImpl.java: new file. * gnu/java/nio/PipeImpl.java (SourceChannelImpl): implement `VMChannelOwner.' (SourceChannelImpl.native_fd): removed. (SourceChannelImpl.<init>): init with a `VMChannel.' (SourceChannelImpl.getNativeFD): removed. (SourceChannelImpl.getVMChannel): new method. (SourceChannelImpl.implCloseSelectableChannel): implement. (SinkChannelImpl): implement `VMChannelOwner.' (SinkChannelImpl.native_fd): removed. (SinkChannelImpl.<init>): init with a `VMChannel.' (SinkChannelImpl.implCloseSelectableChannel): implement. (SinkChannelImpl.getNativeFD): removed. (SinkChannelImpl.getVMChannel): new method. * gnu/java/nio/SelectionKeyImpl.java (getNativeFD): mark deprecated. * gnu/java/nio/SelectorProviderImpl.java (SELECTOR_IMPL_KQUEUE, SELECTOR_IMPL_EPOLL, SELECTOR_IMPL): new constants. (openSelector): return kqueue selector if available. * gnu/java/nio/ServerSocketChannelImpl.java: implement `VMChannelOwner.' (channel): new field. (<init>): init `channel.' (finalizer): check if the `VMChannel.State' is valid. (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (accept): use `VMChannel.accept.' (getVMChannel): new method. * gnu/java/nio/ServerSocketChannelSelectionKey.java (getNativeFD): access native FD through `VMChannel.State.' * gnu/java/nio/SocketChannelImpl.java: implement `VMChannelOwner.' (impl): removed. (channel, connected, connectAddress): new field. (<init>): new constructors. (getPlainSocketImpl): removed. (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (connect): use `connect(SocketAddress,int).' (connect): use `VMChannel.connect.' (finishConnect): don't use a selector. (isConnected): use `VMChannel.getPeerAddress.' (read): use `VMChannel.read.' (read): use `VMChannel.readScattering.' (write): use `VMChannel.write.' (write): use `VMChannel.writeGathering.' (getVMChannel): new method. * gnu/java/nio/SocketChannelSelectionKey.java (getNativeFD): get native FD from `VMChannel.State.' * gnu/java/nio/SocketChannelSelectionKeyImpl.java (getNativeFD): get native FD from `VMChannel.State.' * gnu/java/nio/VMChannelOwner.java: new file. * gnu/java/nio/channels/FileChannelImpl.java: removed. * include/Makefile.am: generate `gnu_java_nio_FileChannelImpl.h' and `gnu_java_nio_KqueueSelectorImpl.h;' don't generate `gnu_java_nio_channels_FileChannelImpl.h.' * include/gnu_java_net_VMPlainSocketImpl.h: regenerated. * include/gnu_java_nio_FileChannelImpl.h: new file. * include/gnu_java_nio_KqueueSelectorImpl.h: new file. * include/gnu_java_nio_VMChannel.h: regenerated. * include/gnu_java_nio_VMPipe.h: regenerated. * include/java_net_VMNetworkInterface.h: regenerated. * java/io/FileDescriptor.java: fix imports. * java/io/FileInputStream.java (<init>): handle exceptions. (read): wrap the destination arary. * java/io/FileOutputStream.java (<init>): handle exceptions. (write): wrap the source array. * java/io/RandomAccessFile.java (<init>): handle exceptions. * java/net/DatagramSocket.java (<init>): handle exceptions. (receive): handle length/port setting. (connect): bind to any address/port if the argument is null. * java/net/NetworkInterface.java (name, inetAddress): removed. (netif): new field. (<init>): make private. (getName): return `netif.name.' (getInetAddresses): access `netif.addresses.' (getDisplayName): return `netif.name.' (getByName, getByAddress): handle changes to `VMNetworkInterface.' (condense): removed. (getNetworkInterfaces): handle changes to `VMNetworkInterface.' (equals): compare `netif' fields. (hashCode): get hash codes from `netif.' (toString): use a StringBuffer. * java/net/ServerSocket.java (close): don't set `impl' to null. (isClosed): use `VMChannel.State.isClosed.' * java/net/Socket.java (getLocalAddress): don't use `getOption' if the `SocketImpl' is a `PlainSocketImpl.' (close): just close the `impl.' (toString): use `super.toString' in the value we return. (isConnected): just access `impl,' not `getImpl.' (isBound): use `PlainSocketImpl' methods if we can. (isClosed): look at `VMChannel.State.' * native/jni/classpath/jcl.c (JNI_OnLoad): new function. (JCL_NewRawDataObject): don't initialize cached fields here; throw an exception if they were not. (JCL_GetRawData): throw an exception if cached fields weren't created. * native/jni/java-lang/java_lang_VMProcess.c: handle FileChannelImpl move. * native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c (IO_EXCEPTION, SOCKET_EXCEPTION, BIND_EXCEPTION, THROW_NO_NETWORK): new macros. (Java_gnu_java_net_VMPlainSocketImpl_bind): reipmlemented. (Java_gnu_java_net_VMPlainSocketImpl_bind6): new function. (Java_gnu_java_net_VMPlainSocketImpl_listen): reimplemented. (java_sockopt): new enum. (Java_gnu_java_net_VMPlainSocketImpl_setOption): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_getOption): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_shutdownInput): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_shutdownOutput): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_sendUrgentData): new function. (Java_gnu_java_net_VMPlainSocketImpl_join): new function. (Java_gnu_java_net_VMPlainSocketImpl_join6): new function. (Java_gnu_java_net_VMPlainSocketImpl_read): removed. (Java_gnu_java_net_VMPlainSocketImpl_leave): new function. (Java_gnu_java_net_VMPlainSocketImpl_leave6): new function. (Java_gnu_java_net_VMPlainSocketImpl_joinGroup): new function. (Java_gnu_java_net_VMPlainSocketImpl_write): removed. (Java_gnu_java_net_VMPlainSocketImpl_joinGroup6): new function. (Java_gnu_java_net_VMPlainSocketImpl_leaveGroup): new function. (Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6): new function. (getif_address): new function. (getif_index): new function. * native/jni/java-net/java_net_VMNetworkInterface.c (java_net_VMNetworkInterface_init, java_net_VMNetworkInterface_addAddress): new file-scope globals. (Java_java_net_VMNetworkInterface_initIds): new function. (struct netif_entry): new struct. (free_netif_list): new function. (Java_java_net_VMNetworkInterface_getInterfaces): removed. (Java_java_net_VMNetworkInterface_getVMInterfaces): new function. * native/jni/java-nio/Makefile.am (libjavanio_la_SOURCES): remove gnu_java_nio_channels_FileChannelImpl.c, add gnu_java_nio_KqueueSelectorImpl.c. * native/jni/java-nio/gnu_java_nio_KqueueSelectorImpl.c: new file. * native/jni/java-nio/gnu_java_nio_VMChannel.c (INTERRUPTED_IO_EXCEPTION, SOCKET_TIMEOUT_EXCEPTION, ALIGN_UP, ALIGN_DOWN): new macros. (JCL_init_buffer): get the address through GetDirectBufferAddress if possible. (Java_gnu_java_nio_VMChannel_stdin_1fd, Java_gnu_java_nio_VMChannel_stdout_1fd, Java_gnu_java_nio_VMChannel_stderr_1fd): new functions. (Java_gnu_java_nio_VMChannel_setBlocking): fix setting blocking value. (Java_gnu_java_nio_VMChannel_read): renamed... (Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2): to this; handle interrupted IO; add HAVE_READ check. (Java_gnu_java_nio_VMChannel_write): renamed... (Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2): to this; handle zero-length write; add HAVE_WRITE check. (Java_gnu_java_nio_VMChannel_receive): new function. (Java_gnu_java_nio_VMChannel_send): new function. (Java_gnu_java_nio_VMChannel_send6): new function. (Java_gnu_java_nio_VMChannel_read__I): new function. (Java_gnu_java_nio_VMChannel_write__II): new function. (Java_gnu_java_nio_VMChannel_socket): new function. (Java_gnu_java_nio_VMChannel_connect): new function. (Java_gnu_java_nio_VMChannel_connect6): new function. (Java_gnu_java_nio_VMChannel_getsockname): new function. (Java_gnu_java_nio_VMChannel_getpeername): new function. (Java_gnu_java_nio_VMChannel_accept): new function. (Java_gnu_java_nio_VMChannel_disconnect): new function. (Java_gnu_java_nio_VMChannel_close): new function. (Java_gnu_java_nio_VMChannel_available): new function. (FileChannel_mode): new enum. (Java_gnu_java_nio_VMChannel_open): new function. (Java_gnu_java_nio_VMChannel_position): new function. (Java_gnu_java_nio_VMChannel_seek): new function. (Java_gnu_java_nio_VMChannel_truncate): new funciton. (Java_gnu_java_nio_VMChannel_lock): new function. (Java_gnu_java_nio_VMChannel_unlock): new function. (Java_gnu_java_nio_VMChannel_size): new function. (Java_gnu_java_nio_VMChannel_map): new function. (Java_gnu_java_nio_VMChannel_flush): new function. * native/jni/java-nio/gnu_java_nio_VMPipe.c (Java_gnu_java_nio_VMPipe_init): removed. (Java_gnu_java_nio_VMPipe_pipe0): new function. * native/jni/java-nio/javanio.c: new file. * native/jni/java-nio/javanio.h: new file. * native/jni/native-lib/cpnet.c (cpnet_getHostByName): fix for systems without `gethostbyname_r.' * vm/reference/gnu/java/net/VMPlainSocketImpl.java (nfd): new field. (<init>, <init>): new constructors. (setOption, getOption): make instance methods; defer to native implementation. (connect): removed. (bind): make an instance method; defer to native methods. (accept): removed. (available): removed. (listen): make an instance method; defer to native method. (read): removed. (join, leave): new methods. (write): removed. (joinGroup, leaveGroup): new methods. (shutdownInput, shutdownOutput): make instance methods. (sendUrgentData): removed. (State): new class. * vm/reference/gnu/java/nio/VMChannel.java: make final. (fd): removed. (nfd): new field. (<init>): new, public constructors. (getVMChannel): methods removed. (getState, getStdin, getStdout, getStderr, stdin_fd, stdout_fd, stderr_fd): new methods. (setBlocking): make an instance method. (available): new method. (read): get native fd from `nfd.' (read): new single-byte read method. (readScattering): get native fd from `nfd.' (receive): new method. (write, writeGathering): get native fd from `nfd.' (send): new method. (write): new single-byte write method. (initSocket): new method. (connect): new method. (disconnect): new method. (getLocalAddress): new method. (getPeerAddress): new method. (accept): new method. (openFile): new method. (position): new method. (seek): new method. (truncate): new method. (lock): new method. (unlock): new method. (size): new method. (map): new method. (flush): new method. (close): new method. (State): new class. (Kind): new class. * vm/reference/gnu/java/nio/VMPipe.java (init): removed. (pipe, pipe0): new method. * vm/reference/java/net/VMNetworkInterface.java (name, addresses): new fields. (<clinit>): call `initIds.' (initIds): new method. (getInterfaces): removed. (getVMInterfaces): new method. (addAddress): new method. * vm/reference/java/nio/channels/VMChannels.java: fix imports.
Diffstat (limited to 'gnu/java/nio')
-rw-r--r--gnu/java/nio/DatagramChannelImpl.java165
-rw-r--r--gnu/java/nio/DatagramChannelSelectionKey.java13
-rw-r--r--gnu/java/nio/FileChannelImpl.java (renamed from gnu/java/nio/channels/FileChannelImpl.java)173
-rw-r--r--gnu/java/nio/FileLockImpl.java2
-rw-r--r--gnu/java/nio/KqueueSelectionKeyImpl.java175
-rw-r--r--gnu/java/nio/KqueueSelectorImpl.java434
-rw-r--r--gnu/java/nio/NIOSocket.java29
-rw-r--r--gnu/java/nio/NIOSocketImpl.java110
-rw-r--r--gnu/java/nio/PipeImpl.java34
-rw-r--r--gnu/java/nio/SelectionKeyImpl.java1
-rw-r--r--gnu/java/nio/SelectorProviderImpl.java17
-rw-r--r--gnu/java/nio/ServerSocketChannelImpl.java39
-rw-r--r--gnu/java/nio/ServerSocketChannelSelectionKey.java13
-rw-r--r--gnu/java/nio/SocketChannelImpl.java251
-rw-r--r--gnu/java/nio/SocketChannelSelectionKey.java13
-rw-r--r--gnu/java/nio/SocketChannelSelectionKeyImpl.java11
-rw-r--r--gnu/java/nio/VMChannelOwner.java60
17 files changed, 1129 insertions, 411 deletions
diff --git a/gnu/java/nio/DatagramChannelImpl.java b/gnu/java/nio/DatagramChannelImpl.java
index 4687bf3f5..268ee0a8a 100644
--- a/gnu/java/nio/DatagramChannelImpl.java
+++ b/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/gnu/java/nio/DatagramChannelSelectionKey.java b/gnu/java/nio/DatagramChannelSelectionKey.java
index 698e07e34..f192e5002 100644
--- a/gnu/java/nio/DatagramChannelSelectionKey.java
+++ b/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/gnu/java/nio/channels/FileChannelImpl.java b/gnu/java/nio/FileChannelImpl.java
index ed439e141..419124050 100644
--- a/gnu/java/nio/channels/FileChannelImpl.java
+++ b/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/gnu/java/nio/FileLockImpl.java b/gnu/java/nio/FileLockImpl.java
index 673ca2522..768906ce9 100644
--- a/gnu/java/nio/FileLockImpl.java
+++ b/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/gnu/java/nio/KqueueSelectionKeyImpl.java b/gnu/java/nio/KqueueSelectionKeyImpl.java
new file mode 100644
index 000000000..9e5035eb4
--- /dev/null
+++ b/gnu/java/nio/KqueueSelectionKeyImpl.java
@@ -0,0 +1,175 @@
+/* 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;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class KqueueSelectionKeyImpl extends SelectionKey
+{
+ int interestOps;
+ int readyOps;
+ ByteBuffer nstate;
+ boolean valid;
+ int key;
+ boolean readEverEnabled = false;
+ boolean writeEverEnabled = false;
+
+ /** 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;
+ valid = true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#cancel()
+ */
+ //@Override
+ public void cancel()
+ {
+ selector.doCancel(this);
+ valid = false;
+ }
+
+ /* (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();
+ if ((ops & ~channel.validOps()) != 0)
+ throw new IllegalArgumentException();
+ this.interestOps = ops;
+ try
+ {
+ selector.updateOps(this,
+ natChannel.getVMChannel().getState().getNativeFD(),
+ false);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalStateException("channel is invalid");
+ }
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see java.nio.channels.SelectionKey#isValid()
+ */
+ //@Override
+ public boolean isValid()
+ {
+ return valid && selector.isOpen();
+ }
+
+ /* (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() + " [ <<invalid>> ]";
+ return super.toString() + " [ 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" : "")
+ + " } ]";
+ }
+}
diff --git a/gnu/java/nio/KqueueSelectorImpl.java b/gnu/java/nio/KqueueSelectorImpl.java
new file mode 100644
index 000000000..dcb058eb5
--- /dev/null
+++ b/gnu/java/nio/KqueueSelectorImpl.java
@@ -0,0 +1,434 @@
+/* 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.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
+{
+ private static final int sizeof_struct_kevent;
+
+ static
+ {
+ try
+ {
+ System.loadLibrary("javanio");
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ }
+
+ if (kqueue_supported ())
+ sizeof_struct_kevent = sizeof_struct_kevent();
+ else
+ sizeof_struct_kevent = -1;
+ }
+
+ /**
+ * 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 HashSet/*<KqueueSelectionKeyImpl>*/ cancelled;
+ private Thread blockedThread;
+
+ public KqueueSelectorImpl(SelectorProvider provider) throws IOException
+ {
+ super(provider);
+ kq = implOpen();
+ keys = new HashMap/*<KqueueSelectionKeyImpl>*/();
+ cancelled = new HashSet();
+ }
+
+ 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;
+ }
+
+ synchronized int doSelect(long timeout) throws IOException
+ {
+ // FIXME -- I'm unclear on how we should synchronize this; and how to
+ // handle cancelled keys.
+ for (Iterator it = cancelled.iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ updateOps(key, 0, true);
+ }
+ int events_size = 0;
+ for (Iterator it = keys.values().iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ if ((key.interestOps & SelectionKey.OP_ACCEPT) != 0
+ || (key.interestOps & SelectionKey.OP_READ) != 0)
+ key.readEverEnabled = true;
+ if ((key.interestOps & SelectionKey.OP_CONNECT) != 0
+ || (key.interestOps & SelectionKey.OP_WRITE) != 0)
+ key.writeEverEnabled = true;
+
+ if (key.readEverEnabled)
+ events_size += sizeof_struct_kevent;
+ if (key.writeEverEnabled)
+ events_size += sizeof_struct_kevent;
+ }
+
+ // We handle native events a little strangely here; per selection key,
+ // we allocate enough space for two struct kevents, the first in the
+ // list will be our EVFILT_READ filter, the second our EVFILT_WRITE
+ // one. If only one of the two needs enabling, though, we don't want
+ // to pass the other to kevent, because that would result in spurious
+ // events. We can break down our handling as follows:
+ //
+ // - READ enabled, WRITE never enabled. We pass only the first structure
+ // to kevent.
+ // - WRITE enabled, READ never enabled. Likewise, but only pass the
+ // second structure.
+ // - READ and WRITE enabled. Pass both.
+ // - READ enabled, WRITE enabled in the past. Pass both, with the
+ // first structure's flag set to EV_ADD or EV_ENABLE, and the second
+ // with EV_DISABLE. It seems OK to keep sending events with the
+ // EV_DISABLE flag.
+ // - WRITE enabled, READ enabled in the past. Likewise, but flipped.
+ //
+ // We handle these states with the readEverEnabled and writeEverEnabled
+ // flags of selection keys; they start off as false, and become true
+ // the first time we select() with READ or WRITE enabled. They never
+ // become false.
+ ByteBuffer events = ByteBuffer.allocateDirect(events_size);
+
+ for (Iterator it = keys.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) e.getValue();
+
+ if (key.readEverEnabled)
+ events.put((ByteBuffer) key.nstate.duplicate().limit
+ (sizeof_struct_kevent));
+ if (key.writeEverEnabled)
+ events.put((ByteBuffer) key.nstate.duplicate().position
+ (sizeof_struct_kevent).limit(2 * sizeof_struct_kevent));
+ }
+ events.rewind();
+
+ //System.out.println("dump of keys to select:");
+ //dump_selection_keys(events.duplicate());
+
+ blockedThread = Thread.currentThread();
+ if (blockedThread.isInterrupted())
+ timeout = 0;
+ final int n = kevent(kq, events, events_size / sizeof_struct_kevent,
+ timeout);
+ Thread.interrupted();
+
+ //System.out.println("dump of keys selected:");
+ //dump_selection_keys((ByteBuffer) events.duplicate().limit(n * sizeof_struct_kevent));
+
+ 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));
+ key.readyOps = ready_ops(events.slice(), key.interestOps);
+ selected.add(key);
+ }
+ for (Iterator it = cancelled.iterator(); it.hasNext(); )
+ {
+ KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
+ keys.remove(new Integer(key.key));
+ it.remove();
+ }
+
+ 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);
+ int k = System.identityHashCode(result);
+ while (keys.containsKey(new Integer(k)))
+ k++;
+ result.key = k;
+ keys.put(new Integer(k), result);
+ result.nstate = ByteBuffer.allocateDirect(2 * sizeof_struct_kevent);
+ updateOps(result, native_fd, false);
+ return result;
+ }
+
+ synchronized void updateOps(KqueueSelectionKeyImpl key)
+ {
+ updateOps(key, 0, false);
+ }
+
+ synchronized void updateOps(KqueueSelectionKeyImpl key, int fd, boolean delete)
+ {
+ //System.out.println(">> updating kqueue selection key:");
+ //dump_selection_keys(key.nstate.duplicate());
+ //System.out.println("<<");
+ kevent_set(key.nstate, fd, key.interestOps, key.key, delete);
+ //System.out.println(">> updated kqueue selection key:");
+ //dump_selection_keys(key.nstate.duplicate());
+ //System.out.println("<<");
+ }
+
+ synchronized void doCancel(KqueueSelectionKeyImpl key)
+ {
+ cancelled.add(key);
+ }
+
+ 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 fd, int interestOps,
+ int key, boolean delete);
+
+ /**
+ * 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 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,
+ 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/gnu/java/nio/NIOSocket.java b/gnu/java/nio/NIOSocket.java
index 4d812bf44..060a3a89c 100644
--- a/gnu/java/nio/NIOSocket.java
+++ b/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/gnu/java/nio/NIOSocketImpl.java b/gnu/java/nio/NIOSocketImpl.java
new file mode 100644
index 000000000..4b26561a2
--- /dev/null
+++ b/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/gnu/java/nio/PipeImpl.java b/gnu/java/nio/PipeImpl.java
index cccaa3988..8a95b9622 100644
--- a/gnu/java/nio/PipeImpl.java
+++ b/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/gnu/java/nio/SelectionKeyImpl.java b/gnu/java/nio/SelectionKeyImpl.java
index 8745377c5..c927f3196 100644
--- a/gnu/java/nio/SelectionKeyImpl.java
+++ b/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/gnu/java/nio/SelectorProviderImpl.java b/gnu/java/nio/SelectorProviderImpl.java
index 47521107e..a9a122570 100644
--- a/gnu/java/nio/SelectorProviderImpl.java
+++ b/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,10 @@ 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";
+
public SelectorProviderImpl ()
{
}
@@ -66,6 +73,16 @@ public class SelectorProviderImpl extends SelectorProvider
public AbstractSelector openSelector ()
throws IOException
{
+ String selectorImpl = "default";
+ if (KqueueSelectorImpl.kqueue_supported())
+ selectorImpl = SELECTOR_IMPL_KQUEUE;
+ selectorImpl = SystemProperties.getProperty(SELECTOR_IMPL, selectorImpl);
+
+ if (selectorImpl.equals(SELECTOR_IMPL_KQUEUE))
+ return new KqueueSelectorImpl(this);
+ if (selectorImpl.equals(SELECTOR_IMPL_EPOLL))
+ throw new UnsupportedOperationException("epoll selector not yet implemented");
+
return new SelectorImpl (this);
}
diff --git a/gnu/java/nio/ServerSocketChannelImpl.java b/gnu/java/nio/ServerSocketChannelImpl.java
index c538ea802..1e8e0901d 100644
--- a/gnu/java/nio/ServerSocketChannelImpl.java
+++ b/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/gnu/java/nio/ServerSocketChannelSelectionKey.java b/gnu/java/nio/ServerSocketChannelSelectionKey.java
index d00c2b748..5b510cb6f 100644
--- a/gnu/java/nio/ServerSocketChannelSelectionKey.java
+++ b/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/gnu/java/nio/SocketChannelImpl.java b/gnu/java/nio/SocketChannelImpl.java
index 680eba2f9..459decf52 100644
--- a/gnu/java/nio/SocketChannelImpl.java
+++ b/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,40 +165,15 @@ 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 ()
@@ -168,37 +182,30 @@ public final class SocketChannelImpl extends SocketChannel
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())
{
- 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();
+ try
+ {
+ InetSocketAddress remote = channel.getPeerAddress();
+ return remote != null;
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace(System.out);
+ return false;
+ }
}
public boolean isConnectionPending ()
@@ -216,52 +223,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 +237,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 +260,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/gnu/java/nio/SocketChannelSelectionKey.java b/gnu/java/nio/SocketChannelSelectionKey.java
index 75b4dfd87..9ceebdec9 100644
--- a/gnu/java/nio/SocketChannelSelectionKey.java
+++ b/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/gnu/java/nio/SocketChannelSelectionKeyImpl.java b/gnu/java/nio/SocketChannelSelectionKeyImpl.java
index 30fb2dfba..31a96ed7d 100644
--- a/gnu/java/nio/SocketChannelSelectionKeyImpl.java
+++ b/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/gnu/java/nio/VMChannelOwner.java b/gnu/java/nio/VMChannelOwner.java
new file mode 100644
index 000000000..faf70888c
--- /dev/null
+++ b/gnu/java/nio/VMChannelOwner.java
@@ -0,0 +1,60 @@
+/* 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;
+
+import java.nio.channels.Channel;
+import java.nio.channels.Selector;
+
+/**
+ * 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();
+}