1 /* 2 * Copyright (c) 2017, 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 * @bug 8164900 26 * @summary Test positional write method of FileChannel with DirectIO 27 * (use -Dseed=X to set PRNG seed) 28 * @library .. /test/lib 29 * @build jdk.test.lib.RandomFactory 30 * DirectIOTest 31 * @run main/othervm PwriteDirect 32 * @key randomness 33 */ 34 35 import java.io.*; 36 import java.nio.ByteBuffer; 37 import java.nio.CharBuffer; 38 import java.nio.channels.*; 39 import java.nio.file.Files; 40 import java.nio.file.FileStore; 41 import java.nio.file.Path; 42 import java.nio.file.Paths; 43 import java.nio.file.StandardOpenOption; 44 import java.util.Random; 45 import com.sun.nio.file.ExtendedOpenOption; 46 47 import jdk.test.lib.RandomFactory; 48 49 /** 50 * Testing FileChannel's positional write method. 51 */ 52 public class PwriteDirect { 53 54 private static Random generator = RandomFactory.getRandom(); 55 56 private static int charsPerGroup = -1; 57 58 private static int alignment = -1; 59 initTests()60 private static boolean initTests() throws Exception { 61 Path p = DirectIOTest.createTempFile(); 62 if (!DirectIOTest.isDirectIOSupportedByFS(p)) { 63 Files.delete(p); 64 return false; 65 } 66 try { 67 FileStore fs = Files.getFileStore(p); 68 alignment = (int)fs.getBlockSize(); 69 charsPerGroup = alignment; 70 } finally { 71 Files.delete(p); 72 } 73 return true; 74 } 75 main(String[] args)76 public static void main(String[] args) throws Exception { 77 if (initTests()) { 78 genericTest(); 79 TestWithNotAlignedChannelPosition(); 80 testUnwritableChannel(); 81 } 82 } 83 testUnwritableChannel()84 private static void testUnwritableChannel() throws Exception { 85 Path p = DirectIOTest.createTempFile(); 86 87 try (FileChannel fc = FileChannel.open(p, 88 StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 89 try { 90 fc.write(ByteBuffer.allocate(charsPerGroup), 0); 91 throw new RuntimeException("Expected exception not thrown"); 92 } catch(NonWritableChannelException e) { 93 // Correct result 94 } 95 } 96 } 97 TestWithNotAlignedChannelPosition()98 private static void TestWithNotAlignedChannelPosition() throws Exception { 99 Path p = DirectIOTest.createTempFile(); 100 101 try (FileChannel fc = FileChannel.open(p, 102 StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 103 int bufferSize = charsPerGroup; 104 long position = charsPerGroup - 1; 105 try { 106 fc.write(ByteBuffer.allocate(bufferSize), position); 107 throw new RuntimeException("Expected exception not thrown"); 108 } catch(IOException e) { 109 if (!e.getMessage().contains("Channel position (" + position + ")" 110 + " is not a multiple of the block size (" + alignment + ")")) 111 throw new RuntimeException("Write test failed"); 112 } 113 } 114 } 115 genericTest()116 private static void genericTest() throws Exception { 117 Path p = DirectIOTest.createTempFile(); 118 119 initTestFile(p); 120 121 try (FileChannel fc = FileChannel.open(p, 122 StandardOpenOption.READ, StandardOpenOption.WRITE, 123 StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 124 ByteBuffer block = 125 ByteBuffer.allocateDirect(charsPerGroup + alignment - 1) 126 .alignedSlice(alignment); 127 for (int x = 0; x < 100; x++) { 128 block.clear(); 129 long offset = generator.nextInt(100) * charsPerGroup; 130 131 // Write known sequence out 132 for (int i = 0; i < charsPerGroup; i++) { 133 block.put(i, (byte)'a'); 134 } 135 long originalPosition = fc.position(); 136 137 int written = fc.write(block, offset); 138 if (written < 0) 139 throw new Exception("Write failed"); 140 141 long newPosition = fc.position(); 142 143 // Ensure that file pointer position has not changed 144 if (originalPosition != newPosition) 145 throw new Exception("File position modified"); 146 147 // Attempt to read sequence back in 148 originalPosition = fc.position(); 149 150 block.rewind(); 151 int read = fc.read(block, offset); 152 if (read != charsPerGroup) 153 throw new Exception("Read failed"); 154 155 newPosition = fc.position(); 156 157 // Ensure that file pointer position has not changed 158 if (originalPosition != newPosition) 159 throw new Exception("File position modified"); 160 161 for (int j = 0; j < charsPerGroup; j++) { 162 if (block.get(j) != (byte)'a') 163 throw new Exception("Write test failed"); 164 } 165 } 166 } 167 } 168 initTestFile(Path p)169 private static void initTestFile(Path p) throws Exception { 170 try (OutputStream fos = Files.newOutputStream(p)) { 171 try (BufferedWriter awriter 172 = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"))) { 173 for (int i = 0; i < 100; i++) { 174 String number = new Integer(i).toString(); 175 for (int h = 0; h < 4 - number.length(); h++) 176 awriter.write("0"); 177 awriter.write("" + i); 178 for (int j = 0; j < 4092; j++) 179 awriter.write("0"); 180 } 181 awriter.flush(); 182 } 183 } 184 } 185 } 186