src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java
author egahlin
Tue, 15 May 2018 20:24:34 +0200
changeset 50113 caf115bb98ad
child 52850 f527b24990d7
permissions -rw-r--r--
8199712: Flight Recorder Reviewed-by: coleenp, ihse, erikj, dsamersoff, mseledtsov, egahlin, mgronlun Contributed-by: erik.gahlin@oracle.com, markus.gronlund@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     2
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     4
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    10
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    15
 * accompanied this code).
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    16
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    20
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    23
 * questions.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    24
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    25
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    26
package jdk.jfr.consumer;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    27
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    28
import java.io.IOException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    29
import java.util.Collection;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    30
import java.util.List;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    31
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    32
import jdk.jfr.EventType;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    33
import jdk.jfr.internal.LogLevel;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    34
import jdk.jfr.internal.LogTag;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    35
import jdk.jfr.internal.Logger;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
import jdk.jfr.internal.MetadataDescriptor;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    37
import jdk.jfr.internal.Type;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
import jdk.jfr.internal.consumer.ChunkHeader;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
import jdk.jfr.internal.consumer.RecordingInput;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
/**
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
 * Parses a chunk.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
final class ChunkParser {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
    private static final long CONSTANT_POOL_TYPE_ID = 1;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
    private final RecordingInput input;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
    private final LongMap<Parser> parsers;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
    private final ChunkHeader chunkHeader;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
    private final long absoluteChunkEnd;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
    private final MetadataDescriptor metadata;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
    private final LongMap<Type> typeMap;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
    private final TimeConverter timeConverter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
    public ChunkParser(RecordingInput input) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
      this(new ChunkHeader(input));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    57
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    58
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    59
    private ChunkParser(ChunkHeader header) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    60
        this.input = header.getInput();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    61
        this.chunkHeader = header;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    62
        this.metadata = header.readMetadata();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    63
        this.absoluteChunkEnd = header.getEnd();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    64
        this.timeConverter =  new TimeConverter(chunkHeader);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
        ParserFactory factory = new ParserFactory(metadata, timeConverter);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    67
        LongMap<ConstantMap> constantPools = factory.getConstantPools();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    68
        parsers = factory.getParsers();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    69
        typeMap = factory.getTypeMap();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    70
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    71
        fillConstantPools(parsers, constantPools);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    72
        constantPools.forEach(ConstantMap::setIsResolving);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    73
        constantPools.forEach(ConstantMap::resolve);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    74
        constantPools.forEach(ConstantMap::setResolved);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    75
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    76
        input.position(chunkHeader.getEventStart());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    77
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    78
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    79
    public RecordedEvent readEvent() throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    80
        while (input.position() < absoluteChunkEnd) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    81
            long pos = input.position();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    82
            int size = input.readInt();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    83
            if (size == 0) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    84
                throw new IOException("Event can't have zero size");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    85
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    86
            long typeId = input.readLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    87
            if (typeId > CONSTANT_POOL_TYPE_ID) { // also skips metadata (id=0)
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    88
                Parser ep = parsers.get(typeId);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    89
                if (ep instanceof EventParser) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    90
                    return (RecordedEvent) ep.parse(input);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    91
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    92
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    93
            input.position(pos + size);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    94
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    95
        return null;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    96
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    97
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    98
    private void fillConstantPools(LongMap<Parser> typeParser, LongMap<ConstantMap> constantPools) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    99
        long nextCP = chunkHeader.getAbsoluteChunkStart();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   100
        long deltaToNext = chunkHeader.getConstantPoolPosition();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   101
        while (deltaToNext != 0) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   102
            nextCP += deltaToNext;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   103
            input.position(nextCP);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   104
            final long position = nextCP;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   105
            int size = input.readInt(); // size
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   106
            long typeId = input.readLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   107
            if (typeId != CONSTANT_POOL_TYPE_ID) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   108
                throw new IOException("Expected check point event (id = 1) at position " + nextCP + ", but found type id = " + typeId);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   109
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   110
            input.readLong(); // timestamp
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   111
            input.readLong(); // duration
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   112
            deltaToNext = input.readLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   113
            final long delta = deltaToNext;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   114
            boolean flush = input.readBoolean();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   115
            int poolCount = input.readInt();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   116
            Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, () -> {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   117
                return "New constant pool: startPosition=" + position +
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   118
                        ", size=" + size + ", deltaToNext=" + delta +
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   119
                        ", flush=" + flush + ", poolCount=" + poolCount;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   120
            });
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   121
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   122
            for (int i = 0; i < poolCount; i++) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   123
                long id = input.readLong(); // type id
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   124
                ConstantMap pool = constantPools.get(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   125
                Type type = typeMap.get(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   126
                if (pool == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   127
                    Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found constant pool(" + id + ") that is never used");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   128
                    if (type == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   129
                        throw new IOException("Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + nextCP + ", " + nextCP + size + "]");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   130
                    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   131
                    pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   132
                    constantPools.put(type.getId(), pool);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   133
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   134
                Parser parser = typeParser.get(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   135
                if (parser == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   136
                    throw new IOException("Could not find constant pool type with id = " + id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   137
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   138
                try {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   139
                    int count = input.readInt();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   140
                    Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, () -> "Constant: " + getName(id) + "[" + count + "]");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   141
                    for (int j = 0; j < count; j++) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   142
                        long key = input.readLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   143
                        Object value = parser.parse(input);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   144
                        pool.put(key, value);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   145
                    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   146
                } catch (Exception e) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   147
                    throw new IOException("Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + nextCP + ", " + nextCP + size + "]", e);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   148
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   149
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   150
            if (input.position() != nextCP + size) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   151
                throw new IOException("Size of check point event doesn't match content");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   152
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   153
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   154
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   155
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   156
    private String getName(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   157
        Type type = typeMap.get(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   158
        return type == null ? ("unknown(" + id +")") : type.getName();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   159
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   160
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   161
    public Collection<Type> getTypes() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   162
        return metadata.getTypes();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   163
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   164
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   165
    public List<EventType> getEventTypes() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   166
        return metadata.getEventTypes();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   167
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   168
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   169
    public boolean isLastChunk() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   170
        return chunkHeader.isLastChunk();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   171
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   172
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   173
    public ChunkParser nextChunkParser() throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   174
        return new ChunkParser(chunkHeader.nextHeader());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   175
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   176
}