--- /dev/null 2017-11-09 09:38:01.297999907 +0100 +++ new/test/jdk/jdk/jfr/event/io/IOEvent.java 2018-04-09 18:09:51.119318826 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2018, 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 jdk.jfr.event.io; + +import java.io.File; +import java.io.IOException; +import java.net.Socket; + +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedThread; +import jdk.test.lib.jfr.EventField; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +// Contains data from a JFR IO event. +public class IOEvent { + public final String thread; + public final EventType eventType; + public final long size; + public final String address; // Name of file or socket address. + public final boolean endOfStream; + + // Constructor is private. Use IOEvent.create... + private IOEvent(String thread, EventType eventType, long size, String address, boolean endOfStream) { + this.thread = thread; + this.eventType = eventType; + this.size = size; + this.address = address; + this.endOfStream = endOfStream; + } + + @Override + public String toString() { + String key = String.format("thread: %s, type: %s, size: %d, address: %s endOfStream: %s", thread, eventType, size, address, endOfStream); + return key; + } + + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof IOEvent)) { + return false; + } + return toString().equals(object.toString()); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + public static final String EVENT_UNKNOWN = "unknown-event??"; + public static final String EVENT_FILE_FORCE = EventNames.FileForce; + public static final String EVENT_FILE_READ = EventNames.FileRead; + public static final String EVENT_FILE_WRITE = EventNames.FileWrite; + public static final String EVENT_SOCKET_READ = EventNames.SocketRead; + public static final String EVENT_SOCKET_WRITE = EventNames.SocketWrite; + + public enum EventType { UnknownEvent, FileForce, FileRead, FileWrite, SocketRead, SocketWrite } + + private static final String[] eventPaths = { + EVENT_UNKNOWN, EVENT_FILE_FORCE, EVENT_FILE_READ, EVENT_FILE_WRITE, EVENT_SOCKET_READ, EVENT_SOCKET_WRITE + }; + + public static boolean isWriteEvent(EventType eventType) { + return (eventType == EventType.SocketWrite || eventType == EventType.FileWrite); + } + + public static boolean isReadEvent(EventType eventType) { + return (eventType == EventType.SocketRead || eventType == EventType.FileRead); + } + + public static boolean isFileEvent(EventType eventType) { + return (eventType == EventType.FileForce || eventType == EventType.FileWrite || eventType == EventType.FileRead); + } + + public static IOEvent createSocketWriteEvent(long size, Socket s) { + if (size < 0) { + size = 0; + } + return new IOEvent(Thread.currentThread().getName(), EventType.SocketWrite, size, getAddress(s), false); + } + + public static IOEvent createSocketReadEvent(long size, Socket s) { + boolean endOfStream = false; + if (size < 0) { + size = 0; + endOfStream = true; + } + return new IOEvent(Thread.currentThread().getName(), EventType.SocketRead, size, getAddress(s), endOfStream); + } + + public static IOEvent createFileForceEvent(File file) { + String address = null; + try { + address = file.getCanonicalPath(); + } catch(IOException ex) { + throw new RuntimeException(); + } + return new IOEvent(Thread.currentThread().getName(), EventType.FileForce, 0, address, false); + } + + public static IOEvent createFileReadEvent(long size, File file) { + boolean endOfStream = false; + if (size < 0) { + endOfStream = true; + size = 0; + } + String address = null; + try { + address = file.getCanonicalPath(); + } catch(IOException ex) { + throw new RuntimeException(); + } + return new IOEvent(Thread.currentThread().getName(), EventType.FileRead, size, address, endOfStream); + } + + public static IOEvent createFileWriteEvent(long size, File file) { + if (size < 0) { + size = 0; + } + String address = null; + try { + address = file.getCanonicalPath(); + } catch(IOException ex) { + throw new RuntimeException(); + } + return new IOEvent(Thread.currentThread().getName(), EventType.FileWrite, size, address, false); + } + + public static EventType getEventType(RecordedEvent event) { + final String path = event.getEventType().getName(); + for (int i = 0; i < eventPaths.length; ++i) { + if (path.endsWith(eventPaths[i])) { + return EventType.values()[i]; + } + } + return EventType.UnknownEvent; + } + + public static IOEvent createTestEvent(RecordedEvent event) { + EventType eventType = getEventType(event); + if (eventType == EventType.UnknownEvent) { + return null; + } + EventField ev = Events.assertField(event, "eventThread"); + RecordedThread t = ev.getValue(); + String thread = t.getJavaName(); + long size = 0L; + if (isWriteEvent(eventType)) { + size = Events.assertField(event, "bytesWritten").getValue(); + } else if (isReadEvent(eventType)) { + size = Events.assertField(event, "bytesRead").getValue(); + } + String address = getEventAddress(event); + boolean endOfStream = false; + if (event.hasField("endOfStream")) { + endOfStream = event.getValue("endOfStream"); + } + if (event.hasField("endOfFile")) { + endOfStream = event.getValue("endOfFile"); + } + return new IOEvent(thread, eventType, size, address, endOfStream); + } + + public static String getEventAddress(RecordedEvent event) { + if (isFileEvent(getEventType(event))) { + String address = Events.assertField(event, "path").getValue(); + // must ensure canonical format + String canonical_path = null; + try { + canonical_path = new File(address).getCanonicalPath(); + } catch (IOException ex) { + throw new RuntimeException(); + } + return canonical_path; + } else { + return String.format("%s/%s:%d", + event.getValue("host"), + event.getValue("address"), + event.getValue("port")); + } + } + + private static String getAddress(Socket s) { + return s.getInetAddress().toString() + ":" + s.getPort(); + } +}