1 /* |
1 /* |
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. |
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. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
82 private volatile Recording recording; |
82 private volatile Recording recording; |
83 private TimerTask stopTask; |
83 private TimerTask stopTask; |
84 private TimerTask startTask; |
84 private TimerTask startTask; |
85 private AccessControlContext noDestinationDumpOnExitAccessControlContext; |
85 private AccessControlContext noDestinationDumpOnExitAccessControlContext; |
86 private boolean shuoldWriteActiveRecordingEvent = true; |
86 private boolean shuoldWriteActiveRecordingEvent = true; |
|
87 private Duration flushInterval = Duration.ofSeconds(1); |
87 |
88 |
88 PlatformRecording(PlatformRecorder recorder, long id) { |
89 PlatformRecording(PlatformRecorder recorder, long id) { |
89 // Typically the access control context is taken |
90 // Typically the access control context is taken |
90 // when you call dump(Path) or setDdestination(Path), |
91 // when you call dump(Path) or setDdestination(Path), |
91 // but if no destination is set and dumponexit=true |
92 // but if no destination is set and dumponexit=true |
96 this.id = id; |
97 this.id = id; |
97 this.recorder = recorder; |
98 this.recorder = recorder; |
98 this.name = String.valueOf(id); |
99 this.name = String.valueOf(id); |
99 } |
100 } |
100 |
101 |
101 public void start() { |
102 public long start() { |
102 RecordingState oldState; |
103 RecordingState oldState; |
103 RecordingState newState; |
104 RecordingState newState; |
|
105 long startNanos = -1; |
104 synchronized (recorder) { |
106 synchronized (recorder) { |
105 oldState = getState(); |
107 oldState = getState(); |
106 if (!Utils.isBefore(state, RecordingState.RUNNING)) { |
108 if (!Utils.isBefore(state, RecordingState.RUNNING)) { |
107 throw new IllegalStateException("Recording can only be started once."); |
109 throw new IllegalStateException("Recording can only be started once."); |
108 } |
110 } |
109 if (startTask != null) { |
111 if (startTask != null) { |
110 startTask.cancel(); |
112 startTask.cancel(); |
111 startTask = null; |
113 startTask = null; |
112 startTime = null; |
114 startTime = null; |
113 } |
115 } |
114 recorder.start(this); |
116 startNanos = recorder.start(this); |
115 Logger.log(LogTag.JFR, LogLevel.INFO, () -> { |
117 Logger.log(LogTag.JFR, LogLevel.INFO, () -> { |
116 // Only print non-default values so it easy to see |
118 // Only print non-default values so it easy to see |
117 // which options were added |
119 // which options were added |
118 StringJoiner options = new StringJoiner(", "); |
120 StringJoiner options = new StringJoiner(", "); |
119 if (!toDisk) { |
121 if (!toDisk) { |
141 return "Started recording \"" + getName() + "\" (" + getId() + ") " + optionText; |
143 return "Started recording \"" + getName() + "\" (" + getId() + ") " + optionText; |
142 }); |
144 }); |
143 newState = getState(); |
145 newState = getState(); |
144 } |
146 } |
145 notifyIfStateChanged(oldState, newState); |
147 notifyIfStateChanged(oldState, newState); |
|
148 |
|
149 return startNanos; |
146 } |
150 } |
147 |
151 |
148 public boolean stop(String reason) { |
152 public boolean stop(String reason) { |
149 RecordingState oldState; |
153 RecordingState oldState; |
150 RecordingState newState; |
154 RecordingState newState; |
778 } |
782 } |
779 |
783 |
780 public SafePath getDumpOnExitDirectory() { |
784 public SafePath getDumpOnExitDirectory() { |
781 return this.dumpOnExitDirectory; |
785 return this.dumpOnExitDirectory; |
782 } |
786 } |
|
787 |
|
788 public void setFlushInterval(Duration interval) { |
|
789 synchronized (recorder) { |
|
790 if (getState() == RecordingState.CLOSED) { |
|
791 throw new IllegalStateException("Can't set stream interval when recording is closed"); |
|
792 } |
|
793 this.flushInterval = interval; |
|
794 } |
|
795 } |
|
796 |
|
797 public Duration getFlushInterval() { |
|
798 synchronized (recorder) { |
|
799 return flushInterval; |
|
800 } |
|
801 } |
|
802 |
|
803 public long getStreamIntervalMillis() { |
|
804 synchronized (recorder) { |
|
805 if (flushInterval != null) { |
|
806 return flushInterval.toMillis(); |
|
807 } |
|
808 return Long.MAX_VALUE; |
|
809 } |
|
810 } |
783 } |
811 } |