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 read 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 PreadDirect 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 read method. 51 */ 52 53 public class PreadDirect { 54 55 private static PrintStream err = System.err; 56 57 private static Random generator = RandomFactory.getRandom(); 58 59 private static int charsPerGroup = -1; 60 61 private static int alignment = -1; 62 63 public static void main(String[] args) throws Exception { 64 if (initTests()) { 65 genericTest(); 66 testNotAlignedChannelPosition(); 67 testNegativeChannelPosition(); 68 } 69 } 70 71 private static boolean initTests() throws Exception { 72 Path p = DirectIOTest.createTempFile(); 73 if (!DirectIOTest.isDirectIOSupportedByFS(p)) { 74 Files.delete(p); 75 return false; 76 } 77 try { 78 FileStore fs = Files.getFileStore(p); 79 alignment = (int)fs.getBlockSize(); 80 charsPerGroup = alignment; 81 } finally { 82 Files.delete(p); 83 } 84 return true; 85 } 86 87 private static void testNegativeChannelPosition() throws Exception { 88 Path p = DirectIOTest.createTempFile(); 89 90 try (OutputStream fos = Files.newOutputStream(p)) { 91 fos.write(new byte[charsPerGroup]); 92 } 93 94 try (FileChannel fc = FileChannel.open(p, 95 StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 96 try { 97 fc.read(ByteBuffer.allocate(charsPerGroup), -1L); 98 throw new RuntimeException("Expected exception not thrown"); 99 } catch(IllegalArgumentException e) { 100 // Correct result 101 } 102 } 103 } 104 105 private static void testNotAlignedChannelPosition() throws Exception { 106 Path p = DirectIOTest.createTempFile(); 107 108 try (OutputStream fos = Files.newOutputStream(p)) { 109 fos.write(new byte[charsPerGroup]); 110 } 111 112 try (FileChannel fc = FileChannel.open(p, 113 StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 114 long pos = charsPerGroup - 1; 115 try { 116 fc.read(ByteBuffer.allocate(charsPerGroup), pos); 117 throw new RuntimeException("Expected exception not thrown"); 118 } catch(IOException e) { 119 if (!e.getMessage().contains("Channel position (" + pos 120 + ") is not a multiple of the block size (" + alignment + ")")) 121 throw new RuntimeException("Read test failed"); 122 } 123 } 124 } 125 126 private static void genericTest() throws Exception { 127 StringBuffer sb = new StringBuffer(); 128 sb.setLength(2); 129 130 Path p = DirectIOTest.createTempFile(); 131 132 initTestFile(p); 133 134 try (FileChannel fc = FileChannel.open(p, 135 StandardOpenOption.DELETE_ON_CLOSE, ExtendedOpenOption.DIRECT)) { 136 ByteBuffer block = 137 ByteBuffer.allocateDirect(charsPerGroup + alignment - 1) 138 .alignedSlice(alignment); 139 for (int x = 0; x < 100; x++) { 140 block.clear(); 141 long offset = generator.nextInt(100) * charsPerGroup; 142 long expectedResult = offset / charsPerGroup; 143 offset = expectedResult * charsPerGroup; 144 145 long originalPosition = fc.position(); 146 147 int read = fc.read(block, offset); 148 if (read != charsPerGroup) 149 throw new Exception("Read failed"); 150 151 long newPosition = fc.position(); 152 153 for (int i = 0; i < 2; i++) { 154 byte aByte = block.get(i); 155 sb.setCharAt(i, (char)aByte); 156 } 157 int result = Integer.parseInt(sb.toString()); 158 if (result != expectedResult) { 159 err.println("I expected "+ expectedResult); 160 err.println("I got "+ result); 161 throw new Exception("Read test failed"); 162 } 163 164 // Ensure that file pointer position has not changed 165 if (originalPosition != newPosition) 166 throw new Exception("File position modified"); 167 } 168 } 169 } 170 171 private static void initTestFile(Path p) throws Exception { 172 try (OutputStream fos = Files.newOutputStream(p)) { 173 try (BufferedWriter awriter 174 = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"))) { 175 176 for (int i = 0; i < 100; i++) { 177 String number = new Integer(i).toString(); 178 for (int h = 0; h < 2 - number.length(); h++) 179 awriter.write("0"); 180 awriter.write(""+i); 181 for (int j = 0; j < (charsPerGroup - 2); j++) 182 awriter.write("0"); 183 } 184 awriter.flush(); 185 } 186 } 187 } 188 }