Skip to content

Commit 30b036a

Browse files
open emergency dump chunk
1 parent 01b11b9 commit 30b036a

File tree

2 files changed

+32
-42
lines changed

2 files changed

+32
-42
lines changed

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/jfr/PosixJfrEmergencyDumpSupport.java

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public class PosixJfrEmergencyDumpSupport implements com.oracle.svm.core.jfr.Jfr
7373
private static int ISO8601_LEN = 19;
7474
private static final byte FILE_SEPARATOR = "/".getBytes(StandardCharsets.UTF_8)[0];
7575
private static final byte DOT = ".".getBytes(StandardCharsets.UTF_8)[0];
76+
// It does not really matter what the name is.
77+
private static final byte[] EMERGENCY_CHUNK_BYTES = "emergency_chunk".getBytes(StandardCharsets.UTF_8);
7678
private static final byte[] DUMP_FILE_PREFIX = "hs_oom_pid_".getBytes(StandardCharsets.UTF_8);
7779
private static final byte[] CHUNKFILE_EXTENSION_BYTES = ".jfr".getBytes(StandardCharsets.UTF_8);
7880
private Dirent.DIR directory;
@@ -109,30 +111,29 @@ public String getDumpPath() {
109111

110112
// Either use create and use the dumpfile itself, or create a new file in the repository
111113
// location.
114+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp#L433-L445")
112115
public RawFileDescriptor chunkPath() {
113116
if (repositoryLocationBytes == null) {
114117
if (!openEmergencyDumpFile()) {
115118
return WordFactory.nullPointer();
116119
}
117-
// We can directly use the emergency dump file name as the chunk.
120+
// We can directly use the emergency dump file name as the new chunk since there are no other chunk files.
118121
return emergencyFd;
119122
}
123+
Log.log().string("Creating a new emergency chunk file in the JFR disk repository").newline();
120124
return createEmergencyChunkPath();
121125
}
122126

127+
/** The normal chunkfile name format is: repository path + file separator + date time + extension.
128+
* In this case we just use a hardcoded string instead of date time, which will successfully rank last in lexographic order among other chunkfile names.*/
129+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp#L418-L431")
123130
private RawFileDescriptor createEmergencyChunkPath() {
124-
int idx = 0;
125131
clearPathBuffer();
126-
for (int i = 0; i < repositoryLocationBytes.length; i++) {
127-
getPathBuffer().write(idx++, repositoryLocationBytes[i]);
128-
}
132+
int idx = 0;
133+
idx = writeToPathBuffer(repositoryLocationBytes, idx);
129134
getPathBuffer().write(idx++, FILE_SEPARATOR);
130-
131-
for (int i = 0; i < CHUNKFILE_EXTENSION_BYTES.length; i++) {
132-
getPathBuffer().write(idx++, CHUNKFILE_EXTENSION_BYTES[i]);
133-
}
134-
// TODO what about date time? Need that for sorting.
135-
// repository path + file separator + date time + extension
135+
idx = writeToPathBuffer(EMERGENCY_CHUNK_BYTES, idx);
136+
writeToPathBuffer(CHUNKFILE_EXTENSION_BYTES, idx);
136137
return getFileSupport().create(getPathBuffer(), FileCreationMode.CREATE, FileAccessMode.READ_WRITE);
137138
}
138139

@@ -171,32 +172,21 @@ private boolean openEmergencyDumpFile() {
171172
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp#L110-L129")
172173
private CCharPointer createEmergencyDumpPath() {
173174
int idx = 0;
174-
175175
clearPathBuffer();
176176

177177
if (dumpPathBytes != null) {
178-
for (int i = 0; i < dumpPathBytes.length; i++) {
179-
getPathBuffer().write(idx++, dumpPathBytes[i]);
180-
}
178+
idx = writeToPathBuffer(dumpPathBytes, idx);
181179
// Add delimiter
182180
getPathBuffer().write(idx++, FILE_SEPARATOR);
183181
}
184182

185-
for (int i = 0; i < DUMP_FILE_PREFIX.length; i++) {
186-
getPathBuffer().write(idx++, DUMP_FILE_PREFIX[i]);
187-
}
188-
189-
for (int i = 0; i < pidBytes.length; i++) {
190-
getPathBuffer().write(idx++, pidBytes[i]);
191-
}
192-
193-
for (int i = 0; i < CHUNKFILE_EXTENSION_BYTES.length; i++) {
194-
getPathBuffer().write(idx++, CHUNKFILE_EXTENSION_BYTES[i]);
195-
}
196-
183+
idx = writeToPathBuffer(DUMP_FILE_PREFIX, idx);
184+
idx = writeToPathBuffer(pidBytes, idx);
185+
writeToPathBuffer(CHUNKFILE_EXTENSION_BYTES, idx);
197186
return getPathBuffer();
198187
}
199188

189+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp#L310-L345")
200190
private GrowableWordArray iterateRepository(GrowableWordArray gwa) {
201191
int count = 0;
202192
// Open directory
@@ -307,9 +297,7 @@ private boolean openDirectory() {
307297

308298
private CCharPointer getRepositoryLocation() {
309299
clearPathBuffer();
310-
for (int i = 0; i < repositoryLocationBytes.length; i++) {
311-
getPathBuffer().write(i, repositoryLocationBytes[i]);
312-
}
300+
writeToPathBuffer(repositoryLocationBytes,0);
313301
return getPathBuffer();
314302
}
315303

@@ -374,9 +362,7 @@ private CCharPointer fullyQualified(CCharPointer fn) {
374362
// TODO HS uses _path_buffer_file_name_offset to avoid building this part of th path each
375363
// time.
376364
// Cached in RepositoryIterator::RepositoryIterator and used in fully_qualified
377-
for (int i = 0; i < repositoryLocationBytes.length; i++) {
378-
getPathBuffer().write(idx++, repositoryLocationBytes[i]);
379-
}
365+
idx = writeToPathBuffer(repositoryLocationBytes, idx);
380366

381367
// Add delimiter
382368
getPathBuffer().write(idx++, FILE_SEPARATOR);
@@ -396,6 +382,13 @@ private void clearPathBuffer() {
396382
LibC.memset(getPathBuffer(), Word.signed(0), Word.unsigned(JVM_MAXPATHLEN));
397383
}
398384

385+
private int writeToPathBuffer(byte[] bytes, int idx){
386+
for (int i = 0; i < bytes.length; i++) {
387+
getPathBuffer().write(idx++, bytes[i]);
388+
}
389+
return idx;
390+
}
391+
399392
@Fold
400393
static RawFileOperationSupport getFileSupport() {
401394
return RawFileOperationSupport.bigEndian();

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -752,16 +752,13 @@ public void vmErrorRotation() {
752752
try {
753753
boolean existingFile = chunkWriter.hasOpenFile();
754754
if (!existingFile) {
755-
Log.log().string("no existing chunk file.").newline();
756-
// If no chunkfile is open, create one.
757-
// TODO when would a file not already be open? must be open for flushes.
758-
// RawFileOperationSupport.RawFileDescriptor fd = JfrEmergencyDumpSupport.singleton().chunkPath();
759-
// chunkWriter.openFile(fd);
760-
// chunkWriter.closeFileForEmergencyDump();
761-
} else {
762-
assert chunkWriter.hasOpenFile();
763-
chunkWriter.closeFileForEmergencyDump();
755+
// If no chunkfile is open, create one. This case is very unlikely.
756+
Log.log().string("No existing chunk file. Creating one.").newline();
757+
RawFileOperationSupport.RawFileDescriptor fd = JfrEmergencyDumpSupport.singleton().chunkPath();
758+
chunkWriter.openFile(fd);
764759
}
760+
assert chunkWriter.hasOpenFile();
761+
chunkWriter.closeFileForEmergencyDump();
765762
JfrEmergencyDumpSupport.singleton().onVmError();
766763
} finally {
767764
chunkWriter.unlock();

0 commit comments

Comments
 (0)