30 import java.io.File; |
30 import java.io.File; |
31 import java.io.IOException; |
31 import java.io.IOException; |
32 import java.nio.file.NoSuchFileException; |
32 import java.nio.file.NoSuchFileException; |
33 import java.nio.file.Path; |
33 import java.nio.file.Path; |
34 import java.util.ArrayList; |
34 import java.util.ArrayList; |
35 import java.util.Collections; |
|
36 import java.util.HashSet; |
35 import java.util.HashSet; |
37 import java.util.List; |
36 import java.util.List; |
38 |
37 |
39 import jdk.jfr.EventType; |
38 import jdk.jfr.EventType; |
40 import jdk.jfr.internal.MetadataDescriptor; |
39 import jdk.jfr.internal.MetadataDescriptor; |
41 import jdk.jfr.internal.Type; |
40 import jdk.jfr.internal.Type; |
42 import jdk.jfr.internal.consumer.ChunkHeader; |
41 import jdk.jfr.internal.consumer.ChunkHeader; |
|
42 import jdk.jfr.internal.consumer.ChunkParser; |
|
43 import jdk.jfr.internal.consumer.FileAccess; |
43 import jdk.jfr.internal.consumer.RecordingInput; |
44 import jdk.jfr.internal.consumer.RecordingInput; |
44 import jdk.jfr.internal.consumer.RecordingInternals; |
|
45 |
45 |
46 /** |
46 /** |
47 * A recording file. |
47 * A recording file. |
48 * <p> |
48 * <p> |
49 * The following example shows how read and print all events in a recording file. |
49 * The following example shows how read and print all events in a recording file. |
60 * </pre> |
60 * </pre> |
61 * |
61 * |
62 * @since 9 |
62 * @since 9 |
63 */ |
63 */ |
64 public final class RecordingFile implements Closeable { |
64 public final class RecordingFile implements Closeable { |
65 static{ |
|
66 RecordingInternals.INSTANCE = new RecordingInternals() { |
|
67 public List<Type> readTypes(RecordingFile file) throws IOException { |
|
68 return file.readTypes(); |
|
69 } |
|
70 |
|
71 public boolean isLastEventInChunk(RecordingFile file) { |
|
72 return file.isLastEventInChunk; |
|
73 } |
|
74 |
|
75 @Override |
|
76 public Object getOffsetDataTime(RecordedObject event, String name) { |
|
77 return event.getOffsetDateTime(name); |
|
78 } |
|
79 |
|
80 @Override |
|
81 public void sort(List<RecordedEvent> events) { |
|
82 Collections.sort(events, (e1, e2) -> Long.compare(e1.endTime, e2.endTime)); |
|
83 } |
|
84 }; |
|
85 } |
|
86 |
65 |
87 private boolean isLastEventInChunk; |
66 private boolean isLastEventInChunk; |
88 private final File file; |
67 private final File file; |
89 private RecordingInput input; |
68 private RecordingInput input; |
90 private ChunkParser chunkParser; |
69 private ChunkParser chunkParser; |
152 * |
131 * |
153 * @see #hasMoreEvents() |
132 * @see #hasMoreEvents() |
154 */ |
133 */ |
155 public List<EventType> readEventTypes() throws IOException { |
134 public List<EventType> readEventTypes() throws IOException { |
156 ensureOpen(); |
135 ensureOpen(); |
|
136 MetadataDescriptor previous = null; |
157 List<EventType> types = new ArrayList<>(); |
137 List<EventType> types = new ArrayList<>(); |
158 HashSet<Long> foundIds = new HashSet<>(); |
138 HashSet<Long> foundIds = new HashSet<>(); |
159 try (RecordingInput ri = new RecordingInput(file)) { |
139 try (RecordingInput ri = new RecordingInput(file, FileAccess.UNPRIVILIGED)) { |
160 ChunkHeader ch = new ChunkHeader(ri); |
140 ChunkHeader ch = new ChunkHeader(ri); |
161 aggregateEventTypeForChunk(ch, types, foundIds); |
141 aggregateEventTypeForChunk(ch, null, types, foundIds); |
162 while (!ch.isLastChunk()) { |
142 while (!ch.isLastChunk()) { |
163 ch = ch.nextHeader(); |
143 ch = ch.nextHeader(); |
164 aggregateEventTypeForChunk(ch, types, foundIds); |
144 previous = aggregateEventTypeForChunk(ch, previous, types, foundIds); |
165 } |
145 } |
166 } |
146 } |
167 return types; |
147 return types; |
168 } |
148 } |
169 |
149 |
170 List<Type> readTypes() throws IOException { |
150 List<Type> readTypes() throws IOException { |
171 ensureOpen(); |
151 ensureOpen(); |
|
152 MetadataDescriptor previous = null; |
172 List<Type> types = new ArrayList<>(); |
153 List<Type> types = new ArrayList<>(); |
173 HashSet<Long> foundIds = new HashSet<>(); |
154 HashSet<Long> foundIds = new HashSet<>(); |
174 try (RecordingInput ri = new RecordingInput(file)) { |
155 try (RecordingInput ri = new RecordingInput(file, FileAccess.UNPRIVILIGED)) { |
175 ChunkHeader ch = new ChunkHeader(ri); |
156 ChunkHeader ch = new ChunkHeader(ri); |
176 aggregateTypeForChunk(ch, types, foundIds); |
157 ch.awaitFinished(); |
|
158 aggregateTypeForChunk(ch, null, types, foundIds); |
177 while (!ch.isLastChunk()) { |
159 while (!ch.isLastChunk()) { |
178 ch = ch.nextHeader(); |
160 ch = ch.nextHeader(); |
179 aggregateTypeForChunk(ch, types, foundIds); |
161 previous = aggregateTypeForChunk(ch, previous, types, foundIds); |
180 } |
162 } |
181 } |
163 } |
182 return types; |
164 return types; |
183 } |
165 } |
184 |
166 |
185 private void aggregateTypeForChunk(ChunkHeader ch, List<Type> types, HashSet<Long> foundIds) throws IOException { |
167 private MetadataDescriptor aggregateTypeForChunk(ChunkHeader ch, MetadataDescriptor previous, List<Type> types, HashSet<Long> foundIds) throws IOException { |
186 MetadataDescriptor m = ch.readMetadata(); |
168 MetadataDescriptor m = ch.readMetadata(previous); |
187 for (Type t : m.getTypes()) { |
169 for (Type t : m.getTypes()) { |
188 if (!foundIds.contains(t.getId())) { |
170 if (!foundIds.contains(t.getId())) { |
189 types.add(t); |
171 types.add(t); |
190 foundIds.add(t.getId()); |
172 foundIds.add(t.getId()); |
191 } |
173 } |
192 } |
174 } |
193 } |
175 return m; |
194 |
176 } |
195 private static void aggregateEventTypeForChunk(ChunkHeader ch, List<EventType> types, HashSet<Long> foundIds) throws IOException { |
177 |
196 MetadataDescriptor m = ch.readMetadata(); |
178 private static MetadataDescriptor aggregateEventTypeForChunk(ChunkHeader ch, MetadataDescriptor previous, List<EventType> types, HashSet<Long> foundIds) throws IOException { |
|
179 MetadataDescriptor m = ch.readMetadata(previous); |
197 for (EventType t : m.getEventTypes()) { |
180 for (EventType t : m.getEventTypes()) { |
198 if (!foundIds.contains(t.getId())) { |
181 if (!foundIds.contains(t.getId())) { |
199 types.add(t); |
182 types.add(t); |
200 foundIds.add(t.getId()); |
183 foundIds.add(t.getId()); |
201 } |
184 } |
202 } |
185 } |
|
186 return m; |
203 } |
187 } |
204 |
188 |
205 /** |
189 /** |
206 * Closes this recording file and releases any system resources that are |
190 * Closes this recording file and releases any system resources that are |
207 * associated with it. |
191 * associated with it. |