001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.persist;
032:
033: import java.nio.channels.FileChannel;
034: import java.nio.channels.FileLock;
035:
036: /**
037: * A LockFile variant that capitalizes upon the
038: * availability of {@link java.nio.channels.FileLock FileLock}.
039: *
040: * @author boucherb@users
041: * @version 1.7.2
042: * @since 1.7.2
043: *
044: */
045: final class NIOLockFile extends LockFile {
046:
047: // From the java.nio.channels.FileLock API docs:
048: //
049: // Some network filesystems do not implement file locks on regions
050: // that extend past a certain position, often 2**30 or 2**31.
051: // In general, great care should be taken when locking files that
052: // reside on network filesystems.
053: static final long MAX_NFS_LOCK_REGION = (1L << 30);
054: static final long MIN_LOCK_REGION = MAGIC.length + 8;
055:
056: /**
057: * A <code>FileChannel</code> object obtained from the super
058: * <code>raf</code> attribute. <p>
059: *
060: * The <code>fc</code> attribute is used to obtain this object's
061: * {@link #fl FileLock} attribute.
062: */
063: private FileChannel fc;
064:
065: /**
066: * The <code>FileLock</code> object used to lock this object's
067: * lock file.
068: */
069: private FileLock fl;
070:
071: /**
072: * Tries to obtain a valid NIO lock upon this object's lock file using
073: * this object's {@link #fl FileLock} attribute.
074: *
075: * @return true if a valid lock is obtained, else false.
076: * @throws Exception if an error occurs while attempting to obtain the lock
077: *
078: */
079: protected boolean lockImpl() throws Exception {
080:
081: boolean isValid;
082:
083: if (fl != null && fl.isValid()) {
084: return true;
085: }
086:
087: trace("lockImpl(): fc = raf.getChannel()");
088:
089: fc = raf.getChannel();
090:
091: trace("lockImpl(): fl = fc.tryLock()");
092:
093: fl = null;
094:
095: try {
096: fl = fc.tryLock(0, MIN_LOCK_REGION, false);
097:
098: trace("lockImpl(): fl = " + fl);
099: } catch (Exception e) {
100:
101: // This will not work with a localized JVM
102: /*
103: if (-1 == e.toString().indexOf("No locks available")) {
104: throw e;
105: } else {
106: trace(e.toString());
107: }
108: */
109: trace(e.toString());
110: }
111:
112: // In an ideal world, maybe?:
113: // try {
114: // fl = fc.tryLock();
115: //
116: // trace("lockImpl(): fl = " + fl);
117: // } catch (Exception e) {
118: // trace(e.toString());
119: //
120: // try {
121: // fl = fc.tryLock(0, MAX_NFS_LOCK_REGION, false);
122: //
123: // trace("lockImpl(): fl = " + fl);
124: // trace("Warning: possibly attempting to lock on NFS");
125: // } catch (Exception e2) {
126: // trace(e2.toString());
127: //
128: // try {
129: // fl = fc.tryLock(0, MIN_LOCK_REGION, false);
130: //
131: // trace("lockImpl(): fl = " + fl);
132: // trace("Warning: backed off to min lock region");
133: // trace("Warning: lock file may be unusable on reuse");
134: // } catch (Exception e3) {
135: // trace(e3.toString());
136: // }
137: // }
138: // }
139: trace("lockImpl(): f.deleteOnExit()");
140: f.deleteOnExit();
141:
142: isValid = fl != null && fl.isValid();
143:
144: trace("lockImpl():isValid(): " + isValid);
145:
146: return isValid;
147: }
148:
149: /**
150: * Tries to release any valid lock held upon this object's lock file using
151: * this object's {@link #fl FileLock} attribute.
152: *
153: * @return true if a valid lock is released, else false
154: * @throws Exception if na error occurs while attempting to release the lock
155: */
156: protected boolean releaseImpl() throws Exception {
157:
158: // PRE: we know that this method is only called
159: // if isLocked() is true.
160: trace("releaseImpl(): fl = " + fl);
161:
162: if (fl != null) {
163: trace("releaseImpl(): fl.release()");
164: fl.release();
165: trace("tryRelease(): fl = " + fl);
166:
167: fl = null;
168: }
169:
170: trace("releaseImpl(): fc = " + fc);
171:
172: if (fc != null) {
173: trace("releaseImpl(): fc.close()");
174: fc.close();
175:
176: fc = null;
177: }
178:
179: // CHECKME:
180: // possibly overcomes some regarding full and
181: // true release of FileLock and maybe related
182: // NIO resources?
183: // System.gc();
184: return true;
185: }
186:
187: /**
188: * Retrieves whether this object's {@link #fl FileLock} attribute represents
189: * a valid lock upon this object's lock file.
190: *
191: * @return true if this object's {@link #fl FileLock} attribute is valid,
192: * else false
193: */
194: public boolean isValid() {
195: return super .isValid() && (fl != null && fl.isValid());
196: }
197:
198: /**
199: * Retrieves the String value: "fl =" + fl
200: * @return the String value: "fl =" + fl
201: */
202: protected String toStringImpl() {
203: return "fl =" + fl;
204: }
205: }
|