Index: .settings/org.eclipse.jdt.core.prefs =================================================================== RCS file: /cvsroot/classpath/classpath/.settings/org.eclipse.jdt.core.prefs,v retrieving revision 1.5 diff -u -r1.5 org.eclipse.jdt.core.prefs --- .settings/org.eclipse.jdt.core.prefs 14 Sep 2005 01:33:27 -0000 1.5 +++ .settings/org.eclipse.jdt.core.prefs 11 Jan 2006 22:09:39 -0000 @@ -1,4 +1,4 @@ -#Tue Sep 13 16:15:04 MDT 2005 +#Thu Dec 22 16:04:11 GMT 2005 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 @@ -15,7 +15,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning @@ -72,6 +72,7 @@ org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=82 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 @@ -302,3 +303,4 @@ org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=2 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false Index: .settings/org.eclipse.jdt.ui.prefs =================================================================== RCS file: /cvsroot/classpath/classpath/.settings/org.eclipse.jdt.ui.prefs,v retrieving revision 1.4 diff -u -r1.4 org.eclipse.jdt.ui.prefs --- .settings/org.eclipse.jdt.ui.prefs 18 Sep 2005 04:19:36 -0000 1.4 +++ .settings/org.eclipse.jdt.ui.prefs 11 Jan 2006 22:09:39 -0000 @@ -1,4 +1,4 @@ -#Sat Sep 17 22:04:29 MDT 2005 +#Thu Dec 22 16:04:10 GMT 2005 eclipse.preferences.version=1 formatter_settings_version=8 internal.default.compliance=user Index: gnu/java/nio/SelectorImpl.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/nio/SelectorImpl.java,v retrieving revision 1.21 diff -u -r1.21 SelectorImpl.java --- gnu/java/nio/SelectorImpl.java 27 Dec 2005 08:32:12 -0000 1.21 +++ gnu/java/nio/SelectorImpl.java 11 Jan 2006 22:09:41 -0000 @@ -379,6 +379,8 @@ result = new DatagramChannelSelectionKey (ch, this); else if (ch instanceof ServerSocketChannelImpl) result = new ServerSocketChannelSelectionKey (ch, this); + else if (ch instanceof gnu.java.nio.channels.SocketChannelImpl) + result = new gnu.java.nio.channels.SocketChannelSelectionKeyImpl((gnu.java.nio.channels.SocketChannelImpl)ch, this); else throw new InternalError ("No known channel type"); Index: gnu/java/nio/SelectorProviderImpl.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/nio/SelectorProviderImpl.java,v retrieving revision 1.8 diff -u -r1.8 SelectorProviderImpl.java --- gnu/java/nio/SelectorProviderImpl.java 2 Jul 2005 20:32:13 -0000 1.8 +++ gnu/java/nio/SelectorProviderImpl.java 11 Jan 2006 22:09:41 -0000 @@ -78,6 +78,7 @@ public SocketChannel openSocketChannel () throws IOException { - return new SocketChannelImpl (this); + //return new SocketChannelImpl (this); + return new gnu.java.nio.channels.SocketChannelImpl (this); } } Index: gnu/java/nio/ServerSocketChannelImpl.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/nio/ServerSocketChannelImpl.java,v retrieving revision 1.14 diff -u -r1.14 ServerSocketChannelImpl.java --- gnu/java/nio/ServerSocketChannelImpl.java 2 Jul 2005 20:32:13 -0000 1.14 +++ gnu/java/nio/ServerSocketChannelImpl.java 11 Jan 2006 22:09:42 -0000 @@ -102,7 +102,7 @@ // 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(); + gnu.java.nio.channels.NIOSocket socket = (gnu.java.nio.channels.NIOSocket) serverSocket.accept(); completed = true; return socket.getChannel(); } Index: include/Makefile.am =================================================================== RCS file: /cvsroot/classpath/classpath/include/Makefile.am,v retrieving revision 1.52 diff -u -r1.52 Makefile.am --- include/Makefile.am 4 Jan 2006 16:37:55 -0000 1.52 +++ include/Makefile.am 11 Jan 2006 22:09:43 -0000 @@ -122,6 +122,7 @@ $(top_srcdir)/include/gnu_java_nio_VMPipe.h \ $(top_srcdir)/include/gnu_java_nio_VMSelector.h \ $(top_srcdir)/include/gnu_java_nio_channels_FileChannelImpl.h \ +$(top_srcdir)/include/gnu_java_nio_channels_VMChannel.h \ $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvEncoder.h \ $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvDecoder.h \ $(top_srcdir)/include/java_io_VMFile.h \ @@ -200,6 +201,8 @@ $(JAVAH) -o $@ java.nio.MappedByteBufferImpl $(top_srcdir)/include/gnu_java_nio_channels_FileChannelImpl.h: $(top_srcdir)/gnu/java/nio/channels/FileChannelImpl.java $(JAVAH) -o $@ gnu.java.nio.channels.FileChannelImpl +$(top_srcdir)/include/gnu_java_nio_channels_FileChannelImpl.h: $(top_srcdir)/gnu/java/nio/channels/VMChannel.java + $(JAVAH) -o $@ gnu.java.nio.channels.VMChannel $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvDecoder.h: $(top_srcdir)/gnu/java/nio/charset/iconv/IconvDecoder.java $(JAVAH) -o $@ gnu.java.nio.charset.iconv.IconvDecoder $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvEncoder.h: $(top_srcdir)/gnu/java/nio/charset/iconv/IconvEncoder.java Index: native/jni/java-nio/Makefile.am =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/java-nio/Makefile.am,v retrieving revision 1.19 diff -u -r1.19 Makefile.am --- native/jni/java-nio/Makefile.am 23 Oct 2005 16:59:08 -0000 1.19 +++ native/jni/java-nio/Makefile.am 11 Jan 2006 22:09:53 -0000 @@ -5,8 +5,10 @@ gnu_java_nio_channels_FileChannelImpl.c \ gnu_java_nio_charset_iconv_IconvDecoder.c \ gnu_java_nio_charset_iconv_IconvEncoder.c \ + gnu_java_nio_channels_VMChannel.c \ java_nio_MappedByteBufferImpl.c \ - java_nio_VMDirectByteBuffer.c + java_nio_VMDirectByteBuffer.c + libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \ $(LTLIBICONV) Index: gnu/java/nio/channels/NIOSocket.java =================================================================== RCS file: gnu/java/nio/channels/NIOSocket.java diff -N gnu/java/nio/channels/NIOSocket.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/java/nio/channels/NIOSocket.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,79 @@ +/* NIOSocket.java -- Wrapper socket implemenation class. + Copyright (C) 2003 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.channels; + +import gnu.java.net.PlainSocketImpl; +import gnu.java.nio.channels.SocketChannelImpl; + +import java.io.IOException; +import java.net.Socket; +import java.nio.channels.SocketChannel; + +/** + * @author Michael Koch + */ +public final class NIOSocket extends Socket +{ + private PlainSocketImpl impl; + private SocketChannelImpl channel; + + protected NIOSocket (PlainSocketImpl impl, SocketChannelImpl channel) + throws IOException + { + super (impl); + this.impl = impl; + this.channel = channel; + } + + public final PlainSocketImpl getPlainSocketImpl() + { + return impl; + } + + final void setChannel (SocketChannelImpl channel) + { + this.impl = channel.getPlainSocketImpl(); + this.channel = channel; + } + + public final SocketChannel getChannel() + { + return channel; + } +} Index: gnu/java/nio/channels/SocketChannelImpl.java =================================================================== RCS file: gnu/java/nio/channels/SocketChannelImpl.java diff -N gnu/java/nio/channels/SocketChannelImpl.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/java/nio/channels/SocketChannelImpl.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,285 @@ +/* PosixSocketChannelImpl.java -- Non-blocking enable socket channel + Copyright (C) 2005 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.channels; + +import gnu.java.net.PlainSocketImpl; +import gnu.java.nio.NIOConstants; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketTimeoutException; +import java.nio.ByteBuffer; +import java.nio.channels.AlreadyConnectedException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ConnectionPendingException; +import java.nio.channels.NoConnectionPendingException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.channels.UnresolvedAddressException; +import java.nio.channels.UnsupportedAddressTypeException; +import java.nio.channels.spi.SelectorProvider; + +/** + * @author Michael Barker + * + */ +public class SocketChannelImpl extends SocketChannel +{ + private VMChannel vmch; + private PlainSocketImpl sImpl; + private Socket socket; + private boolean connectionPending; + + /** + * @param provider + * @throws IOException + */ + public SocketChannelImpl(SelectorProvider provider) + throws IOException + { + super(provider); + this.vmch = new VMChannel(); + this.sImpl = new PlainSocketImpl(); + this.socket = new NIOSocket(sImpl, this); + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer) + */ + public int read(ByteBuffer dst) + throws IOException + { + return vmch.read(getFd(), dst); + } + + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int, int) + */ + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException + { + return vmch.readScattering(getFd(), dsts, offset, length); + } + + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress) + */ + public boolean connect(SocketAddress remote) + throws IOException + { + if (!isOpen()) + throw new ClosedChannelException(); + + if (isConnected()) + throw new AlreadyConnectedException(); + + if (connectionPending) + throw new ConnectionPendingException(); + + if (!(remote instanceof InetSocketAddress)) + throw new UnsupportedAddressTypeException(); + + if (((InetSocketAddress) remote).isUnresolved()) + throw new UnresolvedAddressException(); + + try + { + sImpl.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 + { + sImpl.setInChannelOperation(false); + } + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#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()) + { + selector.select(); // blocking until channel is connected. + connectionPending = false; + return true; + } + + int ready = selector.selectNow(); // non-blocking + if (ready == 1) + { + connectionPending = false; + return true; + } + + return false; + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#isConnected() + */ + public boolean isConnected() + { + return socket.isConnected(); + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#isConnectionPending() + */ + public boolean isConnectionPending() + { + return connectionPending; + } + + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#socket() + */ + public Socket socket() + { + return socket; + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer) + */ + public int write(ByteBuffer src) + throws IOException + { + return vmch.write(getFd(), src); + } + + /* (non-Javadoc) + * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int, int) + */ + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + return vmch.writeGathering(getFd(), srcs, offset, length); + } + + /* (non-Javadoc) + * @see java.nio.channels.spi.AbstractSelectableChannel#implCloseSelectableChannel() + */ + protected void implCloseSelectableChannel() + throws IOException + { + socket.close(); + } + + + /* (non-Javadoc) + * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean) + */ + protected void implConfigureBlocking(boolean blocking) + throws IOException + { + vmch.setBlocking(getFd(), blocking); + } + + public int getFd() + { + return sImpl.getNativeFD(); + } + + + /** + * @return The socket implemenation + */ + public PlainSocketImpl getPlainSocketImpl() + { + return sImpl; + } + + public void finalizer() + { + if (isConnected()) + { + try + { + close (); + } + catch (Exception e) + { + } + } + } + +} Index: gnu/java/nio/channels/SocketChannelSelectionKeyImpl.java =================================================================== RCS file: gnu/java/nio/channels/SocketChannelSelectionKeyImpl.java diff -N gnu/java/nio/channels/SocketChannelSelectionKeyImpl.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/java/nio/channels/SocketChannelSelectionKeyImpl.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,71 @@ +/* SocketChannelSelectionKey.java -- Selection key for Socket Channel + Copyright (C) 2005 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.channels; + +import gnu.java.nio.SelectionKeyImpl; +import gnu.java.nio.SelectorImpl; + +/** + * @author mike + * + */ +public class SocketChannelSelectionKeyImpl extends SelectionKeyImpl +{ + + SocketChannelImpl ch; + + /** + * @param ch + * @param impl + */ + public SocketChannelSelectionKeyImpl(SocketChannelImpl ch, SelectorImpl impl) + { + super(ch, impl); + this.ch = (SocketChannelImpl) ch; + } + + /* (non-Javadoc) + * @see gnu.java.nio.SelectionKeyImpl#getNativeFD() + */ + public int getNativeFD() + { + return ch.getFd(); + } + +} Index: gnu/java/nio/channels/VMChannel.java =================================================================== RCS file: gnu/java/nio/channels/VMChannel.java diff -N gnu/java/nio/channels/VMChannel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/java/nio/channels/VMChannel.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,124 @@ +/* VMChannel.java -- Native interface suppling channel operations. + Copyright (C) 2005 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.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * @author mike + * + */ +public class VMChannel +{ + + static + { + initIDs(); + } + + /** + * Set the file descriptor to have the required blocking + * setting. + * + * @param fd + * @param blocking + */ + native void setBlocking(int fd, boolean blocking); + + + /** + * Reads a byte buffer directly using the supplied file descriptor. + * Assumes that the buffer is a DirectBuffer. + * + * @param fd Native file descriptor to read from. + * @param dst Direct Byte Buffer to read to. + * @return Number of bytes read. + * @throws IOException If an error occurs or dst is not a direct buffers. + */ + native int read(int fd, ByteBuffer dst) + throws IOException; + + /** + * Reads into byte buffers directly using the supplied file descriptor. + * Assumes that the buffer list contains DirectBuffers. Will perform a + * scattering read. + * + * @param fd Native file descriptor to read from. + * @param dsts An array direct byte buffers. + * @param offset Index of the first buffer to read to. + * @param length The number of buffers to read to. + * @return Number of bytes read. + * @throws IOException If an error occurs or the dsts are not direct buffers. + */ + native long readScattering(int fd, ByteBuffer[] dsts, int offset, int length) + throws IOException; + + + /** + * Writes from a direct byte bufer using the supplied file descriptor. + * Assumes the buffer is a DirectBuffer. + * + * @param fd + * @param src + * @return Number of bytes written. + * @throws IOException + */ + native int write(int fd, ByteBuffer src) + throws IOException; + + /** + * Writes from byte buffers directly using the supplied file descriptor. + * Assumes the that buffer list constains DirectBuffers. Will perform + * as gathering write. + * + * @param fd + * @param srcs + * @param offset + * @param length + * @return Number of bytes written. + * @throws IOException + */ + native long writeGathering(int fd, ByteBuffer[] srcs, int offset, int length) + throws IOException; + + + private native static void initIDs(); + +} Index: include/gnu_java_nio_channels_VMChannel.h =================================================================== RCS file: include/gnu_java_nio_channels_VMChannel.h diff -N include/gnu_java_nio_channels_VMChannel.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/gnu_java_nio_channels_VMChannel.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,24 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __gnu_java_nio_channels_VMChannel__ +#define __gnu_java_nio_channels_VMChannel__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_gnu_java_nio_channels_VMChannel_setBlocking (JNIEnv *env, jobject, jint, jboolean); +JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_VMChannel_read (JNIEnv *env, jobject, jint, jobject); +JNIEXPORT jlong JNICALL Java_gnu_java_nio_channels_VMChannel_readScattering (JNIEnv *env, jobject, jint, jobjectArray, jint, jint); +JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_VMChannel_write (JNIEnv *env, jobject, jint, jobject); +JNIEXPORT jlong JNICALL Java_gnu_java_nio_channels_VMChannel_writeGathering (JNIEnv *env, jobject, jint, jobjectArray, jint, jint); +JNIEXPORT void JNICALL Java_gnu_java_nio_channels_VMChannel_initIDs (JNIEnv *env, jclass); + +#ifdef __cplusplus +} +#endif + +#endif /* __gnu_java_nio_channels_VMChannel__ */ Index: native/jni/java-nio/gnu_java_nio_channels_VMChannel.c =================================================================== RCS file: native/jni/java-nio/gnu_java_nio_channels_VMChannel.c diff -N native/jni/java-nio/gnu_java_nio_channels_VMChannel.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ native/jni/java-nio/gnu_java_nio_channels_VMChannel.c 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,508 @@ +/* gnu_java_nio_channels_VMChannel.c - + Copyright (C) 2003, 2004, 2005, 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. */ + + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gnu_java_nio_channels_VMChannel.h" + +#ifdef HAVE_FCNTL_H +#include +#endif /* HAVE_FCNTL_H */ + +#define IO_EXCEPTION "java/io/IOException" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* FIXME: This can't be right. Need converter macros */ +#define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF)) +#define CONVERT_INT_TO_JINT(x) ((int)(x & 0xFFFFFFFF)) + +/* FIXME: This can't be right. Need converter macros. */ +#define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF)) +#define CONVERT_JINT_TO_SSIZE_T(x) (x) + +static jfieldID address_fid; +static jmethodID get_position_mid; +static jmethodID set_position_mid; +static jmethodID get_limit_mid; +static jmethodID set_limit_mid; +static jmethodID has_array_mid; +static jmethodID array_mid; +static jmethodID array_offset_mid; +/* +static jmethodID put_mid; +static jmethodID get_mid; +*/ + +jmethodID +get_method_id(JNIEnv *env, jclass clazz, const char *name, + const char *sig) +{ + jmethodID mid = (*env)->GetMethodID(env, clazz, name, sig); + if (mid == NULL) + { + JCL_ThrowException(env, "java/lang/InternalError", name); + return NULL; + } + + return mid; +} + +enum JCL_buffer_type { DIRECT, ARRAY, UNKNOWN }; + +struct JCL_buffer +{ + enum JCL_buffer_type type; + jbyte *ptr; + jbyteArray array; + jobject bbuf; + jint offset; + jint position; + jint limit; + jint count; +}; + +int +JCL_init_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf) +{ + jobject address = (*env)->GetObjectField(env, bbuf, address_fid); + + buf->position = (*env)->CallIntMethod(env, bbuf, get_position_mid); + buf->limit = (*env)->CallIntMethod(env, bbuf, get_limit_mid); + buf->bbuf = bbuf; + buf->offset = 0; + buf->array = NULL; + buf->count = 0; + buf->type = UNKNOWN; + + if (address != NULL) + { + buf->ptr = (jbyte *) JCL_GetRawData(env, address); + buf->type = DIRECT; + } + else + { + jboolean has_array; + + has_array = (*env)->CallBooleanMethod(env, bbuf, has_array_mid); + if (has_array == JNI_TRUE) + { + buf->offset = (*env)->CallIntMethod(env, bbuf, array_offset_mid); + buf->array = (*env)->CallObjectMethod(env, bbuf, array_mid); + buf->ptr = (*env)->GetByteArrayElements(env, buf->array, 0); + buf->type = ARRAY; + } + else + { + return -1; + } + } + + return 0; +} + +void +JCL_release_buffer(JNIEnv *env, struct JCL_buffer *buf, jint action) +{ + /* Set the position to the appropriate value */ + if (buf->count > 0) + (*env)->CallObjectMethod(env, buf->bbuf, set_position_mid, + buf->position + buf->count); + + switch (buf->type) + { + case DIRECT: + break; + case ARRAY: + (*env)->ReleaseByteArrayElements(env, buf->array, buf->ptr, action); + break; + case UNKNOWN: + /* TODO: Handle buffers that are not direct or array backed */ + break; + } +} + + +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_VMChannel_initIDs (JNIEnv *env, + jclass clazz __attribute__ ((__unused__))) +{ + jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer"); + jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer"); + + address_fid = (*env)->GetFieldID(env, bufferClass, "address", + "Lgnu/classpath/Pointer;"); + if (address_fid == NULL) + { + JCL_ThrowException(env, "java/lang/InternalError", + "Unable to find internal field"); + return; + } + + get_position_mid = get_method_id(env, bufferClass, "position", "()I"); + set_position_mid = get_method_id(env, bufferClass, "position", + "(I)Ljava/nio/Buffer;"); + get_limit_mid = get_method_id(env, bufferClass, "limit", "()I"); + set_limit_mid = get_method_id(env, bufferClass, "limit", + "(I)Ljava/nio/Buffer;"); + has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z"); + array_mid = get_method_id(env, byteBufferClass, "array", "()[B"); + array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I"); + /* + get_mid = get_method_id(env, byteBufferClass, "get", + "([B)Ljava.nio.ByteBuffer;"); + put_mid = get_method_id(env, byteBufferClass, "put", + "([B)Ljava.nio.ByteBuffer;"); + */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_VMChannel_setBlocking (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jboolean blocking) +{ + int opts; + + opts = fcntl(fd, F_GETFL); + if (opts < 0) + { + JCL_ThrowException(env, IO_EXCEPTION, + "Failed to get flags for file desriptor"); + return; + } + + if (blocking) + opts |= O_NONBLOCK; + else + opts &= ~(O_NONBLOCK); + + opts = fcntl(fd, F_SETFL, opts); + + if (opts < 0) + { + JCL_ThrowException(env, IO_EXCEPTION, + "Failed to set flags for file desriptor"); + return; + } +} + + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_VMChannel_read (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobject bbuf) +{ + jint len; + ssize_t result; + struct JCL_buffer buf; + + if (JCL_init_buffer(env, &buf, bbuf) < 0) + { + /* TODO: Rethrown exception */ + JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed"); + return -1; + } + + len = buf.limit - buf.position; + + result = read(fd, &(buf.ptr[buf.position + buf.offset]), len); + buf.count = result; + + if (result == 0) + result = -1; /* End Of File */ + else if (result == -1) + { + buf.count = 0; + if (errno == EAGAIN) /* Non-blocking */ + result = 0; + else + { + JCL_release_buffer(env, &buf, JNI_ABORT); + JCL_ThrowException (env, IO_EXCEPTION, strerror(errno)); + return -1; + } + } + else + + JCL_release_buffer(env, &buf, JNI_COMMIT); + + return result; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_VMChannel_write (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobject bbuf) +{ + jint len; + ssize_t result; + struct JCL_buffer buf; + + if (JCL_init_buffer(env, &buf, bbuf) < 0) + { + /* TODO: Rethrown exception */ + JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed"); + return -1; + } + + len = buf.limit - buf.position; + + result = write(fd, &(buf.ptr[buf.offset]), len); + buf.count = result; + + if (result == -1) + { + if (errno == EAGAIN) /* Non-blocking */ + result = 0; + else + { + JCL_release_buffer(env, &buf, JNI_ABORT); + JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); + return -1; + } + } + + JCL_release_buffer(env, &buf, JNI_ABORT); + + return result; +} + + +/* + * Implementation of a scattering read. Will use the appropriate + * vector based read call (currently readv on Linux). + * + * This has a limit to the number of buffers that will be read. It + * will not make muliple readv calls. This is to ensure that operations + * are atomic. Currently it is limited to sysconf(_SC_IOV_MAX) which + * is 1024 (according to the man page). + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_channels_VMChannel_readScattering (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobjectArray bbufs, + jint offset, + jint length) +{ + /* FIXME: This is not portable */ + const jint JCL_IOV_MAX = CONVERT_INT_TO_JINT(sysconf(_SC_IOV_MAX)); + jint i; + jboolean is_error = JNI_FALSE; + char *error_msg; + struct iovec *buffers = NULL; + struct JCL_buffer *bi_list = NULL; + ssize_t result; + jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX; + jlong bytes_read = 0; + + buffers = JCL_malloc(env, vec_len * sizeof(struct iovec)); + bi_list = JCL_malloc(env, vec_len * sizeof(struct JCL_buffer)); + + /* Build the vector of buffers to read into */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer buf = bi_list[i]; + jobject bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i); + + JCL_init_buffer(env, &buf, bbuf); + + buffers[i].iov_base = &(buf.ptr[buf.position + buf.offset]); + buffers[i].iov_len = buf.limit - buf.position; + } + + /* Work the scattering magic */ + result = readv(fd, buffers, vec_len); + /* XXX: Convert ssize_t to a jlong */ + bytes_read = result; + + /* Handle the response */ + if (result < 0) + { + if (errno == EAGAIN) /* Non blocking */ + result = 0; + else + { + is_error = JNI_TRUE; + error_msg = strerror(errno); + } + bytes_read = 0; + } + else if (result == 0) /* EOF */ + { + result = -1; + } + + /* Update all of the bbufs with the approriate information */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer buf = bi_list[i]; + + if (bytes_read > (buf.limit - buf.position)) + buf.count = (buf.limit - buf.position); + else + buf.count = bytes_read; + + bytes_read -= buf.count; + + JCL_release_buffer(env, &buf, JNI_COMMIT); + } + + + /* A GC, a GC, my kingdom for a GC */ + JCL_free(env, buffers); + JCL_free(env, bi_list); + + if (is_error == JNI_TRUE) + { + JCL_ThrowException(env, IO_EXCEPTION, error_msg); + return -1; + } + + /* XXX: Convert ssize_t to a jlong */ + return result; +} + +/* + * Implementation of a gathering write. Will use the appropriate + * vector based read call (currently readv on Linux). + * + * This has a limit to the number of buffers that will be read. It + * will not make muliple readv calls. This is to ensure that operations + * are atomic. Currently it is limited to sysconf(_SC_IOV_MAX) which + * is 1024 (according to the man page). + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_channels_VMChannel_writeGathering (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobjectArray bbufs, + jint offset, + jint length) +{ + /* FIXME: This is not portable */ + const jint JCL_IOV_MAX = CONVERT_INT_TO_JINT(sysconf(_SC_IOV_MAX)); + int i; + jboolean is_error = JNI_FALSE; + char *error_msg; + struct iovec *buffers = NULL; + struct JCL_buffer *bi_list = NULL; + ssize_t result; + jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX; + jlong bytes_written; + + buffers = JCL_malloc(env, vec_len * sizeof (struct iovec)); + bi_list = JCL_malloc(env, vec_len * sizeof(jbyte *)); + + /* Build the vector of buffers to read into */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer buf = bi_list[i]; + jobject bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i); + + JCL_init_buffer(env, &buf, bbuf); + + buffers[i].iov_base = &(buf.ptr[buf.position + buf.offset]); + buffers[i].iov_len = buf.limit - buf.position; + } + + /* Work the gathering magic */ + result = writev(fd, buffers, vec_len); + bytes_written = result; + + if (result < 0) + { + bytes_written = 0; + if (errno == EAGAIN) /* Non blocking */ + result = 0; + else + { + is_error = JNI_TRUE; + error_msg = strerror(errno); + } + } + else if (result == 0) /* EOF?? Does this happen on a write */ + result = -1; + + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer buf = bi_list[i]; + + if (bytes_written > (buf.limit - buf.position)) + buf.count = (buf.limit - buf.position); + else + buf.count = bytes_written; + + bytes_written -= buf.count; + + JCL_release_buffer(env, &buf, JNI_ABORT); + } + + /* A GC, a GC, my kingdom for a GC */ + JCL_free(env, buffers); + JCL_free(env, bi_list); + + if (is_error == JNI_TRUE) + { + JCL_ThrowException(env, IO_EXCEPTION, error_msg); + return -1; + } + + return result; +} + + + + +#ifdef __cplusplus +} +#endif