src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
changeset 50745 a390cbb82d47
parent 50197 f4735ff8d17d
child 52334 a181612f0715
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java	Sun Jun 24 16:25:47 2018 +0100
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java	Mon Jun 25 02:07:42 2018 +0200
@@ -38,6 +38,7 @@
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -46,7 +47,6 @@
 import java.util.TimerTask;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import jdk.jfr.Enabled;
 import jdk.jfr.EventType;
 import jdk.jfr.FlightRecorder;
 import jdk.jfr.FlightRecorderListener;
@@ -56,8 +56,6 @@
 import jdk.jfr.events.ActiveSettingEvent;
 import jdk.jfr.internal.SecuritySupport.SecureRecorderListener;
 import jdk.jfr.internal.instrument.JDKEvents;
-import jdk.jfr.internal.settings.CutoffSetting;
-import jdk.jfr.internal.test.WhiteBox;
 
 public final class PlatformRecorder {
 
@@ -111,7 +109,16 @@
         return newRecording(settings, ++recordingCounter);
     }
 
-    public synchronized PlatformRecording newRecording(Map<String, String> settings, long id) {
+    // To be used internally when doing dumps.
+    // Caller must have recorder lock and close recording before releasing lock
+    public PlatformRecording newTemporaryRecording() {
+        if(!Thread.holdsLock(this)) {
+            throw new InternalError("Caller must have recorder lock");
+        }
+        return newRecording(new HashMap<>(), 0);
+    }
+
+    private synchronized PlatformRecording newRecording(Map<String, String> settings, long id) {
         PlatformRecording recording = new PlatformRecording(this, id);
         if (!settings.isEmpty()) {
             recording.setSettings(settings);
@@ -249,7 +256,7 @@
         RequestEngine.doChunkBegin();
     }
 
-    synchronized void stop(PlatformRecording recording, WriteableUserPath alternativePath) {
+    synchronized void stop(PlatformRecording recording) {
         RecordingState state = recording.getState();
 
         if (Utils.isAfter(state, RecordingState.RUNNING)) {
@@ -270,7 +277,7 @@
                 }
             }
         }
-        emitOldObjectSamples(recording);
+        OldObjectSample.emit(recording);
 
         if (endPhysical) {
             RequestEngine.doChunkEnd();
@@ -282,7 +289,7 @@
                 }
             } else {
                 // last memory
-                dumpMemoryToDestination(recording, alternativePath);
+                dumpMemoryToDestination(recording);
             }
             jvm.endRecording_();
             disableEvents();
@@ -306,26 +313,13 @@
         recording.setState(RecordingState.STOPPED);
     }
 
-    // Only dump event if the recording that is being stopped
-    // has OldObjectSample enabled + cutoff from recording, not global value
-    private void emitOldObjectSamples(PlatformRecording recording) {
-        Map<String, String> settings = recording.getSettings();
-        String s = settings.get(Type.EVENT_NAME_PREFIX + "OldObjectSample#" + Enabled.NAME);
-        if ("true".equals(s)) {
-            long nanos = CutoffSetting.parseValueSafe(settings.get(Type.EVENT_NAME_PREFIX + "OldObjectSample#" + Cutoff.NAME));
-            long ticks = Utils.nanosToTicks(nanos);
-            JVM.getJVM().emitOldObjectSamples(ticks, WhiteBox.getWriteAllObjectSamples());
-        }
-    }
-
-    private void dumpMemoryToDestination(PlatformRecording recording, WriteableUserPath alternativePath) {
-        WriteableUserPath dest = alternativePath != null ? alternativePath : recording.getDestination();
+    private void dumpMemoryToDestination(PlatformRecording recording)  {
+        WriteableUserPath dest = recording.getDestination();
         if (dest != null) {
             MetadataRepository.getInstance().setOutput(dest.getText());
             recording.clearDestination();
         }
     }
-
     private void disableEvents() {
         MetadataRepository.getInstance().disableEvents();
     }
@@ -504,47 +498,47 @@
         return newRec;
     }
 
-    public synchronized Recording newSnapshot() {
+    public synchronized void fillWithRecordedData(PlatformRecording target, Boolean pathToGcRoots) {
         boolean running = false;
         boolean toDisk = false;
+
         for (PlatformRecording r : recordings) {
             if (r.getState() == RecordingState.RUNNING) {
                 running = true;
+                if (r.isToDisk()) {
+                    toDisk = true;
+                }
             }
-            if (r.isToDisk()) {
-                toDisk = true;
-            }
-
         }
         // If needed, flush data from memory
         if (running) {
             if (toDisk) {
+                OldObjectSample.emit(recordings, pathToGcRoots);
                 rotateDisk();
             } else {
-                try (Recording snapshot = new Recording()) {
-                    PlatformRecording internal = PrivateAccess.getInstance().getPlatformRecording(snapshot);
-                    internal.setShouldWriteActiveRecordingEvent(false);
+                try (PlatformRecording snapshot = newTemporaryRecording()) {
+                    snapshot.setToDisk(true);
+                    snapshot.setShouldWriteActiveRecordingEvent(false);
                     snapshot.start();
-                    snapshot.stop();
-                    return makeRecordingWithDiskChunks();
+                    OldObjectSample.emit(recordings, pathToGcRoots);
+                    snapshot.stop("Snapshot dump");
+                    fillWithDiskChunks(target);
                 }
+                return;
             }
         }
-        return makeRecordingWithDiskChunks();
+        fillWithDiskChunks(target);
     }
 
-    private Recording makeRecordingWithDiskChunks() {
-        Recording snapshot = new Recording();
-        snapshot.setName("Snapshot");
-        PlatformRecording internal = PrivateAccess.getInstance().getPlatformRecording(snapshot);
+    private void fillWithDiskChunks(PlatformRecording target) {
         for (RepositoryChunk c : makeChunkList(null, null)) {
-            internal.add(c);
+            target.add(c);
         }
-        internal.setState(RecordingState.STOPPED);
+        target.setState(RecordingState.STOPPED);
         Instant startTime = null;
         Instant endTime = null;
 
-        for (RepositoryChunk c : makeChunkList(null, null)) {
+        for (RepositoryChunk c : target.getChunks()) {
             if (startTime == null || c.getStartTime().isBefore(startTime)) {
                 startTime = c.getStartTime();
             }
@@ -559,9 +553,8 @@
         if (endTime == null) {
             endTime = now;
         }
-        internal.setStartTime(startTime);
-        internal.setStopTime(endTime);
-        internal.setInternalDuration(Duration.between(startTime, endTime));
-        return snapshot;
+        target.setStartTime(startTime);
+        target.setStopTime(endTime);
+        target.setInternalDuration(Duration.between(startTime, endTime));
     }
 }