| /* |
| * 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(); |
| } |
| } |