src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventParser.java
changeset 58863 c16ac7a2eba4
parent 50113 caf115bb98ad
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
       
     1 /*
       
     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.
       
     4  *
       
     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
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package jdk.jfr.internal.consumer;
       
    27 
       
    28 import static jdk.jfr.internal.EventInstrumentation.FIELD_DURATION;
       
    29 
       
    30 import java.io.IOException;
       
    31 import java.util.List;
       
    32 
       
    33 import jdk.jfr.EventType;
       
    34 import jdk.jfr.ValueDescriptor;
       
    35 import jdk.jfr.consumer.RecordedEvent;
       
    36 import jdk.jfr.internal.consumer.Parser;
       
    37 import jdk.jfr.internal.consumer.RecordingInput;
       
    38 
       
    39 /**
       
    40  * Parses an event and returns a {@link RecordedEvent}.
       
    41  *
       
    42  */
       
    43 final class EventParser extends Parser {
       
    44 
       
    45     private static final JdkJfrConsumer PRIVATE_ACCESS = JdkJfrConsumer.instance();
       
    46 
       
    47     private final Parser[] parsers;
       
    48     private final EventType eventType;
       
    49     private final TimeConverter timeConverter;
       
    50     private final boolean hasDuration;
       
    51     private final List<ValueDescriptor> valueDescriptors;
       
    52     private final int startIndex;
       
    53     private final int length;
       
    54     private final RecordedEvent unorderedEvent;
       
    55     private final ObjectContext objectContext;
       
    56 
       
    57     private RecordedEvent[] cached;
       
    58     private int cacheIndex;
       
    59 
       
    60     private boolean enabled = true;
       
    61     private boolean ordered;
       
    62     private long filterStart;
       
    63     private long filterEnd = Long.MAX_VALUE;
       
    64     private long thresholdNanos = -1;
       
    65 
       
    66     EventParser(TimeConverter timeConverter, EventType type, Parser[] parsers) {
       
    67         this.timeConverter = timeConverter;
       
    68         this.parsers = parsers;
       
    69         this.eventType = type;
       
    70         this.hasDuration = type.getField(FIELD_DURATION) != null;
       
    71         this.startIndex = hasDuration ? 2 : 1;
       
    72         this.length = parsers.length - startIndex;
       
    73         this.valueDescriptors = type.getFields();
       
    74         this.objectContext = new ObjectContext(type, valueDescriptors, timeConverter);
       
    75         this.unorderedEvent = PRIVATE_ACCESS.newRecordedEvent(objectContext, new Object[length], 0L, 0L);
       
    76     }
       
    77 
       
    78     private RecordedEvent cachedEvent() {
       
    79         if (ordered) {
       
    80             if (cacheIndex == cached.length) {
       
    81                 RecordedEvent[] old = cached;
       
    82                 cached = new RecordedEvent[cached.length * 2];
       
    83                 System.arraycopy(old, 0, cached, 0, old.length);
       
    84             }
       
    85             RecordedEvent event = cached[cacheIndex];
       
    86             if (event == null) {
       
    87                 event = PRIVATE_ACCESS.newRecordedEvent(objectContext, new Object[length], 0L, 0L);
       
    88                 cached[cacheIndex] = event;
       
    89             }
       
    90             cacheIndex++;
       
    91             return event;
       
    92         } else {
       
    93             return unorderedEvent;
       
    94         }
       
    95     }
       
    96 
       
    97     public EventType getEventType() {
       
    98         return eventType;
       
    99     }
       
   100 
       
   101     public void setThresholdNanos(long thresholdNanos) {
       
   102         this.thresholdNanos = thresholdNanos;
       
   103     }
       
   104 
       
   105     public void setEnabled(boolean enabled) {
       
   106         this.enabled = enabled;
       
   107     }
       
   108 
       
   109     public boolean isEnabled() {
       
   110         return enabled;
       
   111     }
       
   112 
       
   113     public RecordedEvent parse(RecordingInput input) throws IOException {
       
   114         if (!enabled) {
       
   115             return null;
       
   116         }
       
   117 
       
   118         long startTicks = input.readLong();
       
   119         long endTicks = startTicks;
       
   120         if (hasDuration) {
       
   121             long durationTicks = input.readLong();
       
   122             if (thresholdNanos > 0L) {
       
   123                 if (timeConverter.convertTimespan(durationTicks) < thresholdNanos) {
       
   124                     return null;
       
   125                 }
       
   126             }
       
   127             endTicks += durationTicks;
       
   128         }
       
   129         if (filterStart != 0L || filterEnd != Long.MAX_VALUE) {
       
   130             long eventEnd = timeConverter.convertTimestamp(endTicks);
       
   131             if (eventEnd < filterStart) {
       
   132                 return null;
       
   133             }
       
   134             if (eventEnd > filterEnd) {
       
   135                 return null;
       
   136             }
       
   137         }
       
   138 
       
   139         if (cached != null) {
       
   140             RecordedEvent event = cachedEvent();
       
   141             JdkJfrConsumer access = PRIVATE_ACCESS;
       
   142             access.setStartTicks(event, startTicks);
       
   143             access.setEndTicks(event, endTicks);
       
   144             Object[] values = access.eventValues(event);
       
   145             for (int i = 0; i < values.length; i++) {
       
   146                 values[i] = parsers[startIndex + i].parse(input);
       
   147             }
       
   148             return event;
       
   149         }
       
   150 
       
   151         Object[] values = new Object[length];
       
   152         for (int i = 0; i < values.length; i++) {
       
   153             values[i] = parsers[startIndex + i].parse(input);
       
   154         }
       
   155         return PRIVATE_ACCESS.newRecordedEvent(objectContext, values, startTicks, endTicks);
       
   156     }
       
   157 
       
   158     @Override
       
   159     public void skip(RecordingInput input) throws IOException {
       
   160         throw new InternalError("Should not call this method. More efficent to read event size and skip ahead");
       
   161     }
       
   162 
       
   163     public void resetCache() {
       
   164         cacheIndex = 0;
       
   165     }
       
   166 
       
   167     private boolean hasReuse() {
       
   168         return cached != null;
       
   169     }
       
   170 
       
   171     public void setReuse(boolean reuse) {
       
   172         if (reuse == hasReuse()) {
       
   173             return;
       
   174         }
       
   175         if (reuse) {
       
   176             cached = new RecordedEvent[2];
       
   177             cacheIndex = 0;
       
   178         } else {
       
   179             cached = null;
       
   180         }
       
   181     }
       
   182 
       
   183     public void setFilterStart(long filterStart) {
       
   184         this.filterStart = filterStart;
       
   185     }
       
   186 
       
   187     public void setFilterEnd(long filterEnd) {
       
   188         this.filterEnd = filterEnd;
       
   189     }
       
   190 
       
   191     public void setOrdered(boolean ordered) {
       
   192         if (this.ordered == ordered) {
       
   193             return;
       
   194         }
       
   195         this.ordered = ordered;
       
   196         this.cacheIndex = 0;
       
   197     }
       
   198 }