src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java
changeset 58863 c16ac7a2eba4
parent 52850 f527b24990d7
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
     1 /*
     1 /*
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    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;
   102      * @throws SecurityException if a security manager exists and its
    81      * @throws SecurityException if a security manager exists and its
   103      *         {@code checkRead} method denies read access to the file.
    82      *         {@code checkRead} method denies read access to the file.
   104      */
    83      */
   105     public RecordingFile(Path file) throws IOException {
    84     public RecordingFile(Path file) throws IOException {
   106         this.file = file.toFile();
    85         this.file = file.toFile();
   107         this.input = new RecordingInput(this.file);
    86         this.input = new RecordingInput(this.file, FileAccess.UNPRIVILIGED);
   108         findNext();
    87         findNext();
   109     }
    88     }
   110 
    89 
   111     /**
    90     /**
   112      * Reads the next event in the recording.
    91      * Reads the next event in the recording.
   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.
   243                 list.add(r.readEvent());
   227                 list.add(r.readEvent());
   244             }
   228             }
   245             return list;
   229             return list;
   246         }
   230         }
   247     }
   231     }
       
   232 
       
   233     // package protected
       
   234     File getFile() {
       
   235         return file;
       
   236     }
       
   237 
       
   238     // package protected
       
   239     boolean isLastEventInChunk() {
       
   240         return isLastEventInChunk;
       
   241     }
       
   242 
   248 
   243 
   249     // either sets next to an event or sets eof to true
   244     // either sets next to an event or sets eof to true
   250     private void findNext() throws IOException {
   245     private void findNext() throws IOException {
   251         while (nextEvent == null) {
   246         while (nextEvent == null) {
   252             if (chunkParser == null) {
   247             if (chunkParser == null) {