1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.nio.channels; 19 20 import java.io.IOException; 21 22 /** 23 * A {@code FileLock} represents a locked region of a file. 24 * <p> 25 * Locks have certain properties that enable collaborating processes to avoid 26 * the lost update problem or reading inconsistent data. Logically, a file lock 27 * can be <em>exclusive</em> or <em>shared</em>. Multiple processes can hold 28 * shared locks on the same region of a file, but only a single process can hold 29 * an exclusive lock on a given region of a file and no other process can 30 * simultaneously hold a shared lock overlapping the exclusive lock. An 31 * application can determine whether a {@code FileLock} is shared or exclusive 32 * via the {@code isShared()} method. 33 * <p> 34 * Locks held by a particular process cannot overlap one another. Applications 35 * can determine whether a proposed lock will overlap by using the {@code 36 * overlaps(long, long)}) method. Locks held in other processes may overlap 37 * locks held in this process. Locks are shared amongst all threads in the 38 * acquiring process, and are therefore unsuitable for intra-process 39 * synchronization. 40 * <p> 41 * Once a lock is acquired, it is immutable in all its state except {@code 42 * isValid()}. The lock will initially be valid, but may be rendered invalid by 43 * explicit removal of the lock, using {@code release()}, or implicitly by 44 * closing the channel or exiting the process (terminating the VM). 45 * <h3>Platform dependencies</h3> 46 * <p> 47 * Locks are intended to be true platform operating system file locks, and 48 * therefore locks held by the VM will be visible to other 49 * operating system processes. 50 * <p> 51 * The characteristics of the underlying operating system locks will show 52 * through in the Java implementation. For example, some platforms' locks are 53 * 'mandatory' -- meaning the operating system enforces the locks on processes 54 * that attempt to access locked regions of files; whereas other platforms' 55 * locks are only 'advisory' -- meaning that processes are required to 56 * collaborate to ensure locks are acquired and there is a potential for 57 * processes to not play well. To be on the safe side, it is best to assume that 58 * the platform is adopting advisory locks and always acquire shared locks when 59 * reading a region of a file. 60 * <p> 61 * On some platforms, the presence of a lock will prevent the file from being 62 * memory-mapped. On some platforms, closing a channel on a given file handle 63 * will release all the locks held on that file -- even if there are other 64 * channels open on the same file; their locks will also be released. The safe 65 * option here is to ensure that you only acquire locks on a single channel for 66 * a particular file and that becomes the synchronization point. 67 * <p> 68 * Further care should be exercised when locking files maintained on network 69 * file systems, since they often have further limitations. 70 */ 71 public abstract class FileLock implements AutoCloseable { 72 73 // The underlying file channel. 74 private final FileChannel channel; 75 76 // The lock starting position. 77 private final long position; 78 79 // The lock length in bytes 80 private final long size; 81 82 // If true then shared, if false then exclusive 83 private final boolean shared; 84 85 /** 86 * Constructs a new file lock instance for a given channel. The constructor 87 * enforces the starting position, length and sharing mode of the lock. 88 * 89 * @param channel 90 * the underlying file channel that holds the lock. 91 * @param position 92 * the starting point for the lock. 93 * @param size 94 * the length of the lock in number of bytes. 95 * @param shared 96 * the lock's sharing mode of lock; {@code true} is shared, 97 * {@code false} is exclusive. 98 */ FileLock(FileChannel channel, long position, long size, boolean shared)99 protected FileLock(FileChannel channel, long position, long size, boolean shared) { 100 if (position < 0 || size < 0 || position + size < 0) { 101 throw new IllegalArgumentException("position=" + position + " size=" + size); 102 } 103 this.channel = channel; 104 this.position = position; 105 this.size = size; 106 this.shared = shared; 107 } 108 109 /** 110 * Returns the lock's {@link FileChannel}. 111 */ channel()112 public final FileChannel channel() { 113 return channel; 114 } 115 116 /** 117 * Returns the lock's starting position in the file. 118 * 119 * @return the lock position. 120 */ position()121 public final long position() { 122 return position; 123 } 124 125 /** 126 * Returns the length of the file lock in bytes. 127 * 128 * @return the size of the file lock in bytes. 129 */ size()130 public final long size() { 131 return size; 132 } 133 134 /** 135 * Indicates if the file lock is shared with other processes or if it is 136 * exclusive. 137 * 138 * @return {@code true} if the lock is a shared lock, {@code false} if it is 139 * exclusive. 140 */ isShared()141 public final boolean isShared() { 142 return shared; 143 } 144 145 /** 146 * Indicates if the receiver's lock region overlaps the region described 147 * in the parameter list. 148 * 149 * @param start 150 * the starting position for the comparative lock. 151 * @param length 152 * the length of the comparative lock. 153 * @return {@code true} if there is an overlap, {@code false} otherwise. 154 */ overlaps(long start, long length)155 public final boolean overlaps(long start, long length) { 156 final long end = position + size - 1; 157 final long newEnd = start + length - 1; 158 if (end < start || position > newEnd) { 159 return false; 160 } 161 return true; 162 } 163 164 /** 165 * Indicates whether this lock is a valid file lock. The lock is 166 * valid unless the underlying channel has been closed or it has been 167 * explicitly released. 168 * 169 * @return {@code true} if the lock is valid, {@code false} otherwise. 170 */ isValid()171 public abstract boolean isValid(); 172 173 /** 174 * Releases this particular lock on the file. If the lock is invalid then 175 * this method has no effect. Once released, the lock becomes invalid. 176 * 177 * @throws ClosedChannelException 178 * if the channel is already closed when an attempt to release 179 * the lock is made. 180 * @throws IOException 181 * if another I/O error occurs. 182 */ release()183 public abstract void release() throws IOException; 184 185 /** 186 * Calls {@link #release} for {@code AutoCloseable}. 187 * 188 * @since 1.7 189 */ close()190 public final void close() throws IOException { 191 release(); 192 } 193 194 /** 195 * Returns a string that shows the details of the lock suitable for debugging. 196 */ 197 @Override toString()198 public final String toString() { 199 return "FileLock[position=" + position + ", size=" + size + ", shared=" + shared + "]"; 200 } 201 } 202