1 /* 2 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.management.jfr; 26 27 import java.io.IOException; 28 import java.nio.channels.FileChannel; 29 import java.nio.file.Path; 30 import java.nio.file.StandardOpenOption; 31 import java.util.ArrayDeque; 32 import java.util.Queue; 33 34 import jdk.management.jfr.DiskRepository.DiskChunk; 35 36 final class FileDump { 37 private final Queue<DiskChunk> chunks = new ArrayDeque<>(); 38 private final long stopTimeMillis; 39 private boolean complete; 40 FileDump(long stopTimeMillis)41 FileDump(long stopTimeMillis) { 42 this.stopTimeMillis = stopTimeMillis; 43 } 44 add(DiskChunk dc)45 public synchronized void add(DiskChunk dc) { 46 if (isComplete()) { 47 return; 48 } 49 dc.acquire(); 50 chunks.add(dc); 51 long endMillis = dc.endTimeNanos / 1_000_000; 52 if (endMillis >= stopTimeMillis) { 53 setComplete(); 54 } 55 } 56 isComplete()57 public synchronized boolean isComplete() { 58 return complete; 59 } 60 setComplete()61 public synchronized void setComplete() { 62 complete = true; 63 this.notifyAll(); 64 } 65 close()66 public synchronized void close() { 67 for (DiskChunk dc : chunks) { 68 dc.release(); 69 } 70 chunks.clear(); 71 complete = true; 72 } 73 oldestChunk()74 private DiskChunk oldestChunk() throws InterruptedException { 75 while (true) { 76 synchronized (this) { 77 if (!chunks.isEmpty()) { 78 return chunks.poll(); 79 } 80 if (complete) { 81 return null; 82 } 83 this.wait(); 84 } 85 } 86 } 87 write(Path path)88 public void write(Path path) throws IOException, InterruptedException { 89 try (FileChannel out = FileChannel.open(path, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) { 90 DiskChunk chunk = null; 91 while ((chunk = oldestChunk()) != null) { 92 try (FileChannel in = FileChannel.open(chunk.path(), StandardOpenOption.READ)) { 93 in.transferTo(0, in.size(), out); 94 } 95 } 96 } finally { 97 close(); 98 } 99 } 100 }