8272588: Enhanced recording parsing

Reviewed-by: mgronlun, rhalade, mschoene
This commit is contained in:
Erik Gahlin 2021-12-07 14:46:55 +00:00 committed by Henry Jen
parent 4d4ba814ae
commit f0f0ddbf6d
7 changed files with 29 additions and 2 deletions

@ -136,6 +136,8 @@ public interface EventStream extends AutoCloseable {
* <p>
* By default, the stream starts with the next event flushed by Flight
* Recorder.
* <p>
* Only trusted disk repositories should be opened.
*
* @param directory location of the disk repository, not {@code null}
*
@ -166,6 +168,8 @@ public interface EventStream extends AutoCloseable {
* Creates an event stream from a file.
* <p>
* By default, the stream starts with the first event in the file.
* <p>
* Only recording files from trusted sources should be opened.
*
* @param file location of the file, not {@code null}
*

@ -70,6 +70,8 @@ public final class RecordingFile implements Closeable {
/**
* Creates a recording file.
* <p>
* Only recording files from trusted sources should be used.
*
* @param file the path of the file to open, not {@code null}
* @throws IOException if it's not a valid recording file, or an I/O error
@ -247,6 +249,8 @@ public final class RecordingFile implements Closeable {
* <p>
* This method is intended for simple cases where it's convenient to read all
* events in a single operation. It isn't intended for reading large files.
* <p>
* Only recording files from trusted sources should be used.
*
* @param path the path to the file, not {@code null}
*

@ -113,7 +113,7 @@ public final class ChunkHeader {
byte fs;
input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION);
while ((fs = input.readPhysicalByte()) == UPDATING_CHUNK_HEADER) {
Utils.takeNap(1);
input.pollWait();
input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION);
}
return fs;
@ -180,7 +180,7 @@ public final class ChunkHeader {
finished = true;
return;
}
Utils.takeNap(1);
input.pollWait();
}
} finally {
input.position(pos);

@ -145,6 +145,7 @@ public final class EventDirectoryStream extends AbstractEventStream {
}
currentChunkStartNanos = repositoryFiles.getTimestamp(path);
try (RecordingInput input = new RecordingInput(path.toFile(), fileAccess)) {
input.setStreamed();
currentParser = new ChunkParser(input, disp.parserConfiguration, parserState);
long segmentStart = currentParser.getStartNanos() + currentParser.getChunkDuration();
long filterStart = validStartTime ? disp.startNanos : segmentStart;

@ -49,6 +49,7 @@ public final class EventFileStream extends AbstractEventStream {
public EventFileStream(@SuppressWarnings("removal") AccessControlContext acc, Path file) throws IOException {
super(acc, null, Collections.emptyList());
this.input = new RecordingInput(file.toFile(), FileAccess.UNPRIVILEGED);
this.input.setStreamed();
}
@Override

@ -214,6 +214,7 @@ public final class OngoingStream extends EventByteStream {
return false;
}
input = new RecordingInput(path.toFile(), SecuritySupport.PRIVILEGED);
input.setStreamed();
header = new ChunkHeader(input);
}
return true;

@ -31,6 +31,7 @@ import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Path;
import jdk.jfr.internal.Utils;
public final class RecordingInput implements DataInput, AutoCloseable {
@ -66,6 +67,7 @@ public final class RecordingInput implements DataInput, AutoCloseable {
}
private final int blockSize;
private final FileAccess fileAccess;
private long pollCount = 1000;
private RandomAccessFile file;
private String filename;
private Block currentBlock = new Block();
@ -439,4 +441,18 @@ public final class RecordingInput implements DataInput, AutoCloseable {
initialize(path.toFile());
}
// Marks that it is OK to poll indefinitely for file update
// By default, only 1000 polls are allowed
public void setStreamed() {
this.pollCount = Long.MAX_VALUE;
}
// Wait for file to be updated
public void pollWait() throws IOException {
pollCount--;
if (pollCount < 0) {
throw new IOException("Recording file is stuck in locked stream state.");
}
Utils.takeNap(1);
}
}