1 /* 2 * Copyright (c) 2016, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @ignore This test has huge disk space requirements 26 * @bug 8168628 27 * @summary Test extending files to very large sizes without hitting a SIGBUS 28 * @requires (os.family == "linux") 29 * @run main/othervm/timeout=600 -Xms4g -Xmx4g FileExtensionAndMap 30 * @run main/othervm/timeout=600 -Xms4g -Xmx4g FileExtensionAndMap true 31 */ 32 33 import java.io.File; 34 import java.io.IOException; 35 import java.io.RandomAccessFile; 36 import java.nio.MappedByteBuffer; 37 import java.nio.channels.ClosedChannelException; 38 import java.nio.channels.FileChannel; 39 import java.nio.channels.FileChannel.MapMode; 40 import java.nio.file.Files; 41 import java.nio.file.Path; 42 import java.nio.file.Paths; 43 import java.nio.file.StandardCopyOption; 44 import java.nio.file.StandardOpenOption; 45 import java.util.concurrent.ExecutorService; 46 import java.util.concurrent.Executors; 47 import java.util.concurrent.ForkJoinPool; 48 import java.util.concurrent.Semaphore; 49 import java.util.stream.IntStream; 50 51 public class FileExtensionAndMap { 52 53 private static final ExecutorService CACHED_EXECUTORSERVICE = 54 Executors.newCachedThreadPool(); 55 56 private static final String TMPDIR = System.getProperty("test.dir", "."); 57 58 private static boolean useRaf = false; 59 60 public static void main(String args[]) throws Exception { 61 if (args.length > 2) { 62 throw new IllegalArgumentException 63 ("Arguments: [true|false [targetFolder]]"); 64 } 65 66 String defaultFolder = TMPDIR + File.separator + "target"; 67 if (args.length > 0) { 68 useRaf = Boolean.valueOf(args[0]); 69 if (args.length > 1) { 70 defaultFolder = args[1]; 71 } 72 } 73 final String targetFolder = defaultFolder; 74 Path p = Paths.get(targetFolder); 75 boolean targetExists = Files.exists(p); 76 if (!targetExists) { 77 Files.createDirectory(p); 78 } 79 80 System.out.printf("Using RandomAccessFile: %s; target folder: %s%n", 81 useRaf, targetFolder); 82 83 ForkJoinPool fjPool = new ForkJoinPool(3); 84 fjPool.submit(() -> { 85 IntStream.range(0, 20).parallel().forEach((index) -> { 86 String fileName = "testBigFile_" + index + ".dat"; 87 Path source = null; 88 Path target = null; 89 try { 90 source = Paths.get(TMPDIR, fileName); 91 testCreateBigFile(source); 92 target = Paths.get(targetFolder, fileName); 93 testFileCopy(source, target); 94 } catch (Throwable th) { 95 System.err.println("Error copying file with fileName: " 96 + fileName + " : " + th.getMessage()); 97 th.printStackTrace(System.err); 98 } finally { 99 try { 100 if (source != null) { 101 Files.deleteIfExists(source); 102 } 103 } catch (Throwable ignored) { 104 } 105 try { 106 if (target != null) { 107 Files.deleteIfExists(target); 108 } 109 } catch (Throwable ignored) { 110 } 111 } 112 }); 113 }).join(); 114 115 if (!targetExists) { 116 Files.delete(p); 117 } 118 } 119 120 private static void testFileCopy(Path source, Path target) 121 throws IOException { 122 Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); 123 System.out.println("Finished copying file with fileName: " 124 + source.getFileName()); 125 } 126 127 private static void testCreateBigFile(Path segmentFile) 128 throws IOException { 129 final Semaphore concurrencySemaphore = new Semaphore(5); 130 long fileSize = 3L * 1024L * 1024L * 1024L; 131 int blockSize = 10 * 1024 * 1024; 132 int loopCount = (int) Math.floorDiv(fileSize, blockSize); 133 134 String fileName = segmentFile.getFileName().toString(); 135 if (useRaf) { 136 try (RandomAccessFile raf 137 = new RandomAccessFile(segmentFile.toFile(), "rw")) { 138 raf.setLength(fileSize); 139 try (FileChannel fc = raf.getChannel()) { 140 for (int i = 0; i < loopCount; i++) { 141 final long startPosition = 1L * blockSize * i; 142 concurrencySemaphore.acquireUninterruptibly(); 143 CACHED_EXECUTORSERVICE.submit(() -> { 144 writeTemplateData(fileName, fc, startPosition, 145 blockSize, concurrencySemaphore); 146 }); 147 } 148 } finally { 149 concurrencySemaphore.acquireUninterruptibly(5); 150 } 151 } 152 } else { 153 Path file = Files.createFile(segmentFile); 154 try (FileChannel fc = FileChannel.open(file, 155 StandardOpenOption.READ, StandardOpenOption.WRITE)) { 156 for (int i = 0; i < loopCount; i++) { 157 final long startPosition = 1L * blockSize * i; 158 concurrencySemaphore.acquireUninterruptibly(); 159 CACHED_EXECUTORSERVICE.submit(() -> { 160 writeTemplateData(fileName, fc, startPosition, 161 blockSize, concurrencySemaphore); 162 }); 163 } 164 } 165 } 166 } 167 168 private static void writeTemplateData(String fileName, 169 FileChannel fc, long startPosition, int blockSize, 170 Semaphore concurrencySemaphore) { 171 try { 172 byte[] EMPTY_RECORD = new byte[blockSize / 256]; 173 174 MappedByteBuffer mappedByteBuffer = fc.map(MapMode.READ_WRITE, 175 startPosition, blockSize); 176 IntStream.range(0, 256).forEach((recordIndex) -> { 177 try { 178 mappedByteBuffer.position((int) (recordIndex * 179 EMPTY_RECORD.length)); 180 mappedByteBuffer.put(EMPTY_RECORD, 0, EMPTY_RECORD.length); 181 } catch (Throwable th) { 182 System.err.println 183 ("Error in FileExtensionAndMap.writeTemplateData empty record for fileName: " 184 + fileName + ", startPosition: " + startPosition + ", recordIndex: " 185 + recordIndex + " : " + th.getMessage()); 186 th.printStackTrace(System.err); 187 } 188 }); 189 190 mappedByteBuffer.force(); 191 } catch (Throwable th) { 192 if (!(th instanceof ClosedChannelException)) { 193 System.err.println 194 ("Error in FileExtensionAndMap.writeTemplateData empty record for fileName: " 195 + fileName + ", startPosition: " + startPosition + " : " 196 + th.getMessage()); 197 th.printStackTrace(System.err); 198 } 199 } finally { 200 concurrencySemaphore.release(); 201 } 202 } 203 }