8338405: JFR: Use FILE type for dcmds

Reviewed-by: egahlin, lmesnik
This commit is contained in:
Sonia Zaldana Calles 2024-09-24 14:40:38 +00:00
parent caa751c561
commit 85aed87796
5 changed files with 57 additions and 47 deletions

@ -30,7 +30,6 @@ import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -288,41 +287,4 @@ abstract class AbstractDCmd {
return "/directory/recordings";
}
}
static String expandFilename(String filename) {
if (filename == null || filename.indexOf('%') == -1) {
return filename;
}
String pid = null;
String time = null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filename.length(); i++) {
char c = filename.charAt(i);
if (c == '%' && i < filename.length() - 1) {
char nc = filename.charAt(i + 1);
if (nc == '%') { // %% ==> %
sb.append('%');
i++;
} else if (nc == 'p') {
if (pid == null) {
pid = JVM.getPid();
}
sb.append(pid);
i++;
} else if (nc == 't') {
if (time == null) {
time = ValueFormatter.formatDateTime(LocalDateTime.now());
}
sb.append(time);
i++;
} else {
sb.append('%');
}
} else {
sb.append(c);
}
}
return sb.toString();
}
}

@ -25,14 +25,18 @@
package jdk.jfr.internal.dcmd;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import jdk.jfr.internal.JVM;
import jdk.jfr.internal.util.SpellChecker;
import jdk.jfr.internal.util.TimespanUnit;
import jdk.jfr.internal.util.ValueFormatter;
final class ArgumentParser {
private final Map<String, Object> options = new HashMap<>();
@ -226,10 +230,54 @@ final class ArgumentParser {
case "BOOLEAN" -> parseBoolean(name, text);
case "NANOTIME" -> parseNanotime(name, text);
case "MEMORY SIZE" -> parseMemorySize(name, text);
case "FILE" -> text == null ? "" : parseFilename(text);
default -> throw new InternalError("Unknown type: " + type);
};
}
/**
* Expands filename arguments replacing '%p' with the PID
* and '%t' with the time in 'yyyy_MM_dd_HH_mm_ss' format.
* @param filename a filename to be expanded
* @return filename with expanded arguments
*/
private String parseFilename(String filename) {
if (filename == null || filename.indexOf('%') == -1) {
return filename;
}
String pid = null;
String time = null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filename.length(); i++) {
char c = filename.charAt(i);
if (c == '%' && i < filename.length() - 1) {
char nc = filename.charAt(i + 1);
if (nc == '%') { // %% ==> %
sb.append('%');
i++;
} else if (nc == 'p') {
if (pid == null) {
pid = JVM.getPid();
}
sb.append(pid);
i++;
} else if (nc == 't') {
if (time == null) {
time = ValueFormatter.formatDateTime(LocalDateTime.now());
}
sb.append(time);
i++;
} else {
sb.append('%');
}
} else {
sb.append(c);
}
}
return sb.toString();
}
private Long parseLong(String name, String text) {
if (text == null) {
throw new IllegalArgumentException("Parsing error long value: syntax error, value is null");

@ -55,7 +55,7 @@ final class DCmdDump extends AbstractDCmd {
public void execute(ArgumentParser parser) throws DCmdException {
parser.checkUnknownArguments();
String name = parser.getOption("name");
String filename = expandFilename(parser.getOption("filename"));
String filename = parser.getOption("filename");
Long maxAge = parser.getOption("maxage");
Long maxSize = parser.getOption("maxsize");
String begin = parser.getOption("begin");
@ -230,7 +230,7 @@ final class DCmdDump extends AbstractDCmd {
dumped. If no filename is given, a filename is generated from the PID
and the current date. The filename may also be a directory in which
case, the filename is generated from the PID and the current date in
the specified directory. (STRING, no default value)
the specified directory. (FILE, no default value)
Note: If a filename is given, '%%p' in the filename will be
replaced by the PID, and '%%t' will be replaced by the time in
@ -284,7 +284,7 @@ final class DCmdDump extends AbstractDCmd {
"STRING", false, true, null, false),
new Argument("filename",
"Copy recording data to file, e.g. \\\"" + exampleFilename() + "\\\"",
"STRING", false, true, null, false),
"FILE", false, true, null, false),
new Argument("maxage",
"Maximum duration to dump, in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit",
"NANOTIME", false, true, null, false),

@ -80,7 +80,7 @@ final class DCmdStart extends AbstractDCmd {
Long delay = parser.getOption("delay");
Long duration = parser.getOption("duration");
Boolean disk = parser.getOption("disk");
String path = expandFilename(parser.getOption("filename"));
String path = parser.getOption("filename");
Long maxAge = parser.getOption("maxage");
Long maxSize = parser.getOption("maxsize");
Long flush = parser.getOption("flush-interval");
@ -377,7 +377,7 @@ final class DCmdStart extends AbstractDCmd {
placed in the directory where the process was started. The
filename may also be a directory in which case, the filename is
generated from the PID and the current date in the specified
directory. (STRING, no default value)
directory. (FILE, no default value)
Note: If a filename is given, '%p' in the filename will be
replaced by the PID, and '%t' will be replaced by the time in
@ -501,7 +501,7 @@ final class DCmdStart extends AbstractDCmd {
"BOOLEAN", false, true, "true", false),
new Argument("filename",
"Resulting recording filename, e.g. \\\"" + exampleFilename() + "\\\"",
"STRING", false, true, "hotspot-pid-xxxxx-id-y-YYYY_MM_dd_HH_mm_ss.jfr", false),
"FILE", false, true, "hotspot-pid-xxxxx-id-y-YYYY_MM_dd_HH_mm_ss.jfr", false),
new Argument("maxage",
"Maximum time to keep recorded data (on disk) in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit",
"NANOTIME", false, true, "0", false),

@ -44,7 +44,7 @@ final class DCmdStop extends AbstractDCmd {
protected void execute(ArgumentParser parser) throws DCmdException {
parser.checkUnknownArguments();
String name = parser.getOption("name");
String filename = expandFilename(parser.getOption("filename"));
String filename = parser.getOption("filename");
try {
Recording recording = findRecording(name);
WriteableUserPath path = PrivateAccess.getInstance().getPlatformRecording(recording).getDestination();
@ -80,7 +80,7 @@ final class DCmdStop extends AbstractDCmd {
filename (Optional) Name of the file to which the recording is written when the
recording is stopped. If no path is provided, the data from the recording
is discarded. (STRING, no default value)
is discarded. (FILE, no default value)
Note: If a path is given, '%%p' in the path will be replaced by the PID,
and '%%t' will be replaced by the time in 'yyyy_MM_dd_HH_mm_ss' format.
@ -107,7 +107,7 @@ final class DCmdStop extends AbstractDCmd {
"STRING", true, true, null, false),
new Argument("filename",
"Copy recording data to file, e.g. \\\"" + exampleFilename() + "\\\"",
"STRING", false, true, null, false)
"FILE", false, true, null, false)
};
}
}