# HG changeset patch # User egahlin # Date 1564769123 -7200 # Node ID f5f590eaecf596635b352273209039f9db89bbfb # Parent b38c7a822244cc436ca9ace19537a059d06fe521 Fix EventStream:setStartTime diff -r b38c7a822244 -r f5f590eaecf5 src/jdk.jfr/share/classes/jdk/jfr/consumer/AbstractEventStream.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/AbstractEventStream.java Fri Aug 02 20:04:02 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/AbstractEventStream.java Fri Aug 02 20:05:23 2019 +0200 @@ -332,7 +332,6 @@ private void execute() { JVM.getJVM().exclude(Thread.currentThread()); try { - updateStartNanos(); process(); } catch (IOException e) { if (!isClosed()) { @@ -345,19 +344,6 @@ } } - // User setting overrides default - private void updateStartNanos() { - if (configuration.getStartTime() != null) { - StreamConfiguration c = new StreamConfiguration(configuration); - try { - c.setStartNanos(c.getStartTime().toEpochMilli() * 1_000_000L); - } catch (ArithmeticException ae) { - c.setStartNanos(Long.MAX_VALUE); - } - updateConfiguration(c); - } - } - private void logException(Exception e) { // FIXME: e.printStackTrace(); for debugging purposes, // remove before before integration @@ -522,6 +508,9 @@ throw new IllegalStateException("Event stream can only be started once"); } StreamConfiguration c = new StreamConfiguration(configuration); + if (c.getStartTime() != null) { + startNanos= c.getStartTime().toEpochMilli() * 1_000_000L; + } c.setStartNanos(startNanos); c.setStarted(true); updateConfiguration(c); diff -r b38c7a822244 -r f5f590eaecf5 src/jdk.jfr/share/classes/jdk/jfr/consumer/EventDirectoryStream.java --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventDirectoryStream.java Fri Aug 02 20:04:02 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventDirectoryStream.java Fri Aug 02 20:05:23 2019 +0200 @@ -35,6 +35,7 @@ import java.util.Objects; import java.util.function.Consumer; +import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.consumer.RepositoryFiles; @@ -58,7 +59,7 @@ public DirectoryStream(AccessControlContext acc, Path p) throws IOException { super(acc); - repositoryFiles = new RepositoryFiles(p); + repositoryFiles = new RepositoryFiles(new SafePath(p)); } @Override @@ -98,7 +99,9 @@ } runFlushActions(); } - + if (isClosed()) { + return; + } path = repositoryFiles.nextPath(chunkStartNanos); if (path == null) { return; // stream closed diff -r b38c7a822244 -r f5f590eaecf5 src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java Fri Aug 02 20:04:02 2019 +0200 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java Fri Aug 02 20:05:23 2019 +0200 @@ -44,15 +44,16 @@ import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.Repository; +import jdk.jfr.internal.SecuritySupport.SafePath; public final class RepositoryFiles { - private final Path repostory; + private final Path repository; private final NavigableMap pathSet = new TreeMap<>(); private final Map pathLookup = new HashMap<>(); private volatile boolean closed; - public RepositoryFiles(Path repostory) { - this.repostory = repostory; + public RepositoryFiles(SafePath repository) { + this.repository = repository.toPath(); } public long getTimestamp(Path p) { @@ -71,14 +72,17 @@ return e.getValue(); } } - SortedMap after = pathSet.tailMap(startTimeNanos); - if (!after.isEmpty()) { - Path path = after.get(after.firstKey()); - Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.TRACE, "Return path " + path + " for start time nanos " + startTimeNanos); - return path; + Long f = pathSet.floorKey(startTimeNanos); + if (f != null) { + SortedMap after = pathSet.tailMap(f); + if (!after.isEmpty()) { + Path path = after.get(after.firstKey()); + Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.TRACE, "Return path " + path + " for start time nanos " + startTimeNanos); + return path; + } } try { - if (updatePaths(repostory)) { + if (updatePaths(repository)) { continue; } } catch (IOException e) { diff -r b38c7a822244 -r f5f590eaecf5 test/jdk/jdk/jfr/api/consumer/recordingstream/TestSetStartTime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestSetStartTime.java Fri Aug 02 20:05:23 2019 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.api.consumer.recordingstream; + +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.atomic.AtomicBoolean; + +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.StackTrace; +import jdk.jfr.consumer.EventStream; + +/** + * @test + * @summary Tests RecordingStrream::setStartTime + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.api.consumer.recordingstream.TestSetStartTime + */ +public final class TestSetStartTime { + + @Name("Mark") + @StackTrace(false) + public final static class Mark extends Event { + public boolean before; + } + + public static void main(String... args) throws Exception { + try (Recording r = new Recording()) { + r.setFlushInterval(Duration.ofSeconds(1)); + r.start(); + Mark event1 = new Mark(); + event1.before = true; + event1.commit(); + + Instant now = Instant.now(); + System.out.println("Start time was " + now); + Mark event2 = new Mark(); + event2.before = false; + event2.commit(); + AtomicBoolean error = new AtomicBoolean(); + try (EventStream d = EventStream.openRepository()) { + d.setStartTime(now); + d.onEvent(e -> { + System.out.println(e); + boolean early = e.getBoolean("before"); + if (early) { + error.set(true); + } else { + // OK, as expected + d.close(); + } + }); + d.start(); + if (error.get()) { + throw new Exception("Found unexpected event!"); + } + } + } + } +} \ No newline at end of file