diff options
| author | Casey Marshall <csm@gnu.org> | 2006-09-17 07:31:39 +0000 |
|---|---|---|
| committer | Casey Marshall <csm@gnu.org> | 2006-09-17 07:31:39 +0000 |
| commit | 133e014be0604b45f8ccede687acf1ea979d4955 (patch) | |
| tree | 03bfec201e509081586497b0e4db7944e633cab7 /gnu/java/nio/FileChannelImpl.java | |
| parent | a344c95abdd44f1c697d0520bf97ac3c8403a3b6 (diff) | |
| download | classpath-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/FileChannelImpl.java')
| -rw-r--r-- | gnu/java/nio/FileChannelImpl.java | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/gnu/java/nio/FileChannelImpl.java b/gnu/java/nio/FileChannelImpl.java new file mode 100644 index 000000000..419124050 --- /dev/null +++ b/gnu/java/nio/FileChannelImpl.java @@ -0,0 +1,572 @@ +/* FileChannelImpl.java -- + Copyright (C) 2002, 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. */ + + +package gnu.java.nio; + +import gnu.classpath.Configuration; +import gnu.java.nio.FileLockImpl; +import gnu.java.nio.VMChannel; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.NonReadableChannelException; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * This file is not user visible ! + * But alas, Java does not have a concept of friendly packages + * so this class is public. + * Instances of this class are created by invoking getChannel + * Upon a Input/Output/RandomAccessFile object. + */ +public final class FileChannelImpl extends FileChannel +{ + // These are mode values for open(). + public static final int READ = 1; + public static final int WRITE = 2; + public static final int APPEND = 4; + + // EXCL is used only when making a temp file. + public static final int EXCL = 8; + public static final int SYNC = 16; + public static final int DSYNC = 32; + + public static final FileChannelImpl in; + public static final FileChannelImpl out; + public static final FileChannelImpl err; + + //private static native void init(); + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javanio"); + } + + //init(); + + 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 + */ + private VMChannel ch; + + private int mode; + + final String description; + + /* Open a file. MODE is a combination of the above mode flags. */ + /* 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 IOException + { + return new FileChannelImpl(file, mode); + } + + private FileChannelImpl(File file, int mode) + throws IOException + { + String path = file.getPath(); + description = path; + this.mode = mode; + 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. + if (file.isDirectory()) + { + try + { + close(); + } + catch (IOException e) + { + /* ignore it */ + } + + throw new FileNotFoundException(description + " is a directory"); + } + } + + /** + * Constructor for default channels in, out and err. + * + * Used by init() (native code). + * + * @param fd the file descriptor (0, 1, 2 for stdin, stdout, stderr). + * + * @param mode READ or WRITE + */ + FileChannelImpl (VMChannel ch, int mode) + { + this.mode = mode; + this.description = "descriptor(" + ch.getState() + ")"; + this.ch = ch; + } + + public int available() throws IOException + { + return ch.available(); + } + + private long implPosition() throws IOException + { + return ch.position(); + } + + private void seek(long newPosition) throws IOException + { + ch.seek(newPosition); + } + + private void implTruncate(long size) throws IOException + { + ch.truncate(size); + } + + public void unlock(long pos, long len) throws IOException + { + ch.unlock(pos, len); + } + + public long size () throws IOException + { + return ch.size(); + } + + protected void implCloseChannel() throws IOException + { + ch.close(); + } + + /** + * Makes sure the Channel is properly closed. + */ + protected void finalize() throws IOException + { + if (ch.getState().isValid()) + close(); + } + + public int read (ByteBuffer dst) throws IOException + { + return ch.read(dst); + } + + public int read (ByteBuffer dst, long position) + throws IOException + { + if (position < 0) + throw new IllegalArgumentException ("position: " + position); + long oldPosition = implPosition (); + position (position); + int result = read(dst); + position (oldPosition); + + return result; + } + + public int read() throws IOException + { + return ch.read(); + } + + public long read (ByteBuffer[] dsts, int offset, int length) + throws IOException + { + return ch.readScattering(dsts, offset, length); + } + + public int write (ByteBuffer src) throws IOException + { + return ch.write(src); + } + + public int write (ByteBuffer src, long position) + throws IOException + { + if (position < 0) + throw new IllegalArgumentException ("position: " + position); + + if (!isOpen ()) + throw new ClosedChannelException (); + + if ((mode & WRITE) == 0) + throw new NonWritableChannelException (); + + int result; + long oldPosition; + + oldPosition = implPosition (); + seek (position); + result = write(src); + seek (oldPosition); + + return result; + } + + 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 MappedByteBuffer map (FileChannel.MapMode mode, + long position, long size) + throws IOException + { + char nmode = 0; + if (mode == MapMode.READ_ONLY) + { + nmode = 'r'; + if ((this.mode & READ) == 0) + throw new NonReadableChannelException(); + } + else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE) + { + nmode = mode == MapMode.READ_WRITE ? '+' : 'c'; + if ((this.mode & WRITE) != WRITE) + throw new NonWritableChannelException(); + if ((this.mode & READ) != READ) + throw new NonReadableChannelException(); + } + else + throw new IllegalArgumentException ("mode: " + mode); + + if (position < 0 || size < 0 || size > Integer.MAX_VALUE) + throw new IllegalArgumentException ("position: " + position + + ", size: " + size); + return ch.map(nmode, position, (int) size); + } + + /** + * msync with the disk + */ + public void force (boolean metaData) throws IOException + { + if (!isOpen ()) + throw new ClosedChannelException (); + + ch.flush(metaData); + } + + // like transferTo, but with a count of less than 2Gbytes + private int smallTransferTo (long position, int count, + WritableByteChannel target) + throws IOException + { + ByteBuffer buffer; + try + { + // Try to use a mapped buffer if we can. If this fails for + // any reason we'll fall back to using a ByteBuffer. + buffer = map (MapMode.READ_ONLY, position, count); + } + catch (IOException e) + { + buffer = ByteBuffer.allocate (count); + read (buffer, position); + buffer.flip(); + } + + return target.write (buffer); + } + + public long transferTo (long position, long count, + WritableByteChannel target) + throws IOException + { + if (position < 0 + || count < 0) + throw new IllegalArgumentException ("position: " + position + + ", count: " + count); + + if (!isOpen ()) + throw new ClosedChannelException (); + + if ((mode & READ) == 0) + throw new NonReadableChannelException (); + + final int pageSize = 65536; + long total = 0; + + while (count > 0) + { + int transferred + = smallTransferTo (position, (int)Math.min (count, pageSize), + target); + if (transferred < 0) + break; + total += transferred; + position += transferred; + count -= transferred; + } + + return total; + } + + // like transferFrom, but with a count of less than 2Gbytes + private int smallTransferFrom (ReadableByteChannel src, long position, + int count) + throws IOException + { + ByteBuffer buffer = null; + + if (src instanceof FileChannel) + { + try + { + // Try to use a mapped buffer if we can. If this fails + // for any reason we'll fall back to using a ByteBuffer. + buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position, + count); + } + catch (IOException e) + { + } + } + + if (buffer == null) + { + buffer = ByteBuffer.allocate ((int) count); + src.read (buffer); + buffer.flip(); + } + + return write (buffer, position); + } + + public long transferFrom (ReadableByteChannel src, long position, + long count) + throws IOException + { + if (position < 0 + || count < 0) + throw new IllegalArgumentException ("position: " + position + + ", count: " + count); + + if (!isOpen ()) + throw new ClosedChannelException (); + + if ((mode & WRITE) == 0) + throw new NonWritableChannelException (); + + final int pageSize = 65536; + long total = 0; + + while (count > 0) + { + int transferred = smallTransferFrom (src, position, + (int)Math.min (count, pageSize)); + if (transferred < 0) + break; + total += transferred; + position += transferred; + count -= transferred; + } + + return total; + } + + // Shared sanity checks between lock and tryLock methods. + private void lockCheck(long position, long size, boolean shared) + throws IOException + { + if (position < 0 + || size < 0) + throw new IllegalArgumentException ("position: " + position + + ", size: " + size); + + if (!isOpen ()) + throw new ClosedChannelException(); + + if (shared && ((mode & READ) == 0)) + throw new NonReadableChannelException(); + + if (!shared && ((mode & WRITE) == 0)) + throw new NonWritableChannelException(); + } + + public FileLock tryLock (long position, long size, boolean shared) + throws IOException + { + lockCheck(position, size, shared); + + boolean completed = false; + try + { + begin(); + boolean lockable = ch.lock(position, size, shared, false); + completed = true; + return (lockable + ? new FileLockImpl(this, position, size, shared) + : null); + } + finally + { + end(completed); + } + } + + public FileLock lock (long position, long size, boolean shared) + throws IOException + { + lockCheck(position, size, shared); + + boolean completed = false; + try + { + boolean lockable = ch.lock(position, size, shared, true); + completed = true; + return (lockable + ? new FileLockImpl(this, position, size, shared) + : null); + } + finally + { + end(completed); + } + } + + public long position () + throws IOException + { + if (!isOpen ()) + throw new ClosedChannelException (); + + return implPosition (); + } + + public FileChannel position (long newPosition) + throws IOException + { + if (newPosition < 0) + throw new IllegalArgumentException ("newPosition: " + newPosition); + + if (!isOpen ()) + throw new ClosedChannelException (); + + // FIXME note semantics if seeking beyond eof. + // We should seek lazily - only on a write. + seek (newPosition); + return this; + } + + public FileChannel truncate (long size) + throws IOException + { + if (size < 0) + throw new IllegalArgumentException ("size: " + size); + + if (!isOpen ()) + throw new ClosedChannelException (); + + if ((mode & WRITE) == 0) + throw new NonWritableChannelException (); + + if (size < size ()) + implTruncate (size); + + return this; + } + + public String toString() + { + return (super.toString() + + "[ fd: " + ch.getState() + + "; mode: " + Integer.toOctalString(mode) + + "; " + description + " ]"); + } + + /** + * @return The native file descriptor. + * / + public int getNativeFD() + { + return fd; + }*/ +} |
