src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java
branchJEP-349-branch
changeset 58129 7b751fe181a5
parent 58020 f082177c5023
equal deleted inserted replaced
58121:6f8f18ac1d54 58129:7b751fe181a5
    46 /**
    46 /**
    47  * Parses a chunk.
    47  * Parses a chunk.
    48  *
    48  *
    49  */
    49  */
    50 final class ChunkParser {
    50 final class ChunkParser {
       
    51 
       
    52     static final class ParserConfiguration {
       
    53         final boolean reuse;
       
    54         final boolean ordered;
       
    55         final InternalEventFilter eventFilter;
       
    56 
       
    57         long filterStart;
       
    58         long filterEnd;
       
    59 
       
    60         public ParserConfiguration(long filterStart, long filterEnd, boolean reuse, boolean ordered, InternalEventFilter filter) {
       
    61             this.filterStart = filterStart;
       
    62             this.filterEnd = filterEnd;
       
    63             this.reuse = reuse;
       
    64             this.ordered = ordered;
       
    65             this.eventFilter = filter;
       
    66         }
       
    67 
       
    68         public ParserConfiguration() {
       
    69             this(0, Long.MAX_VALUE, false, false, InternalEventFilter.ACCEPT_ALL);
       
    70         }
       
    71     }
       
    72 
    51     // Checkpoint that finishes a flush segment
    73     // Checkpoint that finishes a flush segment
    52     static final byte CHECKPOINT_FLUSH_MASK = 1;
    74     static final byte CHECKPOINT_FLUSH_MASK = 1;
    53     // Checkpoint contains chunk header information in the first pool
    75     // Checkpoint contains chunk header information in the first pool
    54     static final byte CHECKPOINT_CHUNK_HEADER_MASK = 2;
    76     static final byte CHECKPOINT_CHUNK_HEADER_MASK = 2;
    55     // Checkpoint contains only statics that will not change from chunk to chunk
    77     // Checkpoint contains only statics that will not change from chunk to chunk
    68     private final LongMap<ConstantLookup> constantLookups;
    90     private final LongMap<ConstantLookup> constantLookups;
    69 
    91 
    70     private LongMap<Type> typeMap;
    92     private LongMap<Type> typeMap;
    71     private LongMap<Parser> parsers;
    93     private LongMap<Parser> parsers;
    72     private boolean chunkFinished;
    94     private boolean chunkFinished;
    73     private InternalEventFilter eventFilter = InternalEventFilter.ACCEPT_ALL;
    95 
    74     private boolean reuse;
       
    75     private boolean ordered;
       
    76     private boolean resetEventCache;
       
    77     private long filterStart = 0;
       
    78     private long filterEnd = Long.MAX_VALUE;
       
    79     private Runnable flushOperation;
    96     private Runnable flushOperation;
    80 
    97     private ParserConfiguration configuration;
    81     public ChunkParser(RecordingInput input, boolean reuse) throws IOException {
    98 
    82        this(new ChunkHeader(input), null, 1000);
    99     public ChunkParser(RecordingInput input) throws IOException {
    83        this.reuse = reuse;
   100         this(input, new ParserConfiguration());
       
   101     }
       
   102 
       
   103     public ChunkParser(RecordingInput input, ParserConfiguration pc) throws IOException {
       
   104        this(new ChunkHeader(input), null, pc);
    84     }
   105     }
    85 
   106 
    86     public ChunkParser(ChunkParser previous) throws IOException {
   107     public ChunkParser(ChunkParser previous) throws IOException {
    87         this(new ChunkHeader(previous.input), previous, 1000);
   108         this(new ChunkHeader(previous.input), previous, new ParserConfiguration());
    88      }
   109      }
    89 
   110 
    90     private ChunkParser(ChunkHeader header, ChunkParser previous, long pollInterval) throws IOException {
   111     private ChunkParser(ChunkHeader header, ChunkParser previous, ParserConfiguration pc) throws IOException {
       
   112         this.configuration = pc;
    91         this.input = header.getInput();
   113         this.input = header.getInput();
    92         this.chunkHeader = header;
   114         this.chunkHeader = header;
    93         if (previous == null) {
   115         if (previous == null) {
    94             this.pollInterval = 1000;
   116             this.pollInterval = 1000;
    95             this.constantLookups = new LongMap<>();
   117             this.constantLookups = new LongMap<>();
    96             this.previousMetadata = null;
   118             this.previousMetadata = null;
    97         } else {
   119         } else {
    98             this.constantLookups = previous.constantLookups;
   120             this.constantLookups = previous.constantLookups;
    99             this.previousMetadata = previous.metadata;
   121             this.previousMetadata = previous.metadata;
   100             this.pollInterval = previous.pollInterval;
   122             this.pollInterval = previous.pollInterval;
   101             this.ordered = previous.ordered;
   123             this.configuration = previous.configuration;
   102             this.reuse = previous.reuse;
       
   103             this.eventFilter = previous.eventFilter;
       
   104         }
   124         }
   105         this.metadata = header.readMetadata(previousMetadata);
   125         this.metadata = header.readMetadata(previousMetadata);
   106         this.timeConverter = new TimeConverter(chunkHeader, metadata.getGMTOffset());
   126         this.timeConverter = new TimeConverter(chunkHeader, metadata.getGMTOffset());
   107         if (metadata != previousMetadata) {
   127         if (metadata != previousMetadata) {
   108             ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter);
   128             ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter);
   109             parsers = factory.getParsers();
   129             parsers = factory.getParsers();
   110             typeMap = factory.getTypeMap();
   130             typeMap = factory.getTypeMap();
   111             updateEventParsers();
   131             updateConfiguration();
   112         } else {
   132         } else {
   113             parsers = previous.parsers;
   133             parsers = previous.parsers;
   114             typeMap = previous.typeMap;
   134             typeMap = previous.typeMap;
   115         }
   135         }
   116         constantLookups.forEach(c -> c.newPool());
   136         constantLookups.forEach(c -> c.newPool());
   120         constantLookups.forEach(c -> c.getLatestPool().setResolved());
   140         constantLookups.forEach(c -> c.getLatestPool().setResolved());
   121 
   141 
   122         input.position(chunkHeader.getEventStart());
   142         input.position(chunkHeader.getEventStart());
   123     }
   143     }
   124 
   144 
   125     public void setParserFilter(InternalEventFilter filter) {
   145     public ChunkParser nextChunkParser() throws IOException {
   126         this.eventFilter = filter;
   146         return new ChunkParser(chunkHeader.nextHeader(), this, configuration);
   127     }
   147     }
   128 
   148 
   129     public InternalEventFilter getEventFilter() {
   149     private void updateConfiguration() {
   130         return this.eventFilter;
   150         updateConfiguration(configuration, false);
       
   151     }
       
   152 
       
   153     public void updateConfiguration(ParserConfiguration configuration, boolean resetEventCache) {
       
   154         this.configuration = configuration;
       
   155         parsers.forEach(p -> {
       
   156             if (p instanceof EventParser) {
       
   157                 EventParser ep = (EventParser) p;
       
   158                 if (resetEventCache) {
       
   159                     ep.resetCache();
       
   160                 }
       
   161                 String name = ep.getEventType().getName();
       
   162                 ep.setOrdered(configuration.ordered);
       
   163                 ep.setReuse(configuration.reuse);
       
   164                 ep.setFilterStart(configuration.filterStart);
       
   165                 ep.setFilterEnd(configuration.filterEnd);
       
   166                 long threshold = configuration.eventFilter.getThreshold(name);
       
   167                 if (threshold >= 0) {
       
   168                     ep.setEnabled(true);
       
   169                     ep.setThresholdNanos(threshold);
       
   170                 } else {
       
   171                     ep.setEnabled(false);
       
   172                     ep.setThresholdNanos(Long.MAX_VALUE);
       
   173                 }
       
   174             }
       
   175         });
   131     }
   176     }
   132 
   177 
   133     /**
   178     /**
   134      * Reads an event and returns null when segment or chunk ends.
   179      * Reads an event and returns null when segment or chunk ends.
   135      *
   180      *
   159                 Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new metadata in chunk. Rebuilding types and parsers");
   204                 Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new metadata in chunk. Rebuilding types and parsers");
   160                 MetadataDescriptor metadata = chunkHeader.readMetadata(previousMetadata);
   205                 MetadataDescriptor metadata = chunkHeader.readMetadata(previousMetadata);
   161                 ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter);
   206                 ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter);
   162                 parsers = factory.getParsers();
   207                 parsers = factory.getParsers();
   163                 typeMap = factory.getTypeMap();
   208                 typeMap = factory.getTypeMap();
   164                 updateEventParsers();
   209                 updateConfiguration();;
   165             }
   210             }
   166             if (contantPosition != chunkHeader.getConstantPoolPosition()) {
   211             if (contantPosition != chunkHeader.getConstantPoolPosition()) {
   167                 Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new constant pool data. Filling up pools with new values");
   212                 Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new constant pool data. Filling up pools with new values");
   168                 constantLookups.forEach(c -> c.getLatestPool().setAllResolved(false));
   213                 constantLookups.forEach(c -> c.getLatestPool().setAllResolved(false));
   169                 fillConstantPools(contantPosition + chunkHeader.getAbsoluteChunkStart());
   214                 fillConstantPools(contantPosition + chunkHeader.getAbsoluteChunkStart());
   370 
   415 
   371     public ChunkParser newChunkParser() throws IOException {
   416     public ChunkParser newChunkParser() throws IOException {
   372         return new ChunkParser(this);
   417         return new ChunkParser(this);
   373     }
   418     }
   374 
   419 
   375     public ChunkParser nextChunkParser() throws IOException {
       
   376         return new ChunkParser(chunkHeader.nextHeader(), this, pollInterval);
       
   377     }
       
   378 
       
   379     public boolean isChunkFinished() {
   420     public boolean isChunkFinished() {
   380         return chunkFinished;
   421         return chunkFinished;
   381     }
   422     }
   382 
   423 
   383     // Need to call updateEventParsers() for
       
   384     // change to take effect
       
   385     public void setReuse(boolean resue) {
       
   386         this.reuse = resue;
       
   387     }
       
   388 
       
   389     public void setFlushOperation(Runnable flushOperation) {
   424     public void setFlushOperation(Runnable flushOperation) {
   390         this.flushOperation = flushOperation;
   425         this.flushOperation = flushOperation;
   391     }
   426     }
   392 
   427 
   393     // Need to call updateEventParsers() for
       
   394     // change to take effect
       
   395     public void setOrdered(boolean ordered) {
       
   396         this.ordered = ordered;
       
   397     }
       
   398 
       
   399     // Need to call updateEventParsers() for
       
   400     // change to take effect
       
   401     public void setFilterStart(long filterStart) {
       
   402         long chunkStart = chunkHeader.getStartNanos();
       
   403         // Optimization.
       
   404         if (filterStart < chunkStart - 1_000_000_000L) {
       
   405             filterStart = 0;
       
   406         }
       
   407         this.filterStart = filterStart;
       
   408     }
       
   409 
       
   410     public void setFilterEnd(long filterEnd) {
       
   411         this.filterEnd = filterEnd;
       
   412     }
       
   413 
       
   414     // Need to call updateEventParsers() for
       
   415     // change to take effect
       
   416     public void resetEventCache() {
       
   417         this.resetEventCache = true;
       
   418     }
       
   419 
       
   420     public void updateEventParsers() {
       
   421         parsers.forEach(p -> {
       
   422             if (p instanceof EventParser) {
       
   423                 EventParser ep = (EventParser) p;
       
   424                 String name = ep.getEventType().getName();
       
   425                 ep.setOrdered(ordered);
       
   426                 ep.setReuse(reuse);
       
   427                 ep.setFilterStart(filterStart);
       
   428                 ep.setFilterEnd(filterEnd);
       
   429                 if (resetEventCache) {
       
   430                     ep.resetCache();
       
   431                 }
       
   432                 long threshold = eventFilter.getThreshold(name);
       
   433                 if (threshold >= 0) {
       
   434                     ep.setEnabled(true);
       
   435                     ep.setThresholdNanos(threshold);
       
   436                 } else {
       
   437                     ep.setEnabled(false);
       
   438                     ep.setThresholdNanos(Long.MAX_VALUE);
       
   439                 }
       
   440             }
       
   441         });
       
   442         resetEventCache = false;
       
   443     }
       
   444 
       
   445     public long getChunkDuration() {
   428     public long getChunkDuration() {
   446         return chunkHeader.getDurationNanos();
   429         return chunkHeader.getDurationNanos();
   447     }
   430     }
   448 
   431 
   449     public long getStartNanos() {
   432     public long getStartNanos() {
   450         return chunkHeader.getStartNanos();
   433         return chunkHeader.getStartNanos();
   451     }
   434     }
       
   435 
   452 }
   436 }