From harmony-commits-return-875-apmail-incubator-harmony-commits-archive=incubator.apache.org@incubator.apache.org Fri Feb 10 14:00:39 2006 Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 28172 invoked from network); 10 Feb 2006 14:00:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 10 Feb 2006 14:00:26 -0000 Received: (qmail 52410 invoked by uid 500); 10 Feb 2006 14:00:15 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 52381 invoked by uid 500); 10 Feb 2006 14:00:15 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 52370 invoked by uid 99); 10 Feb 2006 14:00:15 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Feb 2006 06:00:15 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Fri, 10 Feb 2006 06:00:12 -0800 Received: (qmail 27079 invoked by uid 65534); 10 Feb 2006 13:59:38 -0000 Message-ID: <20060210135938.27032.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r376687 - in /incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java: com/ibm/io/nio/ com/ibm/platform/ com/ibm/platform/struct/ java/nio/ java/nio/channels/ java/nio/channels/spi/ Date: Fri, 10 Feb 2006 13:56:32 -0000 To: harmony-commits@incubator.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.6 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: tellison Date: Fri Feb 10 05:56:03 2006 New Revision: 376687 URL: http://svn.apache.org/viewcvs?rev=376687&view=rev Log: Applying patches received as HARMONY-42 (com.ibm.io.nio.FileChannel is not fully implemented) - refactoring of some java platform code - additional behavior on NIO file channels - refactoring of some IO code - work in progress on memory mapping Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/MappedByteBufferFactory.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadOnlyFileChannel.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadWriteFileChannel.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/WriteOnlyFileChannel.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java Removed: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedToByteBufferAdapter.java Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/FileChannelImpl.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IFileSystem.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IMemorySystem.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSFileSystem.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSMemory.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/struct/PlatformAddress.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/BufferFactory.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/ByteBuffer.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBuffer.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/FileLock.java incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/FileChannelImpl.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/FileChannelImpl.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/FileChannelImpl.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/FileChannelImpl.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +16,18 @@ package com.ibm.io.nio; +import java.io.Closeable; +import java.io.FileDescriptor; 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; - -import org.apache.harmony.luni.util.NotYetImplementedException; - import com.ibm.platform.IFileSystem; +import com.ibm.platform.IMemorySystem; import com.ibm.platform.Platform; import com.ibm.platform.struct.PlatformAddress; @@ -41,57 +39,44 @@ * This class is non-API, but implements the API of the FileChannel interface. * */ -public class FileChannelImpl extends FileChannel { +public abstract class FileChannelImpl extends FileChannel { // Reference to the portable file system code. private static final IFileSystem fileSystem = Platform.getFileSystem(); + private static final IMemorySystem memorySystem = Platform + .getMemorySystem(); + + private static final int NATIVE_PAGE_SIZE; + + static { + try { + NATIVE_PAGE_SIZE = fileSystem.getPageSize(); + } catch (IOException e) { + throw new Error(e); + } + + } + // Handle to the open file private final long handle; - /* - * The mode in which we are allowed to manipulate the underlying file. - * defined in the interface IFileSystem. - */ - private final int openMode; - // The object that will track all outstanding locks on this channel. private final LockManager lockManager = new LockManager(); private final Object repositioningLock = new Object(); - // Latch that shows when the underlying file has definitely been closed. - private boolean isClosed = false; + private final Object stream; /* * Create a new file channel implementation class that wraps the given file * handle and operates in the specififed mode. * */ - public FileChannelImpl(long handle, int openMode) { + public FileChannelImpl(Object stream, long handle) { super(); this.handle = handle; - this.openMode = openMode; - } - - private final boolean isReadOnly() { - return openMode == IFileSystem.O_RDONLY; - } - - private final boolean isWriteOnly() { - return openMode == IFileSystem.O_WRONLY; - } - - private final boolean isReadWrite() { - return openMode == IFileSystem.O_RDWR; - } - - private final boolean isReadable() { - return isReadOnly() || isReadWrite(); - } - - private final boolean isWritable() { - return isWriteOnly() || isReadWrite(); + this.stream = stream; } /* @@ -100,33 +85,20 @@ * be closed by operations beyond our control anyways. */ protected final void openCheck() throws ClosedChannelException { - if (isClosed) { + if (!isOpen()) { throw new ClosedChannelException(); } } - protected final void writeCheck() throws ClosedChannelException, - NonWritableChannelException { - openCheck(); - if (!isWritable()) { - throw new NonWritableChannelException(); - } - } - - protected final void readCheck() throws ClosedChannelException, - NonReadableChannelException { - openCheck(); - if (!isReadable()) { - throw new NonReadableChannelException(); - } - } - /* * (non-Javadoc) * * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel() */ - public void closeChannel() throws IOException { + protected void implCloseChannel() throws IOException { + if (stream instanceof Closeable) { + ((Closeable) stream).close(); + } fileSystem.close(handle); } @@ -136,15 +108,8 @@ throw new IllegalArgumentException( "Lock position and size must be non-negative."); //$NON-NLS-1$ } - int lockType; - if (shared) { - readCheck(); - lockType = IFileSystem.SHARED_LOCK_TYPE; - } else { - writeCheck(); - lockType = IFileSystem.EXCLUSIVE_LOCK_TYPE; - } - + int lockType = shared ? IFileSystem.SHARED_LOCK_TYPE + : IFileSystem.EXCLUSIVE_LOCK_TYPE; FileLock pendingLock = new FileLockImpl(this, position, size, shared); lockManager.addLock(pendingLock); @@ -163,9 +128,26 @@ * * @see java.nio.channels.FileChannel#lock(long, long, boolean) */ - public FileLock lock(long position, long size, boolean shared) + public final FileLock lock(long position, long size, boolean shared) throws IOException { - return basicLock(position, size, shared, true); + openCheck(); + FileLock resultLock = null; + { + boolean completed = true; + try { + begin(); + resultLock = basicLock(position, size, shared, true); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } + } + return resultLock; } /* @@ -174,8 +156,9 @@ * * @see java.nio.channels.FileChannel#tryLock(long, long, boolean) */ - public FileLock tryLock(long position, long size, boolean shared) + public final FileLock tryLock(long position, long size, boolean shared) throws IOException { + openCheck(); return basicLock(position, size, shared, false); } @@ -195,33 +178,28 @@ public void force(boolean metadata) throws IOException { openCheck(); // Forcing data-only on a read-only file is a no-op. - if (!metadata & isReadOnly()) { - return; - } - fileSystem.fflush(handle, metadata); - } - - public MappedByteBuffer map(MapMode mode, long position, long size) - throws IOException { - openCheck(); - - if (mode == null) { - throw new NullPointerException(); - } - int mapMode; - if (mode == MapMode.READ_ONLY) { - mapMode = IFileSystem.MMAP_READ_ONLY; - } else { - if (mode == MapMode.READ_WRITE) { - mapMode = IFileSystem.MMAP_READ_WRITE; - } else { - mapMode = IFileSystem.MMAP_WRITE_COPY; - } - } - PlatformAddress address = fileSystem.mmap(handle, position, size, - mapMode); - - throw new NotYetImplementedException(); + if (metadata) { + fileSystem.fflush(handle, metadata); + } + } + + public abstract MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException; + + protected final MappedByteBuffer mapImpl(int mapMode, long position, + long size) throws IOException { + long alignment = position - position % NATIVE_PAGE_SIZE; + int offset = (int) (position - alignment); + PlatformAddress address = memorySystem.mmap(handle, alignment, size + + offset, mapMode); + MappedByteBuffer buffer = null; + try { + buffer = MappedByteBufferFactory.getBuffer(address, mapMode, size, + offset); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + return buffer; } /* @@ -249,6 +227,7 @@ } public int read(ByteBuffer buffer, long position) throws IOException { + openCheck(); synchronized (repositioningLock) { int bytesRead = 0; long preReadPosition = position(); @@ -263,17 +242,46 @@ } public int read(ByteBuffer buffer) throws IOException { - readCheck(); - int bytesRead; + openCheck(); + boolean completed = true; + int bytesRead = 0; synchronized (repositioningLock) { if (buffer.isDirect()) { DirectBuffer directBuffer = (DirectBuffer) buffer; long address = directBuffer.getEffectiveAddress().toLong(); - bytesRead = (int) fileSystem.readDirect(handle, address, buffer - .remaining()); + try { + begin(); + /* + * if (bytesRead <= EOF) delt by read completed = false; + */ + bytesRead = (int) fileSystem.readDirect(handle, address, + buffer.position(), buffer.remaining()); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed && bytesRead >= 0); + } } else { - bytesRead = (int) fileSystem.read(handle, buffer.array(), - buffer.arrayOffset(), buffer.remaining()); + try { + begin(); + /* + * if (bytesRead <= EOF) delt by read completed = false; + */ + bytesRead = (int) fileSystem.read(handle, buffer.array(), + buffer.arrayOffset(), buffer.remaining()); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed && bytesRead >= 0); + } } if (bytesRead > 0) { buffer.position(buffer.position() + bytesRead); @@ -284,15 +292,81 @@ public long read(ByteBuffer[] buffers, int offset, int length) throws IOException { - readCheck(); - throw new NotYetImplementedException(); + openCheck(); + if (offset < 0 || length < 0 || offset + length > buffers.length) { + throw new IndexOutOfBoundsException(); + } + if (length == 0) { + return 0; + } + if (size() == 0) { + return -1; + } + ByteBuffer[] directBuffers = new ByteBuffer[length]; + long[] handles = new long[length]; + int[] offsets = new int[length]; + int[] lengths = new int[length]; + for (int i = 0; i < length; i++) { + ByteBuffer buffer = buffers[i + offset]; + if (!buffer.isDirect()) { + buffer = ByteBuffer.allocateDirect(buffer.remaining()); + directBuffers[i] = buffer; + offsets[i] = 0; + } else { + offsets[i] = buffer.position(); + } + handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toLong(); + lengths[i] = buffer.remaining(); + } + long bytesRead = 0; + { + boolean completed = true; + try { + begin(); + synchronized (repositioningLock) { + bytesRead = fileSystem.readv(handle, handles, offsets, + lengths, length); + + } + /* + * if (bytesRead < EOF) //delt by readv? completed = false; + */ + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } + } + int end = offset + length; + long bytesRemaining = bytesRead; + for (int i = offset; i < end && bytesRemaining > 0; i++) { + if (buffers[i].isDirect()) { + if (lengths[i] < bytesRemaining) { + int pos = buffers[i].limit(); + buffers[i].position(pos); + bytesRemaining -= lengths[i]; + } else { + int pos = (int) bytesRemaining; + buffers[i].position(pos); + break; + } + } else { + bytesRemaining -= directBuffers[i - offset].remaining(); + buffers[i].put(directBuffers[i - offset]); + } + } + return bytesRead; } /* * Answers the current file size, as an integer number of bytes. */ public long size() throws IOException { - readCheck(); + openCheck(); synchronized (repositioningLock) { long currentPosition = fileSystem.seek(handle, 0L, IFileSystem.SEEK_CUR); @@ -305,19 +379,93 @@ public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException { - writeCheck(); - throw new NotYetImplementedException(); + openCheck(); + if (!src.isOpen()) { + throw new ClosedChannelException(); + } + if (position < 0 || count < 0 || position > Integer.MAX_VALUE + || count > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + if (count == 0 || position > size()) { + return 0; + } + ByteBuffer buffer = null; + if (src instanceof FileChannel) { + FileChannel fileSrc = (FileChannel) src; + long size = fileSrc.size(); + long filePosition = fileSrc.position(); + count = Math.min(count, size - filePosition); + buffer = fileSrc.map(MapMode.READ_ONLY, filePosition, count); + } else { + buffer = ByteBuffer.allocateDirect((int) count); + src.read(buffer); + buffer.flip(); + } + return write(buffer, position); } public long transferTo(long position, long count, WritableByteChannel target) throws IOException { - readCheck(); - throw new NotYetImplementedException(); - } + openCheck(); + if (!target.isOpen()) { + throw new ClosedChannelException(); + } + if (position < 0 || count < 0 || position > Integer.MAX_VALUE + || count > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + if (count == 0 || position >= size()) { + return 0; + } + ByteBuffer buffer = null; +// if (target instanceof SocketChannelImpl +// || target instanceof DatagramChannelImpl) { +// // TODO: not implement yet +// // return kernelTransfer(handle, +// // ((FileChannelImpl) target).handle, position, count); +// } + count = Math.min(count, size() - position); + buffer = map(MapMode.READ_ONLY, position, count); + return target.write(buffer); + } + + private long kernelTransfer(long l, FileDescriptor fd, long position, + long count) throws IOException { + boolean completed = true; + try { + begin(); + return fileSystem.transfer(l, fd, position, count); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } + } public FileChannel truncate(long size) throws IOException { - writeCheck(); - throw new NotYetImplementedException(); + openCheck(); + if (size < 0) { + throw new IllegalArgumentException(); + } + if (size < size()) { + synchronized (repositioningLock) { + long position = position(); + fileSystem.truncate(handle, size); + /* + * FIXME: currently the port library always modifies the + * position to given size. not sure it is a bug or intended + * behaviour, so I always reset the position to proper value as + * Java Spec. + */ + position(position > size ? size : position); + } + } + return this; } /* @@ -327,31 +475,59 @@ */ public int write(ByteBuffer buffer, long position) throws IOException { + openCheck(); + int bytesWritten = 0; synchronized (repositioningLock) { - int bytesWritten = 0; long preWritePosition = position(); position(position); try { - bytesWritten = write(buffer); + bytesWritten = writeImpl(buffer); } finally { position(preWritePosition); } - return bytesWritten; } + return bytesWritten; } - public int write(ByteBuffer buffer) throws IOException { - writeCheck(); + public int write(ByteBuffer buffer) throws IOException { + openCheck(); + return writeImpl(buffer); + } + + private int writeImpl(ByteBuffer buffer) throws IOException { int bytesWritten; + boolean completed = true; synchronized (repositioningLock) { if (buffer.isDirect()) { DirectBuffer directBuffer = (DirectBuffer) buffer; long address = directBuffer.getEffectiveAddress().toLong(); - bytesWritten = (int) fileSystem.writeDirect(handle, address, - buffer.remaining()); + try { + begin(); + bytesWritten = (int) fileSystem.writeDirect(handle, + address, buffer.position(), buffer.remaining()); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } } else { - bytesWritten = (int) fileSystem.write(handle, buffer - .array(), buffer.arrayOffset(), buffer.remaining()); + try { + begin(); + bytesWritten = (int) fileSystem.write(handle, buffer + .array(), buffer.arrayOffset(), buffer.remaining()); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } } if (bytesWritten > 0) { buffer.position(buffer.position() + bytesWritten); @@ -362,7 +538,62 @@ public long write(ByteBuffer[] buffers, int offset, int length) throws IOException { - writeCheck(); - throw new NotYetImplementedException(); - } + openCheck(); + if (offset < 0 || length < 0 || offset + length > buffers.length) { + throw new IndexOutOfBoundsException(); + } + if (length == 0) { + return 0; + } + long[] handles = new long[length]; + int[] offsets = new int[length]; + int[] lengths = new int[length]; + for (int i = 0; i < length; i++) { + ByteBuffer buffer = buffers[i + offset]; + if (!buffer.isDirect()) { + ByteBuffer directBuffer = ByteBuffer.allocateDirect(buffer + .remaining()); + directBuffer.put(buffer); + directBuffer.flip(); + buffer = directBuffer; + offsets[i] = 0; + } else { + offsets[i] = buffer.position(); + } + handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toLong(); + lengths[i] = buffer.remaining(); + } + + long bytesWritten = 0; + boolean completed = true; + synchronized (repositioningLock) { + try { + begin(); + bytesWritten = fileSystem.writev(handle, handles, offsets, + lengths, length); + } catch (IOException e) { + completed = false; + throw e; + } catch (RuntimeException e) { + completed = false; + throw e; + } finally { + end(completed); + } + } + + long bytesRemaining = bytesWritten; + for (int i = offset; i < length; i++) { + if (bytesRemaining > buffers[i].remaining()) { + int pos = buffers[i].limit(); + buffers[i].position(pos); + bytesRemaining -= buffers[i].remaining(); + } else { + int pos = buffers[i].position() + (int) bytesRemaining; + buffers[i].position(pos); + break; + } + } + return bytesWritten; + } } Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/MappedByteBufferFactory.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/MappedByteBufferFactory.java?rev=376687&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/MappedByteBufferFactory.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/MappedByteBufferFactory.java Fri Feb 10 05:56:03 2006 @@ -0,0 +1,61 @@ +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ibm.io.nio; + +import java.lang.reflect.Constructor; +import java.nio.MappedByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import com.ibm.platform.struct.PlatformAddress; + +class MappedByteBufferFactory { + + static final Constructor constructor; + + static { + constructor = (Constructor) AccessController + .doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class wrapperClazz = ClassLoader + .getSystemClassLoader().loadClass( + "java.nio.MappedByteBufferAdapter"); //$NON-NLS-1$ + Constructor result = wrapperClazz + .getConstructor(new Class[] { + PlatformAddress.class, int.class, + int.class, int.class }); + result.setAccessible(true); + return result; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } + + static MappedByteBuffer getBuffer(PlatformAddress addr, int mapmode, + long size, int offset) throws Exception { + // FIXME: the long->int cast of size may be dangerous, but JavaSpec + // specifies that the mmap size cannot be larger than + // Integer.MAX_VALUE, may since the direct buffer only supports size of + // 32 bits. Maybe int the later version(i.e. 64 bit platform) + // this issue can be handled more elegantly + return (MappedByteBuffer) constructor.newInstance(new Object[] { addr, + new Integer((int) size), new Integer(offset), + new Integer(mapmode) }); + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadOnlyFileChannel.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadOnlyFileChannel.java?rev=376687&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadOnlyFileChannel.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadOnlyFileChannel.java Fri Feb 10 05:56:03 2006 @@ -0,0 +1,89 @@ +/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.io.nio; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.ReadableByteChannel; + +import com.ibm.platform.IMemorySystem; + +public final class ReadOnlyFileChannel extends FileChannelImpl { + public ReadOnlyFileChannel(Object stream, long handle) { + super(stream, handle); + } + + public final int write(ByteBuffer buffer, long position) throws IOException { + openCheck(); + throw new NonWritableChannelException(); + } + + public final int write(ByteBuffer buffer) throws IOException { + openCheck(); + throw new NonWritableChannelException(); + } + + public final long write(ByteBuffer[] buffers, int offset, int length) + throws IOException { + openCheck(); + throw new NonWritableChannelException(); + } + + public final FileChannel truncate(long size) throws IOException { + openCheck(); + throw new NonWritableChannelException(); + } + + public final long transferFrom(ReadableByteChannel src, long position, + long count) throws IOException { + openCheck(); + if (null == src) { + throw new NullPointerException(); + } + throw new NonWritableChannelException(); + } + + public final MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException { + openCheck(); + if (mode == null) { + throw new NullPointerException(); + } + if (position < 0 || size < 0 || size > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + if (mode != MapMode.READ_ONLY) { + throw new NonWritableChannelException(); + } + return super.mapImpl(IMemorySystem.MMAP_READ_ONLY, position, size); + } + + public final void force(boolean metadata) throws IOException { + openCheck(); + return; + } + + protected final FileLock basicLock(long position, long size, + boolean shared, boolean wait) throws IOException { + if (!shared) { + throw new NonWritableChannelException(); + } + return super.basicLock(position, size, shared, true); + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadWriteFileChannel.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadWriteFileChannel.java?rev=376687&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadWriteFileChannel.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/ReadWriteFileChannel.java Fri Feb 10 05:56:03 2006 @@ -0,0 +1,46 @@ +/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.io.nio; + +import java.io.IOException; +import java.nio.MappedByteBuffer; + +import com.ibm.platform.IMemorySystem; + +public final class ReadWriteFileChannel extends FileChannelImpl { + public ReadWriteFileChannel(Object stream, long handle) { + super(stream, handle); + } + + public final MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException { + openCheck(); + if (mode == null) { + throw new NullPointerException(); + } + if (position < 0 || size < 0 || size > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + int mapMode; + if (mode == MapMode.READ_ONLY) { + mapMode = IMemorySystem.MMAP_READ_ONLY; + } else if (mode == MapMode.READ_WRITE) { + mapMode = IMemorySystem.MMAP_READ_WRITE; + } else { + mapMode = IMemorySystem.MMAP_WRITE_COPY; + } + return mapImpl(mapMode, position, size); + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/WriteOnlyFileChannel.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/WriteOnlyFileChannel.java?rev=376687&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/WriteOnlyFileChannel.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/io/nio/WriteOnlyFileChannel.java Fri Feb 10 05:56:03 2006 @@ -0,0 +1,89 @@ +/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.io.nio; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileLock; +import java.nio.channels.NonReadableChannelException; +import java.nio.channels.WritableByteChannel; + +public final class WriteOnlyFileChannel extends FileChannelImpl { + + private boolean append = false; + + public WriteOnlyFileChannel(Object stream, long handle) { + super(stream, handle); + } + + public WriteOnlyFileChannel(Object stream, long handle, boolean isAppend) { + super(stream, handle); + append = isAppend; + } + + public long transferTo(long position, long count, WritableByteChannel target) + throws IOException { + openCheck(); + if (null == target) { + throw new NullPointerException(); + } + throw new NonReadableChannelException(); + } + + public long read(ByteBuffer[] buffers, int offset, int length) + throws IOException { + openCheck(); + throw new NonReadableChannelException(); + } + + public int read(ByteBuffer buffer) throws IOException { + openCheck(); + throw new NonReadableChannelException(); + } + + public int read(ByteBuffer buffer, long position) throws IOException { + openCheck(); + throw new NonReadableChannelException(); + } + + public MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException { + openCheck(); + if (mode == null) { + throw new NullPointerException(); + } + if (position < 0 || size < 0 || size > Integer.MAX_VALUE) { + throw new IllegalArgumentException(); + } + throw new NonReadableChannelException(); + } + + public int write(ByteBuffer buffer) throws IOException { + if (append) { + position(size()); + } + return super.write(buffer); + } + + protected final FileLock basicLock(long position, long size, + boolean shared, boolean wait) throws IOException { + if (shared) { + throw new NonReadableChannelException(); + } + return super.basicLock(position, size, shared, true); + } + +} Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IFileSystem.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IFileSystem.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IFileSystem.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IFileSystem.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,10 @@ package com.ibm.platform; - +import java.io.FileDescriptor; +import java.io.FileNotFoundException; import java.io.IOException; -import com.ibm.platform.struct.PlatformAddress; - /** * TODO Type description * @@ -36,12 +35,6 @@ public final int SEEK_END = 4; - public final int MMAP_READ_ONLY = 1; - - public final int MMAP_READ_WRITE = 2; - - public final int MMAP_WRITE_COPY = 4; - public final int O_RDONLY = 0x00000000; public final int O_WRONLY = 0x00000001; @@ -66,18 +59,18 @@ public long write(long fileDescriptor, byte[] bytes, int offset, int length) throws IOException; - public long readv(long fileDescriptor, byte[] bytes, int[] offsets, - int[] lengths) throws IOException; + public long readv(long fileDescriptor, long[] addresses, int[] offsets, + int[] lengths, int size) throws IOException; - public long writev(long fileDescriptor, byte[] bytes, int[] offsets, - int[] lengths) throws IOException; + public long writev(long fileDescriptor, long[] addresses, int[] offsets, + int[] lengths, int size) throws IOException; // Required to support direct byte buffers - public long readDirect(long fileDescriptor, long address, int length) - throws IOException; + public long readDirect(long fileDescriptor, long address, int offset, + int length) throws IOException; - public long writeDirect(long fileDescriptor, long address, int length) - throws IOException; + public long writeDirect(long fileDescriptor, long address, int offset, + int length) throws IOException; public boolean lock(long fileDescriptor, long start, long length, int type, boolean waitFlag) throws IOException; @@ -91,8 +84,15 @@ public void fflush(long fileDescriptor, boolean metadata) throws IOException; - public PlatformAddress mmap(long fileDescriptor, long offset, long size, - int mapMode) throws IOException; - public void close(long fileDescriptor) throws IOException; + + public void truncate(long fileDescriptor, long size) throws IOException; + + public int getPageSize() throws IOException; + + public long open(byte[] fileName, int mode) throws FileNotFoundException; + + public long transfer(long fileHandler, FileDescriptor socketDescriptor, + long offset, long count) throws IOException; + } Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IMemorySystem.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IMemorySystem.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IMemorySystem.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/IMemorySystem.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,11 @@ * limitations under the License. */ -package com.ibm.platform; +package com.ibm.platform; +import java.io.IOException; + +import com.ibm.platform.struct.PlatformAddress; /** * IMemorySystem @@ -22,6 +25,12 @@ */ public interface IMemorySystem { + public final int MMAP_READ_ONLY = 1; + + public final int MMAP_READ_WRITE = 2; + + public final int MMAP_WRITE_COPY = 4; + /** * Answers true if the platform is little endian, otherwise it may be * assumed to be big endian.. @@ -392,4 +401,41 @@ * the value of the platform pointer as a Java long. */ public void setAddress(long address, long value); + + /** + * TODO: JavaDoc + * + * @param fileDescriptor + * @param alignment + * @param size + * @param mapMode + * @return + * @throws IOException + */ + public PlatformAddress mmap(long fileDescriptor, long alignment, long size, + int mapMode) throws IOException; + + /** + * TODO: JavaDoc + * + * @param addr + * @throws IOException + */ + public void unmap(PlatformAddress addr); + + /** + * TODO: JavaDoc + */ + public void load(PlatformAddress addr, long size); + + /** + * TODO: JavaDoc + */ + public boolean isLoaded(PlatformAddress addr, long size); + + /** + * TODO : JavaDoc + */ + public void flush(PlatformAddress addr, long size); + } Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSFileSystem.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSFileSystem.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSFileSystem.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSFileSystem.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +15,10 @@ package com.ibm.platform; - +import java.io.FileDescriptor; +import java.io.FileNotFoundException; import java.io.IOException; -import org.apache.harmony.luni.util.NotYetImplementedException; - -import com.ibm.platform.struct.PlatformAddress; - /** * This is the portable implementation of the file system interface. * @@ -33,7 +30,6 @@ */ public OSFileSystem() { super(); - // Auto-generated constructor stub } private final void validateLockArgs(int type, long start, long length) { @@ -58,6 +54,8 @@ private native int lockImpl(long fileDescriptor, long start, long length, int type, boolean wait); + public native int getPageSize(); + public boolean lock(long fileDescriptor, long start, long length, int type, boolean waitFlag) throws IOException { // Validate arguments @@ -107,11 +105,11 @@ * Direct read/write APIs work on addresses. */ private native long readDirectImpl(long fileDescriptor, long address, - int length); + int offset, int length); - public long readDirect(long fileDescriptor, long address, int length) - throws IOException { - long bytesRead = readDirectImpl(fileDescriptor, address, length); + public long readDirect(long fileDescriptor, long address, int offset, + int length) throws IOException { + long bytesRead = readDirectImpl(fileDescriptor, address, offset, length); if (bytesRead < -1) { throw new IOException(); } @@ -119,12 +117,13 @@ } private native long writeDirectImpl(long fileDescriptor, long address, - int length); + int offset, int length); - public long writeDirect(long fileDescriptor, long address, int length) - throws IOException { - long bytesWritten = writeDirectImpl(fileDescriptor, address, length); - if (bytesWritten < -1) { + public long writeDirect(long fileDescriptor, long address, int offset, + int length) throws IOException { + long bytesWritten = writeDirectImpl(fileDescriptor, address, offset, + length); + if (bytesWritten < 0) { throw new IOException(); } return bytesWritten; @@ -145,43 +144,47 @@ return bytesRead; } + private native long writeImpl(long fileDescriptor, byte[] bytes, + int offset, int length); + public long write(long fileDescriptor, byte[] bytes, int offset, int length) throws IOException { - // Auto-generated method stub - throw new NotYetImplementedException(); + long bytesWritten = writeImpl(fileDescriptor, bytes, offset, length); + if (bytesWritten < 0) { + throw new IOException(); + } + return bytesWritten; } /* * Scatter/gather calls. */ - public long readv(long fileDescriptor, byte[] bytes, int[] offsets, - int[] lengths) throws IOException { - // Auto-generated method stub - throw new NotYetImplementedException(); - } - - public long writev(long fileDescriptor, byte[] bytes, int[] offsets, - int[] lengths) throws IOException { - // Auto-generated method stub - throw new NotYetImplementedException(); + public long readv(long fileDescriptor, long[] addresses, int[] offsets, + int[] lengths, int size) throws IOException { + long bytesRead = readvImpl(fileDescriptor, addresses, offsets, lengths, + size); + if (bytesRead < -1) { + throw new IOException(); + } + return bytesRead; } - /* - * Memory mapped file - */ - private native long mmapImpl(long fileDescriptor, long offset, long size, - int mapMode); + private native long readvImpl(long fileDescriptor, long[] addresses, + int[] offsets, int[] lengths, int size); - public PlatformAddress mmap(long fileDescriptor, long offset, long size, - int mapMode) throws IOException { - long address = mmapImpl(fileDescriptor, offset, size, mapMode); - if (address == -1) { + public long writev(long fileDescriptor, long[] addresses, int[] offsets, + int[] lengths, int size) throws IOException { + long bytesWritten = writevImpl(fileDescriptor, addresses, offsets, + lengths, size); + if (bytesWritten < 0) { throw new IOException(); } - return PlatformAddress.on(address); - + return bytesWritten; } + private native long writevImpl(long fileDescriptor, long[] addresses, + int[] offsets, int[] lengths, int size); + private native int closeImpl(long fileDescriptor); /* @@ -195,4 +198,38 @@ throw new IOException(); } } + + public void truncate(long fileDescriptor, long size) throws IOException { + int rc = truncateImpl(fileDescriptor, size); + if (rc < 0) { + throw new IOException(); + } + } + + private native int truncateImpl(long fileDescriptor, long size); + + public long open(byte[] fileName, int mode) throws FileNotFoundException { + if (fileName == null) { + throw new NullPointerException(); + } + long handler = openImpl(fileName, mode); + if (handler < 0) { + throw new FileNotFoundException(); + } + return handler; + } + + private native long openImpl(byte[] fileName, int mode); + + public long transfer(long fileHandler, FileDescriptor socketDescriptor, + long offset, long count) throws IOException { + long result = transferImpl(fileHandler, socketDescriptor, offset, count); + if (result < 0) + throw new IOException(); + return result; + } + + private native long transferImpl(long fileHandler, + FileDescriptor socketDescriptor, long offset, long count); + } Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSMemory.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSMemory.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSMemory.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/OSMemory.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,13 @@ * limitations under the License. */ -package com.ibm.platform; +package com.ibm.platform; + +import java.io.IOException; + +import org.apache.harmony.luni.util.NotYetImplementedException; + +import com.ibm.platform.struct.PlatformAddress; // import com.ibm.oti.vm.VM; @@ -53,6 +59,8 @@ private static final OSMemory singleton = new OSMemory(); static { + // FIXME: OSMemory, OSFileSystem, OSNetwork, should be moved to luni + System.loadLibrary("hynio"); POINTER_SIZE = getPointerSizeImpl(); if (isLittleEndianImpl()) { @@ -530,6 +538,49 @@ * the value of the platform pointer as a Java long. */ public native void setAddress(long address, long value); + + /* + * Memory mapped file + */ + private native long mmapImpl(long fileDescriptor, long alignment, + long size, int mapMode); + + public PlatformAddress mmap(long fileDescriptor, long alignment, long size, + int mapMode) throws IOException { + throw new NotYetImplementedException(); +// long address = mmapImpl(fileDescriptor, alignment, size, mapMode); +// if (address == -1) { +// throw new IOException(); +// } +// return PlatformAddress.on(address, true); + } + + private native void unmapImpl(long addr); + + public void unmap(PlatformAddress addr) { + long osAddr = addr.toLong(); + unmapImpl(osAddr); + } + + public void load(PlatformAddress addr, long size) { + // WIN32: virtualLock, need + // Linux: + loadImpl(addr.toLong(), size); + } + + private native int loadImpl(long l, long size); + + public boolean isLoaded(PlatformAddress addr, long size) { + return size == 0 ? true : isLoadedImpl(addr.toLong(), size); + } + + private native boolean isLoadedImpl(long l, long size); + + public void flush(PlatformAddress addr, long size) { + flushImpl(addr.toLong(), size); + } + + private native int flushImpl(long l, long size); /* * Helper methods to change byte order. Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/struct/PlatformAddress.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/struct/PlatformAddress.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/struct/PlatformAddress.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/com/ibm/platform/struct/PlatformAddress.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package com.ibm.platform.struct; - import com.ibm.platform.Endianness; import com.ibm.platform.IMemorySystem; import com.ibm.platform.Platform; @@ -42,12 +41,24 @@ private final long osaddr; + private final boolean isMappedAddress; + public static PlatformAddress on(PlatformAddress other) { - return new PlatformAddress(other.osaddr); + return new PlatformAddress(other.osaddr, other.isMappedAddress); } public static PlatformAddress on(long value) { - return (value == 0) ? NULL : new PlatformAddress(value); + return (value == 0) ? NULL : new PlatformAddress(value, false); + } + + public static PlatformAddress on(long value, boolean isMapped) { + PlatformAddress addr = (value == 0) ? NULL : new PlatformAddress(value, + isMapped); + if (isMapped) { + // FIXME: some platform need the size to unmap/free, fix it + memorySpy.alloc(addr, 0); + } + return addr; } public static PlatformAddress alloc(long size) { @@ -58,8 +69,13 @@ } public PlatformAddress(long address) { + this(address, false); + } + + public PlatformAddress(long address, boolean isMapped) { super(); - this.osaddr = address; + osaddr = address; + isMappedAddress = isMapped; } /** @@ -102,6 +118,9 @@ // Memory spys can veto the basic free if they determine the memory was // not allocated. if (memorySpy.free(this)) { + if (isMappedAddress) { + unmap(); + } osMemory.free(osaddr); } } @@ -118,26 +137,28 @@ return PlatformAddress.on(addr); } - public void setByteArray(int offset, byte[] bytes, int bytesOffset, int length) { - memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE); - osMemory.setByteArray(osaddr + offset, bytes, bytesOffset, length); - } - - public void getByteArray(int offset, byte[] bytes, int bytesOffset, int length) { - memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE); - osMemory.getByteArray(osaddr + offset, bytes, bytesOffset, length); - } - public void setByte(int offset, byte value) { memorySpy.rangeCheck(this, offset, SIZEOF_JBYTE); osMemory.setByte(osaddr + offset, value); } + public void setByteArray(int offset, byte[] bytes, int bytesOffset, + int length) { + memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE); + osMemory.setByteArray(osaddr + offset, bytes, bytesOffset, length); + } + public byte getByte(int offset) { memorySpy.rangeCheck(this, offset, SIZEOF_JBYTE); return osMemory.getByte(osaddr + offset); } + public void getByteArray(int offset, byte[] bytes, int bytesOffset, + int length) { + memorySpy.rangeCheck(this, offset, length * SIZEOF_JBYTE); + osMemory.getByteArray(osaddr + offset, bytes, bytesOffset, length); + } + public void setShort(int offset, short value, Endianness order) { memorySpy.rangeCheck(this, offset, SIZEOF_JSHORT); osMemory.setShort(osaddr + offset, value, order); @@ -236,6 +257,25 @@ public double getDouble(int offset) { memorySpy.rangeCheck(this, offset, SIZEOF_JDOUBLE); return osMemory.getDouble(osaddr + offset); + } + + public void mmapLoad(long size) { + memorySpy.rangeCheck(this, 0, (int) size * SIZEOF_JBYTE); + osMemory.load(this, size); + } + + public boolean mmapIsLoaded(long size) { + memorySpy.rangeCheck(this, 0, (int) size * SIZEOF_JBYTE); + return osMemory.isLoaded(this, size); + } + + public void mmapFlush(long size) { + memorySpy.rangeCheck(this, 0, (int) size * SIZEOF_JBYTE); + osMemory.flush(this, size); + } + + public void unmap() { + osMemory.unmap(this); } public long toLong() { Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/BufferFactory.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/BufferFactory.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/BufferFactory.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/BufferFactory.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,6 @@ package java.nio; -import java.io.File; -import java.nio.channels.FileChannel.MapMode; - /** * Provide factory service of buffer classes. *

@@ -182,24 +179,6 @@ */ public static LongBuffer newLongBuffer(long array[]) { return new ReadWriteLongArrayBuffer(array); - } - - /** - * Returns a new byte buffer mapped to the specified region of file. - * - * @param mappedFile - * The file to be mapped - * @param offset - * The offset of the region - * @param size - * The size of the region - * @param mapMode - * The map mode - * @return A new byte buffer mapped to the specified region of file. - */ - public static MappedByteBuffer newMappedByteBuffer(File mappedFile, - long offset, int size, MapMode mapMode) { - return new MappedToByteBufferAdapter(mappedFile, offset, size, mapMode); } /** Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/ByteBuffer.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/ByteBuffer.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/ByteBuffer.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/ByteBuffer.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -689,10 +689,10 @@ * @return This buffer */ public final ByteBuffer order(ByteOrder byteOrder) { - /* - * This method is not 'final', because MappedToByteBufferAdapter - * needs to override this method. - */ + return orderImpl(byteOrder); + } + + ByteBuffer orderImpl(ByteOrder byteOrder) { if (byteOrder == null) { throw new NullPointerException(); } Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBuffer.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBuffer.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBuffer.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBuffer.java Fri Feb 10 05:56:03 2006 @@ -15,11 +15,9 @@ package java.nio; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel.MapMode; +import com.ibm.io.nio.DirectBuffer; +import com.ibm.platform.IMemorySystem; +import com.ibm.platform.struct.PlatformAddress; /** * MappedByteBuffer is a special kind of direct byte buffer, @@ -40,105 +38,35 @@ */ public abstract class MappedByteBuffer extends ByteBuffer { - /** - * The map mode used when creating this buffer. - */ - final MapMode mapMode; - - /** - * The mapped file. - */ - final File mappedFile; - - /** - * The offset of the mapped region. The size of the mapped region is defined - * by capacity. - */ - final long offset; - - /** - * The wrapped byte buffer. - */ - final ByteBuffer wrappedBuffer; - - /** - * Create a new mapped byte buffer, mapping to the specified region of file. - * A new direct byte buffer will be allocated. - * - * @param mappedFile - * @param offset - * @param size - * @param mapMode - */ - MappedByteBuffer(File mappedFile, long offset, int size, - MapMode mapMode) { - super(size); - this.mappedFile = mappedFile; - this.offset = offset; - this.mapMode = mapMode; - this.wrappedBuffer = ByteBuffer.allocateDirect(size); - - load(); - } + final DirectByteBuffer wrapped; - /** - * Create a new mapped byte buffer, mapping to the specified region of file. - * The specified byte buffer is used. - * - * @param mappedFile - * @param offset - * @param size - * @param mapMode - * @param wrappedBuffer - */ - MappedByteBuffer(File mappedFile, long offset, int size, - MapMode mapMode, ByteBuffer wrappedBuffer) { - super(size); - this.mappedFile = mappedFile; - this.offset = offset; - this.mapMode = mapMode; - this.wrappedBuffer = wrappedBuffer; - this.wrappedBuffer.clear(); - - if (wrappedBuffer.capacity() != size) { - throw new IllegalArgumentException(); - } - } + private int mapMode; - /** - * Writes all changes made to this buffer's content back to the file. - *

- * If this buffer is not mapped in read/write mode, then this method does - * nothing. - *

- * - * @return This buffer - */ - public final MappedByteBuffer force() { - // TODO re-impl in a direct way - if (mapMode == MapMode.READ_WRITE) { - RandomAccessFile accessFile = null; - try { - accessFile = new RandomAccessFile(mappedFile, "rw"); //$NON-NLS-1$ - accessFile.seek(offset); - for (int i = 0; i < capacity; i++) { - accessFile.writeByte(wrappedBuffer.get(i)); - } - } catch (IOException e) { - // javadoc does not specify how to report this exception - e.printStackTrace(); - } finally { - if (accessFile != null) { - try { - accessFile.close(); - } catch (IOException e) { - // nothing to do - } - } - } - } - return this; - } + MappedByteBuffer(ByteBuffer directBuffer) { + super(directBuffer.capacity); + if (!directBuffer.isDirect()) { + throw new IllegalArgumentException(); + } + this.wrapped = (DirectByteBuffer) directBuffer; + + } + + MappedByteBuffer(PlatformAddress addr, int capa, int offset, int mode) { + super(capa); + mapMode = mode; + switch (mapMode) { + case IMemorySystem.MMAP_READ_ONLY: + wrapped = new ReadOnlyDirectByteBuffer(addr, capa, offset); + break; + case IMemorySystem.MMAP_READ_WRITE: + case IMemorySystem.MMAP_WRITE_COPY: + wrapped = new ReadWriteDirectByteBuffer(addr, capa, offset); + break; + default: + throw new IllegalArgumentException(); + } + addr.autoFree(); + } /** * Returns true if this buffer's content is loaded. @@ -146,7 +74,8 @@ * @return True if this buffer's content is loaded. */ public final boolean isLoaded() { - return true; + return ((DirectBuffer) wrapped).getEffectiveAddress().mmapIsLoaded( + wrapped.capacity()); } /** @@ -155,27 +84,20 @@ * @return This buffer */ public final MappedByteBuffer load() { - // TODO re-impl in a direct way - RandomAccessFile accessFile = null; - try { - accessFile = new RandomAccessFile(mappedFile, "r"); //$NON-NLS-1$ - accessFile.seek(offset); - for (int i = 0; i < capacity; i++) { - wrappedBuffer.put(i, accessFile.readByte()); - } - } catch (IOException e) { - // javadoc does not specify how to report this exception - e.printStackTrace(); - } finally { - if (accessFile != null) { - try { - accessFile.close(); - } catch (IOException e) { - // nothing to do - } - } - } + ((DirectBuffer) wrapped).getEffectiveAddress().mmapLoad( + wrapped.capacity()); return this; } + /** + * TODO: JavaDoc + * @return + */ + public final MappedByteBuffer force() { + if (mapMode == IMemorySystem.MMAP_READ_WRITE) { + ((DirectBuffer) wrapped).getEffectiveAddress().mmapFlush( + wrapped.capacity()); + } + return this; + } } Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java?rev=376687&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java Fri Feb 10 05:56:03 2006 @@ -0,0 +1,363 @@ +/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.nio; + +import com.ibm.io.nio.DirectBuffer; +import com.ibm.platform.struct.PlatformAddress; + +class MappedByteBufferAdapter extends MappedByteBuffer implements DirectBuffer { + + public MappedByteBufferAdapter(ByteBuffer buffer) { + super(buffer); + } + + public MappedByteBufferAdapter(PlatformAddress addr, int capa, int offset, + int mode) { + super(addr, capa, offset, mode); + } + + public CharBuffer asCharBuffer() { + return this.wrapped.asCharBuffer(); + } + + public DoubleBuffer asDoubleBuffer() { + return this.wrapped.asDoubleBuffer(); + } + + public FloatBuffer asFloatBuffer() { + return this.wrapped.asFloatBuffer(); + } + + public IntBuffer asIntBuffer() { + return this.wrapped.asIntBuffer(); + } + + public LongBuffer asLongBuffer() { + return this.wrapped.asLongBuffer(); + } + + public ByteBuffer asReadOnlyBuffer() { + MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped + .asReadOnlyBuffer()); + buf.limit = this.limit; + buf.position = this.position; + buf.mark = this.mark; + return buf; + } + + public ShortBuffer asShortBuffer() { + return this.wrapped.asShortBuffer(); + } + + public ByteBuffer compact() { + if (this.wrapped.isReadOnly()) { + throw new ReadOnlyBufferException(); + } + this.wrapped.limit(this.limit); + this.wrapped.position(this.position); + this.wrapped.compact(); + this.wrapped.clear(); + this.position = this.limit - this.position; + this.limit = this.capacity; + this.mark = UNSET_MARK; + return this; + } + + public ByteBuffer duplicate() { + MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped + .duplicate()); + buf.limit = this.limit; + buf.position = this.position; + buf.mark = this.mark; + return buf; + } + + public byte get() { + if (this.position == this.limit) { + throw new BufferUnderflowException(); + } + return this.wrapped.get(this.position++); + } + + public byte get(int index) { + return this.wrapped.get(index); + } + + // FIXME Need synchronization as far as the update of this.position is + // concerned of the following methods? Spec does not say whether + // MappedByteBuffer + // is thread safe. It is the decision we should make. + public char getChar() { + int newPosition = this.position + 2; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + char result = this.wrapped.getChar(this.position); + this.position = newPosition; + return result; + } + + public char getChar(int index) { + return this.wrapped.getChar(index); + } + + // FIXME use fields defined in ISystemType class instead of magic number? + public double getDouble() { + int newPosition = this.position + 8; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + double result = this.wrapped.getDouble(this.position); + this.position = newPosition; + return result; + } + + public double getDouble(int index) { + return this.wrapped.getDouble(index); + } + + public PlatformAddress getEffectiveAddress() { + return ((DirectBuffer) this.wrapped).getEffectiveAddress(); + } + + public float getFloat() { + int newPosition = this.position + 4; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + float result = this.wrapped.getFloat(this.position); + this.position = newPosition; + return result; + } + + public float getFloat(int index) { + return this.wrapped.getFloat(index); + } + + public int getInt() { + int newPosition = this.position + 4; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + int result = this.wrapped.getInt(this.position); + this.position = newPosition; + return result; + } + + public int getInt(int index) { + return this.wrapped.getInt(index); + } + + public long getLong() { + int newPosition = this.position + 8; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + long result = this.wrapped.getLong(this.position); + this.position = newPosition; + return result; + } + + public long getLong(int index) { + return this.wrapped.getLong(index); + } + + public short getShort() { + int newPosition = this.position + 2; + if (newPosition > this.limit) { + throw new BufferUnderflowException(); + } + short result = this.wrapped.getShort(this.position); + this.position = newPosition; + return result; + } + + public short getShort(int index) { + return this.wrapped.getShort(index); + } + + public boolean isDirect() { + return true; + } + + public boolean isReadOnly() { + return this.wrapped.isReadOnly(); + } + + ByteBuffer orderImpl(ByteOrder byteOrder) { + super.orderImpl(byteOrder); + return this.wrapped.order(byteOrder); + } + + // FIXME: This method also has the synchronization problem. + public ByteBuffer put(byte b) { + if (this.position == this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.put(this.position++, b); + return this; + } + + public ByteBuffer put(byte[] src, int off, int len) { + this.wrapped.position(this.position); + this.wrapped.put(src, off, len); + this.position += len; + return this; + } + + public ByteBuffer put(int index, byte b) { + this.wrapped.put(index, b); + return this; + } + + public ByteBuffer putChar(char value) { + int newPosition = this.position + 2; + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putChar(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer putChar(int index, char value) { + this.wrapped.putChar(index, value); + return this; + } + + public ByteBuffer putDouble(double value) { + int newPosition = this.position + 8; + // FIXME: Does this need synchronization? + // FIXME: Replace magic number + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putDouble(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer putDouble(int index, double value) { + this.wrapped.putDouble(index, value); + return this; + } + + public ByteBuffer putFloat(float value) { + // FIXME Replace the magic number + int newPosition = this.position + 4; + // FIXME:Synchronization problem + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putFloat(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer putFloat(int index, float value) { + this.wrapped.putFloat(index, value); + return this; + } + + public ByteBuffer putInt(int index, int value) { + this.wrapped.putInt(index, value); + return this; + } + + public ByteBuffer putInt(int value) { + // FIXME: Replace the magic number + int newPosition = this.position + 4; + // FIXME: Synchronization + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putInt(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer putLong(int index, long value) { + this.wrapped.putLong(index, value); + return this; + } + + public ByteBuffer putLong(long value) { + // FIXME: Magic number + // FIXME: Synchronization + int newPosition = this.position + 8; + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putLong(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer putShort(int index, short value) { + this.wrapped.putShort(index, value); + return this; + } + + public ByteBuffer putShort(short value) { + // FIXME: Magic number + // FIXME: Synchronization + int newPosition = this.position + 2; + if (newPosition > this.limit) { + throw new BufferOverflowException(); + } + this.wrapped.putShort(this.position, value); + this.position = newPosition; + return this; + } + + public ByteBuffer slice() { + this.wrapped.limit(this.limit); + this.wrapped.position(this.position); + MappedByteBufferAdapter result = new MappedByteBufferAdapter( + this.wrapped.slice()); + this.wrapped.clear(); + return result; + } + + byte[] protectedArray() { + return this.wrapped.protectedArray(); + } + + int protectedArrayOffset() { + return this.wrapped.protectedArrayOffset(); + } + + boolean protectedHasArray() { + return this.wrapped.protectedHasArray(); + } + + public PlatformAddress getBaseAddress() { + return this.wrapped.getBaseAddress(); + } + + public boolean isAddressValid() { + return this.wrapped.isAddressValid(); + } + + public void addressValidityCheck() { + this.wrapped.addressValidityCheck(); + } + + public void free() { + this.wrapped.getBaseAddress().unmap(); + this.wrapped.free(); + } +} Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/FileLock.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/FileLock.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/FileLock.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/FileLock.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package java.nio.channels; - import java.io.IOException; /** @@ -65,7 +64,7 @@ *

* Further care should be exercised when locking files maintained on network file systems since they often * have further limitations.

- * + * */ public abstract class FileLock { @@ -98,7 +97,9 @@ protected FileLock(FileChannel channel, long position, long size, boolean shared) { super(); - + if (position < 0 || size < 0) { + throw new IllegalArgumentException(); + } this.channel = channel; this.position = position; this.size = size; @@ -153,8 +154,8 @@ * @return true if there is an overlap, and false otherwise. */ public final boolean overlaps(long start, long length) { - long myEnd = position + size; - long otherEnd = start + length; + final long myEnd = position + size - 1; + final long otherEnd = start + length - 1; return ((start >= position) && (start <= myEnd)) || ((otherEnd >= position) && (otherEnd <= myEnd)); } Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java?rev=376687&r1=376686&r2=376687&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java Fri Feb 10 05:56:03 2006 @@ -1,4 +1,4 @@ -/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable +/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,12 @@ package java.nio.channels.spi; - import java.io.IOException; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.Channel; import java.nio.channels.InterruptibleChannel; +import java.util.LinkedList; +import java.util.List; /** * This class roots the implementation of interruptable channels. @@ -35,12 +36,14 @@ public abstract class AbstractInterruptibleChannel implements Channel, InterruptibleChannel { - private boolean isClosed = false; + private static List blockingThreads = new LinkedList(); + + private volatile boolean closed = false; /** * Default constructor. */ - public AbstractInterruptibleChannel() { + protected AbstractInterruptibleChannel() { super(); } @@ -50,8 +53,8 @@ * @return true if the channel is open, and false if it is closed. * @see java.nio.channels.Channel#isOpen() */ - public boolean isOpen() { - return !isClosed; + public synchronized final boolean isOpen() { + return !closed; } /** @@ -63,10 +66,14 @@ * * @see java.nio.channels.Channel#close() */ - public synchronized final void close() throws IOException { - if (!isClosed) { - closeChannel(); - isClosed = true; + public final void close() throws IOException { + if (!closed) { + synchronized (this) { + if (!closed) { + closed = true; + implCloseChannel(); + } + } } } @@ -76,8 +83,10 @@ * Once the operation is completed the applicaion should invoke a * corresponding end(boolean). */ - protected synchronized final void begin() { - // TODO + protected final void begin() { + // FIXME: not implemented yet + blockingThreads.add(Thread.currentThread()); + // throw new NotYetImplementedException(); } /** @@ -93,7 +102,13 @@ * the thread conducting the IO operation was interrupted. */ protected final void end(boolean success) throws AsynchronousCloseException { - // TODO + blockingThreads.remove(Thread.currentThread()); + if (success) { + return; + } + + // FIXME: not implemented yet + // throw new NotYetImplementedException(); } /** @@ -110,5 +125,5 @@ * @throws IOException * if a problem occurs closig the channel. */ - protected abstract void closeChannel() throws IOException; + protected abstract void implCloseChannel() throws IOException; }