blob: e3939fbf88afd5384cda839ab66ea203c19b58ef [file] [log] [blame]
/*
* 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();
}
}