src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java
branchJEP-349-branch
changeset 57360 5d043a159d5c
parent 50113 caf115bb98ad
child 57373 400db63e4937
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java	Fri May 17 15:53:21 2019 +0200
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java	Fri May 17 16:02:27 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,13 +28,13 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 
 import jdk.jfr.EventType;
 import jdk.jfr.ValueDescriptor;
 import jdk.jfr.internal.MetadataDescriptor;
 import jdk.jfr.internal.PrivateAccess;
 import jdk.jfr.internal.Type;
+import jdk.jfr.internal.consumer.Parser;
 import jdk.jfr.internal.consumer.RecordingInput;
 
 /**
@@ -44,19 +44,21 @@
     private final LongMap<Parser> parsers = new LongMap<>();
     private final TimeConverter timeConverter;
     private final LongMap<Type> types = new LongMap<>();
-    private final LongMap<ConstantMap> constantPools;
+    private final LongMap<ConstantLookup> constantLookups;
 
-    public ParserFactory(MetadataDescriptor metadata, TimeConverter timeConverter) throws IOException {
-        this.constantPools = new LongMap<>();
+    public ParserFactory(MetadataDescriptor metadata, LongMap<ConstantLookup> constantLookups, TimeConverter timeConverter) throws IOException {
+        this.constantLookups = constantLookups;
         this.timeConverter = timeConverter;
         for (Type t : metadata.getTypes()) {
             types.put(t.getId(), t);
         }
-        for (Type t : types) {
+        List<Type> typeList = new ArrayList<>();
+        types.forEach(typeList::add);
+        for (Type t : typeList) {
             if (!t.getFields().isEmpty()) { // Avoid primitives
-                CompositeParser cp = createCompositeParser(t);
+                CompositeParser cp = createCompositeParser(t, false);
                 if (t.isSimpleType()) { // Reduce to nested parser
-                   parsers.put(t.getId(), cp.parsers[0]);
+                    parsers.put(t.getId(), cp.parsers[0]);
                 }
 
             }
@@ -71,10 +73,6 @@
         return parsers;
     }
 
-    public LongMap<ConstantMap> getConstantPools() {
-        return constantPools;
-    }
-
     public LongMap<Type> getTypeMap() {
         return types;
     }
@@ -82,17 +80,17 @@
     private EventParser createEventParser(EventType eventType) throws IOException {
         List<Parser> parsers = new ArrayList<Parser>();
         for (ValueDescriptor f : eventType.getFields()) {
-            parsers.add(createParser(f));
+            parsers.add(createParser(f, true));
         }
         return new EventParser(timeConverter, eventType, parsers.toArray(new Parser[0]));
     }
 
-    private Parser createParser(ValueDescriptor v) throws IOException {
+    private Parser createParser(ValueDescriptor v, boolean event) throws IOException {
         boolean constantPool = PrivateAccess.getInstance().isConstantPool(v);
         if (v.isArray()) {
             Type valueType = PrivateAccess.getInstance().getType(v);
             ValueDescriptor element = PrivateAccess.getInstance().newValueDescriptor(v.getName(), valueType, v.getAnnotationElements(), 0, constantPool, null);
-            return new ArrayParser(createParser(element));
+            return new ArrayParser(createParser(element, event));
         }
         long id = v.getTypeId();
         Type type = types.get(id);
@@ -100,25 +98,29 @@
             throw new IOException("Type '" + v.getTypeName() + "' is not defined");
         }
         if (constantPool) {
-            ConstantMap pool = constantPools.get(id);
-            if (pool == null) {
-                pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName());
-                constantPools.put(id, pool);
+            ConstantLookup lookup = constantLookups.get(id);
+            if (lookup == null) {
+                ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName());
+                lookup = new ConstantLookup(pool, type);
+                constantLookups.put(id, lookup);
             }
-            return new ConstantMapValueParser(pool);
+            if (event) {
+                return new EventValueConstantParser(lookup);
+            }
+            return new ConstantValueParser(lookup);
         }
         Parser parser = parsers.get(id);
         if (parser == null) {
             if (!v.getFields().isEmpty()) {
-                return createCompositeParser(type);
+                return createCompositeParser(type, event);
             } else {
-                return registerParserType(type, createPrimitiveParser(type));
+                return registerParserType(type, createPrimitiveParser(type, constantPool));
             }
         }
         return parser;
     }
 
-    private Parser createPrimitiveParser(Type type) throws IOException {
+    private Parser createPrimitiveParser(Type type, boolean event) throws IOException {
         switch (type.getName()) {
         case "int":
             return new IntegerParser();
@@ -138,8 +140,9 @@
             return new ByteParser();
         case "java.lang.String":
             ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName());
-            constantPools.put(type.getId(), pool);
-            return new StringParser(pool);
+            ConstantLookup lookup = new ConstantLookup(pool, type);
+            constantLookups.put(type.getId(), lookup);
+            return new StringParser(lookup, event);
         default:
             throw new IOException("Unknown primitive type " + type.getName());
         }
@@ -155,7 +158,7 @@
         return parser;
     }
 
-    private CompositeParser createCompositeParser(Type type) throws IOException {
+    private CompositeParser createCompositeParser(Type type, boolean event) throws IOException {
         List<ValueDescriptor> vds = type.getFields();
         Parser[] parsers = new Parser[vds.size()];
         CompositeParser composite = new CompositeParser(parsers);
@@ -164,7 +167,7 @@
 
         int index = 0;
         for (ValueDescriptor vd : vds) {
-            parsers[index++] = createParser(vd);
+            parsers[index++] = createParser(vd, event);
         }
         return composite;
     }
@@ -174,6 +177,11 @@
         public Object parse(RecordingInput input) throws IOException {
             return input.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.skipBytes(1);
+        }
     }
 
     private static final class ByteParser extends Parser {
@@ -181,19 +189,50 @@
         public Object parse(RecordingInput input) throws IOException {
             return Byte.valueOf(input.readByte());
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.skipBytes(1);
+        }
     }
 
     private static final class LongParser extends Parser {
+        private Object lastLongObject = Long.valueOf(0);
+        private long last = 0;
+
         @Override
         public Object parse(RecordingInput input) throws IOException {
-            return Long.valueOf(input.readLong());
+            long l = input.readLong();
+            if (l != last) {
+                last = l;
+                lastLongObject = Long.valueOf(l);
+            }
+            return lastLongObject;
+        }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readLong();
         }
     }
 
     private static final class IntegerParser extends Parser {
+        private Integer lastIntegergObject = Integer.valueOf(0);
+        private int last = 0;
+
         @Override
         public Object parse(RecordingInput input) throws IOException {
-            return Integer.valueOf(input.readInt());
+            int i = input.readInt();
+            if (i != last) {
+                last = i;
+                lastIntegergObject = Integer.valueOf(i);
+            }
+            return lastIntegergObject;
+        }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readInt();
         }
     }
 
@@ -202,6 +241,11 @@
         public Object parse(RecordingInput input) throws IOException {
             return Short.valueOf(input.readShort());
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readShort();
+        }
     }
 
     private static final class CharacterParser extends Parser {
@@ -209,6 +253,11 @@
         public Object parse(RecordingInput input) throws IOException {
             return Character.valueOf(input.readChar());
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readChar();
+        }
     }
 
     private static final class FloatParser extends Parser {
@@ -216,6 +265,11 @@
         public Object parse(RecordingInput input) throws IOException {
             return Float.valueOf(input.readFloat());
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.skipBytes(Float.SIZE);
+        }
     }
 
     private static final class DoubleParser extends Parser {
@@ -223,33 +277,10 @@
         public Object parse(RecordingInput input) throws IOException {
             return Double.valueOf(input.readDouble());
         }
-    }
-
-    private static final class StringParser extends Parser {
-        private final ConstantMap stringConstantMap;
-        private String last;
-
-        StringParser(ConstantMap stringConstantMap) {
-            this.stringConstantMap = stringConstantMap;
-        }
 
         @Override
-        public Object parse(RecordingInput input) throws IOException {
-            String s = parseEncodedString(input);
-            if (!Objects.equals(s, last)) {
-                last = s;
-            }
-            return last;
-        }
-
-        private String parseEncodedString(RecordingInput input) throws IOException {
-            byte encoding = input.readByte();
-            if (encoding == RecordingInput.STRING_ENCODING_CONSTANT_POOL) {
-                long id = input.readLong();
-                return (String) stringConstantMap.get(id);
-            } else {
-                return input.readEncodedString(encoding);
-            }
+        public void skip(RecordingInput input) throws IOException {
+            input.skipBytes(Double.SIZE);
         }
     }
 
@@ -269,9 +300,17 @@
             }
             return array;
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            final int size = input.readInt();
+            for (int i = 0; i < size; i++) {
+                elementParser.skip(input);
+            }
+        }
     }
 
-    private final static class CompositeParser extends Parser {
+    final static class CompositeParser extends Parser {
         private final Parser[] parsers;
 
         public CompositeParser(Parser[] valueParsers) {
@@ -286,18 +325,54 @@
             }
             return values;
         }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            for (int i = 0; i < parsers.length; i++) {
+                parsers[i].skip(input);
+            }
+        }
     }
 
-    private static final class ConstantMapValueParser extends Parser {
-        private final ConstantMap pool;
-
-        ConstantMapValueParser(ConstantMap pool) {
-            this.pool = pool;
+    public static final class EventValueConstantParser extends Parser {
+        private final ConstantLookup lookup;
+        private Object lastValue = 0;
+        private long lastKey = -1;
+        EventValueConstantParser(ConstantLookup lookup) {
+            this.lookup = lookup;
         }
 
         @Override
         public Object parse(RecordingInput input) throws IOException {
-            return pool.get(input.readLong());
+            long key = input.readLong();
+            if (key == lastKey) {
+                return lastValue;
+            }
+            lastKey = key;
+            lastValue = lookup.getCurrentResolved(key);
+            return lastValue;
+        }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readLong();
+        }
+    }
+
+    public static final class ConstantValueParser extends Parser {
+        private final ConstantLookup lookup;
+        ConstantValueParser(ConstantLookup lookup) {
+            this.lookup = lookup;
+        }
+
+        @Override
+        public Object parse(RecordingInput input) throws IOException {
+            return lookup.getCurrent(input.readLong());
+        }
+
+        @Override
+        public void skip(RecordingInput input) throws IOException {
+            input.readLong();
         }
     }
 }