Lock.java revision 15476:2c68a91dcecf
1/* 2 * Copyright (c) 2001, 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 * @bug 4429043 4493595 6332756 6709457 7146506 26 * @summary Test FileChannel file locking 27 */ 28 29import java.io.*; 30import java.nio.channels.*; 31import static java.nio.file.StandardOpenOption.*; 32 33/** 34 * Testing FileChannel's lock method. 35 */ 36public class Lock { 37 38 public static void main(String[] args) throws Exception { 39 if (args.length == 2) { 40 attemptLock(args[1], args[0].equals("2")); 41 return; 42 } else if (args.length != 0) { 43 throw new RuntimeException("Wrong number of parameters."); 44 } 45 File blah = File.createTempFile("blah", null); 46 blah.deleteOnExit(); 47 RandomAccessFile raf = new RandomAccessFile(blah, "rw"); 48 raf.write(1); 49 raf.close(); 50 test1(blah, "1"); 51 test1(blah, "2"); 52 test2(blah, true); 53 test2(blah, false); 54 test3(blah); 55 test4(blah); 56 } 57 58 /** 59 * Test mutual locking with other process 60 */ 61 static void test1(File blah, String str) throws Exception { 62 try (RandomAccessFile fis = new RandomAccessFile(blah, "rw")) { 63 FileChannel fc = fis.getChannel(); 64 FileLock lock = null; 65 66 // grab the lock 67 if (str.equals("1")) { 68 lock = fc.lock(0, 10, false); 69 if (lock == null) 70 throw new RuntimeException("Lock should not return null"); 71 try { 72 fc.lock(5, 10, false); 73 throw new RuntimeException("Overlapping locks allowed"); 74 } catch (OverlappingFileLockException e) {} // correct result 75 } 76 77 // execute the tamperer 78 String command = System.getProperty("java.home") + 79 File.separator + "bin" + File.separator + "java"; 80 String testClasses = System.getProperty("test.classes"); 81 if (testClasses != null) 82 command += " -cp " + testClasses; 83 command += " Lock " + str + " " + blah; 84 Process p = Runtime.getRuntime().exec(command); 85 86 // evaluate System.out of child process 87 String s; 88 boolean hasOutput = false; 89 InputStreamReader isr; 90 isr = new InputStreamReader(p.getInputStream()); 91 BufferedReader br = new BufferedReader(isr); 92 while ((s = br.readLine()) != null) { 93 // only throw on Unix as windows over NFS fails... 94 if ((File.separatorChar == '/') && !s.equals("good")) { 95 throw new RuntimeException("Failed: " + s); 96 } 97 hasOutput = true; 98 } 99 100 // evaluate System.err in case of System.out of child process 101 // was empty 102 if (!hasOutput) { 103 isr = new InputStreamReader(p.getErrorStream()); 104 br = new BufferedReader(isr); 105 if ((s = br.readLine()) != null) { 106 System.err.println("Error output:"); 107 System.err.println(s); 108 while ((s = br.readLine()) != null) { 109 System.err.println(s); 110 } 111 } 112 throw new RuntimeException("Failed, no output"); 113 } 114 115 // clean up, check multiple releases 116 if (lock != null) { 117 lock.release(); 118 lock.release(); 119 } 120 } 121 } 122 123 /** 124 * Basic test for FileChannel.lock() and FileChannel.tryLock() 125 */ 126 static void test2(File blah, boolean b) throws Exception { 127 try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) { 128 FileChannel channel = raf.getChannel(); 129 FileLock lock; 130 if (b) 131 lock = channel.lock(); 132 else 133 lock = channel.tryLock(); 134 lock.release(); 135 } 136 } 137 138 /** 139 * Test that overlapping file locking is not possible when using different 140 * FileChannel objects to the same file path 141 */ 142 static void test3(File blah) throws Exception { 143 try (RandomAccessFile raf1 = new RandomAccessFile(blah, "rw"); 144 RandomAccessFile raf2 = new RandomAccessFile(blah, "rw")) 145 { 146 FileChannel fc1 = raf1.getChannel(); 147 FileChannel fc2 = raf2.getChannel(); 148 149 // lock via one channel, and then attempt to lock the same file 150 // using a second channel 151 FileLock fl1 = fc1.lock(); 152 try { 153 fc2.tryLock(); 154 throw new RuntimeException("Overlapping locks allowed"); 155 } catch (OverlappingFileLockException x) {} 156 try { 157 fc2.lock(); 158 throw new RuntimeException("Overlapping locks allowed"); 159 } catch (OverlappingFileLockException x) {} 160 161 // release lock and the attempt to lock with the second channel 162 // should succeed. 163 fl1.release(); 164 fc2.lock(); 165 try { 166 fc1.lock(); 167 throw new RuntimeException("Overlapping locks allowed"); 168 } catch (OverlappingFileLockException x) {} 169 } 170 } 171 172 /** 173 * Test file locking when file is opened for append 174 */ 175 static void test4(File blah) throws Exception { 176 try (FileOutputStream fos = new FileOutputStream(blah, true)) { 177 FileChannel fc = fos.getChannel(); 178 fc.tryLock().release(); 179 fc.tryLock(0L, 1L, false).release(); 180 fc.lock().release(); 181 fc.lock(0L, 1L, false).release(); 182 } 183 try (FileChannel fc = FileChannel.open(blah.toPath(), APPEND)) { 184 fc.tryLock().release(); 185 fc.tryLock(0L, 1L, false).release(); 186 fc.lock().release(); 187 fc.lock(0L, 1L, false).release(); 188 } 189 } 190 191 /** 192 * Utility method to be run in secondary process which tries to acquire a 193 * lock on a FileChannel 194 */ 195 static void attemptLock(String fileName, 196 boolean expectsLock) throws Exception 197 { 198 File f = new File(fileName); 199 try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) { 200 FileChannel fc = raf.getChannel(); 201 if (fc.tryLock(10, 10, false) == null) { 202 System.out.println("bad: Failed to grab adjacent lock"); 203 } 204 if (fc.tryLock(0, 10, false) == null) { 205 if (expectsLock) 206 System.out.println("bad"); 207 else 208 System.out.println("good"); 209 } else { 210 if (expectsLock) 211 System.out.println("good"); 212 else 213 System.out.println("bad"); 214 } 215 } 216 } 217} 218