001 /*
002 * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.nio.channels;
027
028 import java.io.IOException;
029
030 /**
031 * A token representing a lock on a region of a file.
032 *
033 * <p> A file-lock object is created each time a lock is acquired on a file via
034 * one of the {@link FileChannel#lock(long,long,boolean) lock} or {@link
035 * FileChannel#tryLock(long,long,boolean) tryLock} methods of the {@link
036 * FileChannel} class.
037 *
038 * <p> A file-lock object is initially valid. It remains valid until the lock
039 * is released by invoking the {@link #release release} method, by closing the
040 * channel that was used to acquire it, or by the termination of the Java
041 * virtual machine, whichever comes first. The validity of a lock may be
042 * tested by invoking its {@link #isValid isValid} method.
043 *
044 * <p> A file lock is either <i>exclusive</i> or <i>shared</i>. A shared lock
045 * prevents other concurrently-running programs from acquiring an overlapping
046 * exclusive lock, but does allow them to acquire overlapping shared locks. An
047 * exclusive lock prevents other programs from acquiring an overlapping lock of
048 * either type. Once it is released, a lock has no further effect on the locks
049 * that may be acquired by other programs.
050 *
051 * <p> Whether a lock is exclusive or shared may be determined by invoking its
052 * {@link #isShared isShared} method. Some platforms do not support shared
053 * locks, in which case a request for a shared lock is automatically converted
054 * into a request for an exclusive lock.
055 *
056 * <p> The locks held on a particular file by a single Java virtual machine do
057 * not overlap. The {@link #overlaps overlaps} method may be used to test
058 * whether a candidate lock range overlaps an existing lock.
059 *
060 * <p> A file-lock object records the file channel upon whose file the lock is
061 * held, the type and validity of the lock, and the position and size of the
062 * locked region. Only the validity of a lock is subject to change over time;
063 * all other aspects of a lock's state are immutable.
064 *
065 * <p> File locks are held on behalf of the entire Java virtual machine.
066 * They are not suitable for controlling access to a file by multiple
067 * threads within the same virtual machine.
068 *
069 * <p> File-lock objects are safe for use by multiple concurrent threads.
070 *
071 *
072 * <a name="pdep">
073 * <h4> Platform dependencies </h4>
074 *
075 * <p> This file-locking API is intended to map directly to the native locking
076 * facility of the underlying operating system. Thus the locks held on a file
077 * should be visible to all programs that have access to the file, regardless
078 * of the language in which those programs are written.
079 *
080 * <p> Whether or not a lock actually prevents another program from accessing
081 * the content of the locked region is system-dependent and therefore
082 * unspecified. The native file-locking facilities of some systems are merely
083 * <i>advisory</i>, meaning that programs must cooperatively observe a known
084 * locking protocol in order to guarantee data integrity. On other systems
085 * native file locks are <i>mandatory</i>, meaning that if one program locks a
086 * region of a file then other programs are actually prevented from accessing
087 * that region in a way that would violate the lock. On yet other systems,
088 * whether native file locks are advisory or mandatory is configurable on a
089 * per-file basis. To ensure consistent and correct behavior across platforms,
090 * it is strongly recommended that the locks provided by this API be used as if
091 * they were advisory locks.
092 *
093 * <p> On some systems, acquiring a mandatory lock on a region of a file
094 * prevents that region from being {@link java.nio.channels.FileChannel#map
095 * </code>mapped into memory<code>}, and vice versa. Programs that combine
096 * locking and mapping should be prepared for this combination to fail.
097 *
098 * <p> On some systems, closing a channel releases all locks held by the Java
099 * virtual machine on the underlying file regardless of whether the locks were
100 * acquired via that channel or via another channel open on the same file. It
101 * is strongly recommended that, within a program, a unique channel be used to
102 * acquire all locks on any given file.
103 *
104 * <p> Some network filesystems permit file locking to be used with
105 * memory-mapped files only when the locked regions are page-aligned and a
106 * whole multiple of the underlying hardware's page size. Some network
107 * filesystems do not implement file locks on regions that extend past a
108 * certain position, often 2<sup>30</sup> or 2<sup>31</sup>. In general, great
109 * care should be taken when locking files that reside on network filesystems.
110 *
111 *
112 * @author Mark Reinhold
113 * @author JSR-51 Expert Group
114 * @version 1.15, 07/05/05
115 * @since 1.4
116 */
117
118 public abstract class FileLock {
119
120 private final FileChannel channel;
121 private final long position;
122 private final long size;
123 private final boolean shared;
124
125 /**
126 * Initializes a new instance of this class. </p>
127 *
128 * @param channel
129 * The file channel upon whose file this lock is held
130 *
131 * @param position
132 * The position within the file at which the locked region starts;
133 * must be non-negative
134 *
135 * @param size
136 * The size of the locked region; must be non-negative, and the sum
137 * <tt>position</tt> + <tt>size</tt> must be non-negative
138 *
139 * @param shared
140 * <tt>true</tt> if this lock is shared,
141 * <tt>false</tt> if it is exclusive
142 *
143 * @throws IllegalArgumentException
144 * If the preconditions on the parameters do not hold
145 */
146 protected FileLock(FileChannel channel, long position, long size,
147 boolean shared) {
148 if (position < 0)
149 throw new IllegalArgumentException("Negative position");
150 if (size < 0)
151 throw new IllegalArgumentException("Negative size");
152 if (position + size < 0)
153 throw new IllegalArgumentException(
154 "Negative position + size");
155 this .channel = channel;
156 this .position = position;
157 this .size = size;
158 this .shared = shared;
159 }
160
161 /**
162 * Returns the file channel upon whose file this lock is held. </p>
163 *
164 * @return The file channel
165 */
166 public final FileChannel channel() {
167 return channel;
168 }
169
170 /**
171 * Returns the position within the file of the first byte of the locked
172 * region.
173 *
174 * <p> A locked region need not be contained within, or even overlap, the
175 * actual underlying file, so the value returned by this method may exceed
176 * the file's current size. </p>
177 *
178 * @return The position
179 */
180 public final long position() {
181 return position;
182 }
183
184 /**
185 * Returns the size of the locked region in bytes.
186 *
187 * <p> A locked region need not be contained within, or even overlap, the
188 * actual underlying file, so the value returned by this method may exceed
189 * the file's current size. </p>
190 *
191 * @return The size of the locked region
192 */
193 public final long size() {
194 return size;
195 }
196
197 /**
198 * Tells whether this lock is shared. </p>
199 *
200 * @return <tt>true</tt> if lock is shared,
201 * <tt>false</tt> if it is exclusive
202 */
203 public final boolean isShared() {
204 return shared;
205 }
206
207 /**
208 * Tells whether or not this lock overlaps the given lock range. </p>
209 *
210 * @return <tt>true</tt> if, and only if, this lock and the given lock
211 * range overlap by at least one byte
212 */
213 public final boolean overlaps(long position, long size) {
214 if (position + size <= this .position)
215 return false; // That is below this
216 if (this .position + this .size <= position)
217 return false; // This is below that
218 return true;
219 }
220
221 /**
222 * Tells whether or not this lock is valid.
223 *
224 * <p> A lock object remains valid until it is released or the associated
225 * file channel is closed, whichever comes first. </p>
226 *
227 * @return <tt>true</tt> if, and only if, this lock is valid
228 */
229 public abstract boolean isValid();
230
231 /**
232 * Releases this lock.
233 *
234 * <p> If this lock object is valid then invoking this method releases the
235 * lock and renders the object invalid. If this lock object is invalid
236 * then invoking this method has no effect. </p>
237 *
238 * @throws ClosedChannelException
239 * If the channel that was used to acquire this lock
240 * is no longer open
241 *
242 * @throws IOException
243 * If an I/O error occurs
244 */
245 public abstract void release() throws IOException;
246
247 /**
248 * Returns a string describing the range, type, and validity of this lock.
249 *
250 * @return A descriptive string
251 */
252 public final String toString() {
253 return (this .getClass().getName() + "[" + position + ":" + size
254 + " " + (shared ? "shared" : "exclusive") + " "
255 + (isValid() ? "valid" : "invalid") + "]");
256 }
257
258 }
|