--- old/make/java/java/mapfile-vers 2012-11-26 10:30:11.000000000 +0100 +++ new/make/java/java/mapfile-vers 2012-11-26 10:30:11.000000000 +0100 @@ -79,7 +79,7 @@ Java_java_io_FileInputStream_close0; Java_java_io_FileInputStream_initIDs; Java_java_io_FileInputStream_open; - Java_java_io_FileInputStream_read; + Java_java_io_FileInputStream_read0; Java_java_io_FileInputStream_readBytes; Java_java_io_FileInputStream_skip; Java_java_io_FileOutputStream_close0; @@ -100,12 +100,12 @@ Java_java_io_RandomAccessFile_initIDs; Java_java_io_RandomAccessFile_length; Java_java_io_RandomAccessFile_open; - Java_java_io_RandomAccessFile_read; - Java_java_io_RandomAccessFile_readBytes; + Java_java_io_RandomAccessFile_read0; + Java_java_io_RandomAccessFile_readBytes0; Java_java_io_RandomAccessFile_seek; Java_java_io_RandomAccessFile_setLength; - Java_java_io_RandomAccessFile_write; - Java_java_io_RandomAccessFile_writeBytes; + Java_java_io_RandomAccessFile_write0; + Java_java_io_RandomAccessFile_writeBytes0; Java_java_io_UnixFileSystem_canonicalize0; Java_java_io_UnixFileSystem_checkAccess; Java_java_io_UnixFileSystem_createDirectory; --- old/src/share/classes/java/io/FileInputStream.java 2012-11-26 10:30:14.000000000 +0100 +++ new/src/share/classes/java/io/FileInputStream.java 2012-11-26 10:30:13.000000000 +0100 @@ -27,6 +27,7 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; /** @@ -51,6 +52,9 @@ /* File Descriptor - handle to the open file */ private final FileDescriptor fd; + /* The path of the referenced file (null if the stream is created with a file descriptor) */ + private final String path; + private FileChannel channel = null; private final Object closeLock = new Object(); @@ -135,6 +139,7 @@ } fd = new FileDescriptor(); fd.incrementAndGetUseCount(); + this.path = name; open(name); } @@ -171,6 +176,7 @@ security.checkRead(fdObj); } fd = fdObj; + path = null; /* * FileDescriptor is being shared by streams. @@ -194,7 +200,18 @@ * file is reached. * @exception IOException if an I/O error occurs. */ - public native int read() throws IOException; + public int read() throws IOException { + Object traceContext = IoTrace.fileReadBegin(path); + int b = 0; + try { + b = read0(); + } finally { + IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1); + } + return b; + } + + private native int read0() throws IOException; /** * Reads a subarray as a sequence of bytes. @@ -217,7 +234,14 @@ * @exception IOException if an I/O error occurs. */ public int read(byte b[]) throws IOException { - return readBytes(b, 0, b.length); + Object traceContext = IoTrace.fileReadBegin(path); + int bytesRead = 0; + try { + bytesRead = readBytes(b, 0, b.length); + } finally { + IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); + } + return bytesRead; } /** @@ -239,7 +263,14 @@ * @exception IOException if an I/O error occurs. */ public int read(byte b[], int off, int len) throws IOException { - return readBytes(b, off, len); + Object traceContext = IoTrace.fileReadBegin(path); + int bytesRead = 0; + try { + bytesRead = readBytes(b, off, len); + } finally { + IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); + } + return bytesRead; } /** @@ -361,7 +392,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, true, false, this); + channel = FileChannelImpl.open(fd, path, true, false, this); /* * Increment fd's use count. Invoking the channel's close() --- old/src/share/classes/java/io/FileOutputStream.java 2012-11-26 10:30:16.000000000 +0100 +++ new/src/share/classes/java/io/FileOutputStream.java 2012-11-26 10:30:16.000000000 +0100 @@ -27,6 +27,7 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; /** @@ -58,6 +59,11 @@ private final FileDescriptor fd; /** + * The path of the referenced file (null if the stream is created with a file descriptor) + */ + private final String path; + + /** * True if the file is opened for append. */ private final boolean append; @@ -207,7 +213,7 @@ } this.fd = new FileDescriptor(); this.append = append; - + this.path = name; fd.incrementAndGetUseCount(); open(name, append); } @@ -244,6 +250,7 @@ security.checkWrite(fdObj); } this.fd = fdObj; + this.path = null; this.append = false; /* @@ -279,7 +286,14 @@ * @exception IOException if an I/O error occurs. */ public void write(int b) throws IOException { - write(b, append); + Object traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + write(b, append); + bytesWritten = 1; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -302,7 +316,14 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[]) throws IOException { - writeBytes(b, 0, b.length, append); + Object traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + writeBytes(b, 0, b.length, append); + bytesWritten = b.length; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -315,7 +336,14 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[], int off, int len) throws IOException { - writeBytes(b, off, len, append); + Object traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + writeBytes(b, off, len, append); + bytesWritten = len; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -398,7 +426,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, false, true, append, this); + channel = FileChannelImpl.open(fd, path, false, true, append, this); /* * Increment fd's use count. Invoking the channel's close() --- old/src/share/classes/java/io/RandomAccessFile.java 2012-11-26 10:30:19.000000000 +0100 +++ new/src/share/classes/java/io/RandomAccessFile.java 2012-11-26 10:30:19.000000000 +0100 @@ -27,6 +27,7 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; /** @@ -62,6 +63,9 @@ private FileChannel channel = null; private boolean rw; + /* The path of the referenced file */ + private final String path; + private Object closeLock = new Object(); private volatile boolean closed = false; @@ -230,6 +234,7 @@ } fd = new FileDescriptor(); fd.incrementAndGetUseCount(); + this.path = name; open(name, imode); } @@ -267,7 +272,7 @@ public final FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, true, rw, this); + channel = FileChannelImpl.open(fd, path, true, rw, this); /* * FileDescriptor could be shared by FileInputStream or @@ -315,7 +320,18 @@ * @exception IOException if an I/O error occurs. Not thrown if * end-of-file has been reached. */ - public native int read() throws IOException; + public int read() throws IOException { + Object traceContext = IoTrace.fileReadBegin(path); + int b = 0; + try { + b = read0(); + } finally { + IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1); + } + return b; + } + + private native int read0() throws IOException; /** * Reads a sub array as a sequence of bytes. @@ -324,7 +340,18 @@ * @param len the number of bytes to read. * @exception IOException If an I/O error has occurred. */ - private native int readBytes(byte b[], int off, int len) throws IOException; + private int readBytes(byte b[], int off, int len) throws IOException { + Object traceContext = IoTrace.fileReadBegin(path); + int bytesRead = 0; + try { + bytesRead = readBytes0(b, off, len); + } finally { + IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); + } + return bytesRead; + } + + private native int readBytes0(byte b[], int off, int len) throws IOException; /** * Reads up to len bytes of data from this file into an @@ -463,17 +490,38 @@ * @param b the byte to be written. * @exception IOException if an I/O error occurs. */ - public native void write(int b) throws IOException; + public void write(int b) throws IOException { + Object traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + write0(b); + bytesWritten = 1; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } + } + + private native void write0(int b) throws IOException; /** * Writes a sub array as a sequence of bytes. * @param b the data to be written - * @param off the start offset in the data * @param len the number of bytes that are written * @exception IOException If an I/O error has occurred. */ - private native void writeBytes(byte b[], int off, int len) throws IOException; + private void writeBytes(byte b[], int off, int len) throws IOException { + Object traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + writeBytes0(b, off, len); + bytesWritten = len; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } + } + + private native void writeBytes0(byte b[], int off, int len) throws IOException; /** * Writes b.length bytes from the specified byte array --- old/src/share/classes/java/net/SocketInputStream.java 2012-11-26 10:30:21.000000000 +0100 +++ new/src/share/classes/java/net/SocketInputStream.java 2012-11-26 10:30:21.000000000 +0100 @@ -30,6 +30,7 @@ import java.io.IOException; import java.nio.channels.FileChannel; +import sun.misc.IoTrace; import sun.net.ConnectionResetException; /** @@ -122,7 +123,7 @@ } int read(byte b[], int off, int length, int timeout) throws IOException { - int n; + int n = 0; // EOF already encountered if (eof) { @@ -144,6 +145,7 @@ boolean gotReset = false; + Object traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout); // acquire file descriptor and do the read FileDescriptor fd = impl.acquireFD(); try { @@ -155,6 +157,7 @@ gotReset = true; } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); } /* @@ -162,6 +165,7 @@ * buffered on the socket */ if (gotReset) { + traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout); impl.setConnectionResetPending(); impl.acquireFD(); try { @@ -172,6 +176,7 @@ } catch (ConnectionResetException rstExc) { } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); } } --- old/src/share/classes/java/net/SocketOutputStream.java 2012-11-26 10:30:23.000000000 +0100 +++ new/src/share/classes/java/net/SocketOutputStream.java 2012-11-26 10:30:23.000000000 +0100 @@ -30,6 +30,8 @@ import java.io.IOException; import java.nio.channels.FileChannel; +import sun.misc.IoTrace; + /** * This stream extends FileOutputStream to implement a * SocketOutputStream. Note that this class should NOT be @@ -104,9 +106,12 @@ throw new ArrayIndexOutOfBoundsException(); } + Object traceContext = IoTrace.socketWriteBegin(impl.address, impl.port); + int bytesWritten = 0; FileDescriptor fd = impl.acquireFD(); try { socketWrite0(fd, b, off, len); + bytesWritten = len; } catch (SocketException se) { if (se instanceof sun.net.ConnectionResetException) { impl.setConnectionResetPending(); @@ -119,6 +124,7 @@ } } finally { impl.releaseFD(); + IoTrace.socketWriteEnd(traceContext, bytesWritten); } } --- old/src/share/classes/sun/nio/ch/FileChannelImpl.java 2012-11-26 10:30:25.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/FileChannelImpl.java 2012-11-26 10:30:25.000000000 +0100 @@ -34,6 +34,7 @@ import java.util.List; import java.security.AccessController; import sun.misc.Cleaner; +import sun.misc.IoTrace; import sun.security.action.GetPropertyAction; public class FileChannelImpl @@ -56,13 +57,16 @@ // Required to prevent finalization of creating stream (immutable) private final Object parent; + // The path of the referenced file (null if the parent stream is created with a file descriptor) + private final String path; + // Thread-safe set of IDs of native threads, for signalling private final NativeThreadSet threads = new NativeThreadSet(2); // Lock for operations involving position and size private final Object positionLock = new Object(); - private FileChannelImpl(FileDescriptor fd, boolean readable, + private FileChannelImpl(FileDescriptor fd, String path, boolean readable, boolean writable, boolean append, Object parent) { this.fd = fd; @@ -70,23 +74,24 @@ this.writable = writable; this.append = append; this.parent = parent; + this.path = path; this.nd = new FileDispatcherImpl(append); } // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel() - public static FileChannel open(FileDescriptor fd, + public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, readable, writable, false, parent); + return new FileChannelImpl(fd, path, readable, writable, false, parent); } // Used by FileOutputStream.getChannel - public static FileChannel open(FileDescriptor fd, + public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, boolean append, Object parent) { - return new FileChannelImpl(fd, readable, writable, append, parent); + return new FileChannelImpl(fd, path, readable, writable, append, parent); } private void ensureOpen() throws IOException { @@ -134,6 +139,7 @@ synchronized (positionLock) { int n = 0; int ti = -1; + Object traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -145,6 +151,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -162,6 +169,7 @@ synchronized (positionLock) { long n = 0; int ti = -1; + Object traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -173,6 +181,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -186,6 +195,7 @@ synchronized (positionLock) { int n = 0; int ti = -1; + Object traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -198,6 +208,7 @@ } finally { threads.remove(ti); end(n > 0); + IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0); assert IOStatus.check(n); } } @@ -214,6 +225,7 @@ synchronized (positionLock) { long n = 0; int ti = -1; + Object traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -225,6 +237,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -665,6 +678,7 @@ ensureOpen(); int n = 0; int ti = -1; + Object traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -676,6 +690,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -691,6 +706,7 @@ ensureOpen(); int n = 0; int ti = -1; + Object traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -703,6 +719,7 @@ } finally { threads.remove(ti); end(n > 0); + IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0); assert IOStatus.check(n); } } --- old/src/share/classes/sun/nio/ch/SocketAdaptor.java 2012-11-26 10:30:28.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/SocketAdaptor.java 2012-11-26 10:30:27.000000000 +0100 @@ -34,6 +34,8 @@ import java.security.PrivilegedExceptionAction; import java.util.*; +import sun.misc.IoTrace; + // Make a socket channel look like a socket. // @@ -204,8 +206,9 @@ SelectionKey sk = null; Selector sel = null; sc.configureBlocking(false); + int n = 0; + Object traceContext = IoTrace.socketReadBegin(getInetAddress(), getPort(), timeout); try { - int n; if ((n = sc.read(bb)) != 0) return n; sel = Util.getTemporarySelector(sc); @@ -226,6 +229,7 @@ throw new SocketTimeoutException(); } } finally { + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); if (sk != null) sk.cancel(); if (sc.isOpen()) --- old/src/share/classes/sun/nio/ch/SocketChannelImpl.java 2012-11-26 10:30:30.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/SocketChannelImpl.java 2012-11-26 10:30:30.000000000 +0100 @@ -33,7 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; - +import sun.misc.IoTrace; /** * An implementation of SocketChannels @@ -80,8 +80,8 @@ private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress; - private SocketAddress remoteAddress; + private InetSocketAddress localAddress; + private InetSocketAddress remoteAddress; // Input/Output open private boolean isInputOpen = true; @@ -278,6 +278,11 @@ synchronized (readLock) { if (!ensureReadOpen()) return -1; + Object traceContext = null; + if (isBlocking()) { + traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(), + remoteAddress.getPort(), 0); + } int n = 0; try { @@ -367,6 +372,11 @@ } finally { readerCleanup(); // Clear reader thread + + if (isBlocking()) { + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); + } + // The end method, which is defined in our superclass // AbstractInterruptibleChannel, resets the interruption // machinery. If its argument is true then it returns @@ -407,6 +417,11 @@ if (!ensureReadOpen()) return -1; long n = 0; + Object traceContext = null; + if (isBlocking()) { + traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(), + remoteAddress.getPort(), 0); + } try { begin(); synchronized (stateLock) { @@ -423,6 +438,9 @@ } } finally { readerCleanup(); + if (isBlocking()) { + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); + } end(n > 0 || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isInputOpen)) @@ -439,6 +457,10 @@ synchronized (writeLock) { ensureWriteOpen(); int n = 0; + Object traceContext = + IoTrace.socketWriteBegin(remoteAddress.getAddress(), + remoteAddress.getPort()); + try { begin(); synchronized (stateLock) { @@ -454,6 +476,7 @@ } } finally { writerCleanup(); + IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0); end(n > 0 || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isOutputOpen)) @@ -472,6 +495,9 @@ synchronized (writeLock) { ensureWriteOpen(); long n = 0; + Object traceContext = + IoTrace.socketWriteBegin(remoteAddress.getAddress(), + remoteAddress.getPort()); try { begin(); synchronized (stateLock) { @@ -487,6 +513,7 @@ } } finally { writerCleanup(); + IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0); end((n > 0) || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isOutputOpen)) --- old/src/share/native/java/io/FileInputStream.c 2012-11-26 10:30:33.000000000 +0100 +++ new/src/share/native/java/io/FileInputStream.c 2012-11-26 10:30:32.000000000 +0100 @@ -62,7 +62,7 @@ } JNIEXPORT jint JNICALL -Java_java_io_FileInputStream_read(JNIEnv *env, jobject this) { +Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) { return readSingle(env, this, fis_fd); } --- old/src/share/native/java/io/RandomAccessFile.c 2012-11-26 10:30:35.000000000 +0100 +++ new/src/share/native/java/io/RandomAccessFile.c 2012-11-26 10:30:35.000000000 +0100 @@ -64,23 +64,23 @@ } JNIEXPORT jint JNICALL -Java_java_io_RandomAccessFile_read(JNIEnv *env, jobject this) { +Java_java_io_RandomAccessFile_read0(JNIEnv *env, jobject this) { return readSingle(env, this, raf_fd); } JNIEXPORT jint JNICALL -Java_java_io_RandomAccessFile_readBytes(JNIEnv *env, +Java_java_io_RandomAccessFile_readBytes0(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len) { return readBytes(env, this, bytes, off, len, raf_fd); } JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_write(JNIEnv *env, jobject this, jint byte) { +Java_java_io_RandomAccessFile_write0(JNIEnv *env, jobject this, jint byte) { writeSingle(env, this, byte, JNI_FALSE, raf_fd); } JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_writeBytes(JNIEnv *env, +Java_java_io_RandomAccessFile_writeBytes0(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len) { writeBytes(env, this, bytes, off, len, JNI_FALSE, raf_fd); } --- old/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2012-11-26 10:30:38.000000000 +0100 +++ new/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2012-11-26 10:30:38.000000000 +0100 @@ -147,7 +147,7 @@ int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0); // wrap with channel - FileChannel fc = UnixChannelFactory.newFileChannel(afd, true, false); + FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), true, false); // read to EOF (nothing we can do if I/O error occurs) try { @@ -188,7 +188,7 @@ UnixFileModeAttribute.ALL_PERMISSIONS); // wrap with channel - FileChannel fc = UnixChannelFactory.newFileChannel(afd, false, true); + FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), false, true); // write value (nothing we can do if I/O error occurs) try { --- old/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java 2012-11-26 10:30:41.000000000 +0100 +++ new/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java 2012-11-26 10:30:40.000000000 +0100 @@ -100,10 +100,10 @@ /** * Constructs a file channel from an existing (open) file descriptor */ - static FileChannel newFileChannel(int fd, boolean reading, boolean writing) { + static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) { FileDescriptor fdObj = new FileDescriptor(); fdAccess.set(fdObj, fd); - return FileChannelImpl.open(fdObj, reading, writing, null); + return FileChannelImpl.open(fdObj, path, reading, writing, null); } /** @@ -134,7 +134,8 @@ throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode); - return FileChannelImpl.open(fdObj, flags.read, flags.write, flags.append, null); + return FileChannelImpl.open(fdObj, path.toString(), + flags.read, flags.write, flags.append, null); } /** --- old/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2012-11-26 10:30:43.000000000 +0100 +++ new/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2012-11-26 10:30:43.000000000 +0100 @@ -157,7 +157,7 @@ throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); - return FileChannelImpl.open(fdObj, flags.read, flags.write, flags.append, null); + return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, flags.append, null); } /** --- /dev/null 2012-11-26 10:30:46.000000000 +0100 +++ new/src/share/classes/sun/misc/IoTrace.java 2012-11-26 10:30:45.000000000 +0100 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.misc; + +import java.net.InetAddress; + +/** + * Utility class used to identify trace points for I/O calls. + *

+ * To use this class, a diagnostic tool must redefine this class with a version + * that contains calls to the the diagnostic tool. This implementation will then + * receive callbacks when file and socket operations are performed. The reason + * for requiring a redefine of the class is to avoid any overhead caused by the + * instrumentation. + *

+ * The xxBegin() methods return a "context". This can be any Object. This + * context will be passed to the corresponding xxEnd() method. This way, an + * implementation can correlate the beginning of an operation with the end. + *

+ * It is possible for a xxEnd() method to be called with a null handle. This + * happens if tracing was started between the call to xxBegin() and xxEnd(), in + * which case xxBegin() would not have been called. It is the implementation's + * responsibility to not throw an exception in this case. + *

+ * Only blocking I/O operations are identified with this facility. + *

+ * Warning + *

+ * These methods are called from sensitive points in the I/O subsystem. Great + * care must be taken to not interfere with ongoing operations or cause + * deadlocks. In particular: + *

+ */ +public final class IoTrace { + private IoTrace() { + } + + /** + * Called before data is read from a socket. + * + * @param address + * the remote address the socket is bound to + * @param port + * the remote port the socket is bound to + * @param timeout + * the SO_TIMEOUT value of the socket (in milliseconds) or 0 if + * there is no timeout set + * @return a context object + */ + public static Object socketReadBegin(InetAddress address, int port, + int timeout) { + return null; + } + + /** + * Called after data is read from the socket. + * + * @param context + * the context returned by the previous call to socketReadBegin() + * @param bytesRead + * the number of bytes read from the socket, 0 if there was an + * error reading from the socket + */ + public static void socketReadEnd(Object context, long bytesRead) { + } + + /** + * Called before data is written to a socket. + * + * @param address + * the remote address the socket is bound to + * @param port + * the remote port the socket is bound to + * @return a context object + */ + public static Object socketWriteBegin(InetAddress address, int port) { + return null; + } + + /** + * Called after data is written to a socket. + * + * @param context + * the context returned by the previous call to + * socketWriteBegin() + * @param bytesWritten + * the number of bytes written to the socket, 0 if there was an + * error writing to the socket + */ + public static void socketWriteEnd(Object context, long bytesWritten) { + } + + /** + * Called before data is read from a file. + * + * @param path + * the path of the file + * @return a context object + */ + public static Object fileReadBegin(String path) { + return null; + } + + /** + * Called after data is read from a file. + * + * @param context + * the context returned by the previous call to fileReadBegin() + * @param bytesRead + * the number of bytes written to the file, 0 if there was an + * error writing to the file + */ + public static void fileReadEnd(Object context, long bytesRead) { + } + + /** + * Called before data is written to a file. + * + * @param path + * the path of the file + * @return a context object + */ + public static Object fileWriteBegin(String path) { + return null; + } + + /** + * Called after data is written to a file. + * + * @param context + * the context returned by the previous call to fileReadBegin() + * @param bytesWritten + * the number of bytes written to the file, 0 if there was an + * error writing to the file + */ + public static void fileWriteEnd(Object context, long bytesWritten) { + } +} --- /dev/null 2012-11-26 10:30:48.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceAgent.java 2012-11-26 10:30:47.000000000 +0100 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_FINAL; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_PRIVATE; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_STATIC; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_SUPER; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ILOAD; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.INVOKESTATIC; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.IRETURN; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.RETURN; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.V1_6; + +import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.InetAddress; + +import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter; +import com.sun.xml.internal.ws.org.objectweb.asm.MethodVisitor; +import com.sun.xml.internal.ws.org.objectweb.asm.Type; +import sun.misc.IoTrace; + +public class IoTraceAgent { + + private static IoTraceListener listener; + + public static void setListener(IoTraceListener l) { + listener = l; + } + + public static Object socketReadBegin(InetAddress address, int port, + int timeout) { + IoTraceListener l = listener; + if (l != null) { + return l.socketReadBegin(address, port, timeout); + } + return null; + } + + public static void socketReadEnd(Object context, long bytesRead) { + IoTraceListener l = listener; + if (l != null) { + l.socketReadEnd(context, bytesRead); + } + } + + public static Object socketWriteBegin(InetAddress address, int port) { + IoTraceListener l = listener; + if (l != null) { + return l.socketWriteBegin(address, port); + } + return null; + } + + public static void socketWriteEnd(Object context, long bytesWritten) { + IoTraceListener l = listener; + if (l != null) { + l.socketWriteEnd(context, bytesWritten); + } + } + + public static Object fileReadBegin(String path) { + IoTraceListener l = listener; + if (l != null) { + return l.fileReadBegin(path); + } + return null; + } + + public static void fileReadEnd(Object context, long bytesRead) { + IoTraceListener l = listener; + if (l != null) { + l.fileReadEnd(context, bytesRead); + } + } + + public static Object fileWriteBegin(String path) { + IoTraceListener l = listener; + if (l != null) { + return l.fileWriteBegin(path); + } + return null; + } + + public static void fileWriteEnd(Object context, long bytesWritten) { + IoTraceListener l = listener; + if (l != null) { + l.fileWriteEnd(context, bytesWritten); + } + } + + public static void premain(String agentArgs, Instrumentation inst) + throws Exception { + ClassDefinition cd = new ClassDefinition(IoTrace.class, + generateClassAsm()); + inst.redefineClasses(cd); + } + + private static byte[] generateClassAsm() { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cw.visit(V1_6, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, "sun/misc/IoTrace", + null, "java/lang/Object", null); + + // for all methods in the existing IoTrace class + // we want to create a method in the new version of it which call + // IoTraceAgent + // + // 0: aload_0 + // 1: iload_1 + // 2: iload_2 + // 3: invokestatic #16 // Method + // IoTraceAgent.socketReadBegin:(Ljava/net/InetAddress;II)Ljava/lang/Object; + // 6: areturn + + for (Method om : IoTrace.class.getDeclaredMethods()) { + if (!Modifier.isStatic(om.getModifiers())) { + continue; + } + + // create a method with the same signature as the + // original method + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, + om.getName(), Type.getMethodDescriptor(om), null, null); + mv.visitCode(); + + // get the return type and argument list types + Type[] argTypes = Type.getArgumentTypes(om); + Type retType = Type.getReturnType(om); + + // load all the arguments + int i = 0; + for (Type t : argTypes) { + mv.visitVarInsn(t.getOpcode(ILOAD), i++); + } + + // call a method with the same signature (but in a different class) + // with all the arguments + mv.visitMethodInsn(INVOKESTATIC, "IoTraceAgent", om.getName(), + Type.getMethodDescriptor(om)); + + // return the value from the called method + mv.visitInsn(retType.getOpcode(IRETURN)); + mv.visitEnd(); + } + + // empty private constructor + MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "", "()V", null, + null); + mv.visitCode(); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); + mv.visitInsn(RETURN); + mv.visitEnd(); + + cw.visitEnd(); + return cw.toByteArray(); + } +} --- /dev/null 2012-11-26 10:30:50.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceBase.java 2012-11-26 10:30:50.000000000 +0100 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.net.InetAddress; + + +public class IoTraceBase implements IoTraceListener { + + protected static final Object my_context = new Object() { + }; + + private String path; + private long bytesRead; + private long bytesWritten; + private Object context; + private InetAddress address; + private int port; + private int timeout; + + protected void clear() { + context = null; + bytesRead = 0; + bytesWritten = 0; + address = null; + port = 0; + timeout = 0; + path = null; + } + + @Override + public Object fileWriteBegin(String p) { + path = p; + return my_context; + } + + @Override + public void fileWriteEnd(Object ctx, long bw) { + context = ctx; + bytesWritten = bw; + } + + @Override + public Object fileReadBegin(String p) { + path = p; + return my_context; + } + + @Override + public void fileReadEnd(Object ctx, long br) { + context = ctx; + bytesRead = br; + } + + @Override + public Object socketReadBegin(InetAddress address, int port, + int timeout) { + this.address = address; + this.port = port; + this.timeout = timeout; + return my_context; + } + + @Override + public void socketReadEnd(Object context, long bytesRead) { + this.context = context; + this.bytesRead = bytesRead; + } + + @Override + public Object socketWriteBegin(InetAddress address, int port) { + this.address = address; + this.port = port; + return my_context; + } + + @Override + public void socketWriteEnd(Object context, long bytesWritten) { + this.context = context; + this.bytesWritten = bytesWritten; + } + + protected void expectFileRead(long br, File f) throws Exception { + expectFile(0, br, f); + } + + protected void expectFileWrite(long bw, File f) throws Exception { + expectFile(bw, 0, f); + } + + protected void expectFile(long bw, long br, File f) throws Exception { + if (context != my_context) { + throw new Exception("Wrong context: " + context); + } + if (bytesWritten != bw) { + throw new Exception("Expected " + bw + " byte to be read, got: " + + bytesWritten); + } + if (bytesRead != br) { + throw new Exception("Expected " + br + " byte to be read, got: " + + bytesWritten); + } + if (!path.equals(f.getPath())) { + throw new Exception("Incorrect path: " + path + ". Expected: " + + f.getPath()); + } + } + + protected void expectSocket(int br, int bw, InetAddress ia, int p, int t) + throws Exception { + if (context != my_context) { + throw new Exception("Wrong context: " + context); + } + if (bytesWritten != bw) { + throw new Exception("Expected " + bw + " byte to be written, got: " + + bytesWritten); + } + if (bytesRead != br) { + throw new Exception("Expected " + br + " byte to be read, got: " + + bytesWritten); + } + if (!address.equals(ia)) { + throw new Exception("Incorrect address: " + address + + ". Expected: " + ia); + } + if (port != p) { + throw new Exception("Expected " + p + " port, got: " + port); + } + if (timeout != t) { + throw new Exception("Expected " + t + " timeout, got: " + timeout); + } + } +} \ No newline at end of file --- /dev/null 2012-11-26 10:30:53.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceFileChannelReadWrite.java 2012-11-26 10:30:53.000000000 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; + +/* + * @test + * @bug 8003322 + * @run shell ioTraceTest.sh IoTraceFileChannelReadWrite + */ +public class IoTraceFileChannelReadWrite extends IoTraceBase { + + private void testWrite(File f) throws IOException, FileNotFoundException, + Exception { + try (FileChannel fc = FileChannel.open(f.toPath(), + StandardOpenOption.WRITE)) { + ByteBuffer bb = ByteBuffer.allocate(1); + bb.put((byte) 11); + bb.flip(); + fc.write(bb); + } + expectFile(1, 0, f); + } + + private void testRead(File f) throws IOException, FileNotFoundException, + Exception { + try (FileChannel fc = FileChannel.open(f.toPath(), + StandardOpenOption.READ)) { + ByteBuffer bb = ByteBuffer.allocate(1); + fc.read(bb); + } + expectFile(0, 1, f); + } + + public void test() throws Exception { + IoTraceAgent.setListener(this); + File f = File.createTempFile("IoTraceFileChannelReadWrite", ".bin"); + try { + clear(); + testWrite(f); + clear(); + testRead(f); + } finally { + f.delete(); + } + } + + public static void main(String... args) throws Exception { + IoTraceFileChannelReadWrite t = new IoTraceFileChannelReadWrite(); + t.test(); + } +} --- /dev/null 2012-11-26 10:30:56.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceFileReadWrite.java 2012-11-26 10:30:56.000000000 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/* + * @test + * @bug 8003322 + * @run shell ioTraceTest.sh IoTraceFileReadWrite + */ +public class IoTraceFileReadWrite extends IoTraceBase { + + private void testWrite(File f) throws IOException, FileNotFoundException, + Exception { + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(11); + } + expectFile(1, 0, f); + } + + + private void testRead(File f) throws IOException, FileNotFoundException, + Exception { + try (FileInputStream fos = new FileInputStream(f)) { + fos.read(); + } + expectFile(0, 1, f); + } + + private void testRandomAccessWrite(File f) throws Exception { + try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) { + raf.write(11); + } + expectFile(1, 0, f); + } + + private void testRandomAccessRead(File f) throws Exception { + try (RandomAccessFile raf = new RandomAccessFile(f, "r")) { + raf.read(); + } + expectFile(0, 1, f); + } + + public void test() throws Exception { + IoTraceAgent.setListener(this); + File f = File.createTempFile("IoTraceFileReadWrite", ".bin"); + try { + clear(); + testWrite(f); + clear(); + testRead(f); + clear(); + testRandomAccessWrite(f); + clear(); + testRandomAccessRead(f); + } finally { + f.delete(); + } + } + + public static void main(String... args) throws Exception { + IoTraceFileReadWrite t = new IoTraceFileReadWrite(); + t.test(); + } +} --- /dev/null 2012-11-26 10:30:58.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceListener.java 2012-11-26 10:30:58.000000000 +0100 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.InetAddress; + +import sun.misc.IoTrace; + +/** + * Implementations of this interface can be registered with + * {@link IoTrace#setListener(IoTraceListener)} to receive callbacks when file + * and socket operations are performed. + *

+ * The xxBegin() methods return a "context". This can be any Object. This + * context will be passed to the corresponding xxEnd() method. This way, an + * implementation can correlate the beginning of an operation with the end. + *

+ * It is possible for a xxEnd() method to be called with a null handle. This + * happens if tracing was started between the call to xxBegin() and xxEnd(), in + * which case xxBegin() would not have been called. It is the implementation's + * responsibility to not throw an exception in this case. + *

+ * Implementations should never throw exceptions since this will cause + * disruptions to the I/O operations. + *

+ * An xxBegin() call is not guaranteed to be followed by an xxEnd() call, since + * the listener in IoTrace can be reset at any time. + */ +public interface IoTraceListener { + + /** + * Called before data is read from a socket. + * + * @param address + * the remote address the socket is bound to + * @param port + * the remote port the socket is bound to + * @param timeout + * the SO_TIMEOUT value of the socket (in milliseconds) or 0 if + * there is no timeout set + * @return a context object + */ + public Object socketReadBegin(InetAddress address, int port, int timeout); + + /** + * Called after data is read from the socket. + * + * @param context + * the context returned by the previous call to socketReadBegin() + * @param bytesRead + * the number of bytes read from the socket, 0 if there was an + * error reading from the socket + */ + public void socketReadEnd(Object context, long bytesRead); + + /** + * Called before data is written to a socket. + * + * @param address + * the remote address the socket is bound to + * @param port + * the remote port the socket is bound to + * @return a context object + */ + public Object socketWriteBegin(InetAddress address, int port); + + /** + * Called after data is written to a socket. + * + * @param context + * the context returned by the previous call to + * socketWriteBegin() + * @param bytesWritten + * the number of bytes written to the socket, 0 if there was an + * error writing to the socket + */ + public void socketWriteEnd(Object context, long bytesWritten); + + /** + * Called before data is read from a file. + * + * @param path + * the path of the file + * @return a context object + */ + public Object fileReadBegin(String path); + + /** + * Called after data is read from a file. + * + * @param context + * the context returned by the previous call to fileReadBegin() + * @param bytesRead + * the number of bytes written to the file, 0 if there was an + * error writing to the file + */ + public void fileReadEnd(Object context, long bytesRead); + + /** + * Called before data is written to a file. + * + * @param path + * the path of the file + * @return a context object + */ + public Object fileWriteBegin(String path); + + /** + * Called after data is written to a file. + * + * @param context + * the context returned by the previous call to fileReadBegin() + * @param bytesWritten + * the number of bytes written to the file, 0 if there was an + * error writing to the file + */ + public void fileWriteEnd(Object context, long bytesWritten); +} --- /dev/null 2012-11-26 10:31:00.000000000 +0100 +++ new/test/sun/misc/IoTrace/IoTraceSocketReadWrite.java 2012-11-26 10:31:00.000000000 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; + +/* + * @test + * @bug 8003322 + * @run shell ioTraceTest.sh IoTraceSocketReadWrite + */ +public class IoTraceSocketReadWrite extends IoTraceBase { + + public void test() throws Exception { + IoTraceAgent.setListener(this); + + ServerSocket ss = null; + Socket s1 = null, s2 = null; + OutputStream os = null; + InputStream is = null; + + try { + InetAddress iaddr = InetAddress.getLocalHost(); + ss = new ServerSocket(0); + s1 = new Socket(iaddr, ss.getLocalPort()); + s2 = ss.accept(); + + os = s1.getOutputStream(); + is = s2.getInputStream(); + + os.write((byte) 11); + is.read(); + + expectSocket(1, 1, s2.getInetAddress(), s2.getPort(), 0); + + } finally { + if (ss != null) { + ss.close(); + } + if (s1 != null) { + s1.close(); + } + if (s2 != null) { + s2.close(); + } + } + } + + public static void main(String... args) throws Exception { + IoTraceSocketReadWrite t = new IoTraceSocketReadWrite(); + t.test(); + } +} \ No newline at end of file --- /dev/null 2012-11-26 10:31:03.000000000 +0100 +++ new/test/sun/misc/IoTrace/ioTraceTest.sh 2012-11-26 10:31:02.000000000 +0100 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code 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 +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +set -x +PWD=`pwd` + +cd ${TESTSRC} +${TESTJAVA}/bin/javac -XDignore.symbol.file=true -d ${TESTCLASSES} *.java + +cd ${TESTCLASSES} +${TESTJAVA}/bin/jar cfm iotraceagent.jar ${TESTSRC}/iotraceagent.mf IoTraceAgent.class IoTraceListener.class + +cd ${PWD} +${TESTJAVA}/bin/java ${TESTVMOPTS} -javaagent:${TESTCLASSES}/iotraceagent.jar -cp ${TESTCLASSES} $* --- /dev/null 2012-11-26 10:31:05.000000000 +0100 +++ new/test/sun/misc/IoTrace/iotraceagent.mf 2012-11-26 10:31:05.000000000 +0100 @@ -0,0 +1,3 @@ +Premain-Class: IoTraceAgent +Can-Redefine-Classes: true +Boot-Class-Path: iotraceagent.jar