001: package org.apache.lucene.store;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.File;
021: import java.io.IOException;
022:
023: /**
024: * <p>Implements {@link LockFactory} using {@link
025: * File#createNewFile()}. This is the default LockFactory
026: * for {@link FSDirectory}.</p>
027: *
028: * <p><b>NOTE:</b> the <a target="_top"
029: * href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html#createNewFile()">javadocs
030: * for <code>File.createNewFile</code></a> contain a vague
031: * yet spooky warning about not using the API for file
032: * locking. This warning was added due to <a target="_top"
033: * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4676183">this
034: * bug</a>, and in fact the only known problem with using
035: * this API for locking is that the Lucene write lock may
036: * not be released when the JVM exits abnormally.</p>
037:
038: * <p>When this happens, a {@link LockObtainFailedException}
039: * is hit when trying to create a writer, in which case you
040: * need to explicitly clear the lock file first. You can
041: * either manually remove the file, or use the {@link
042: * org.apache.lucene.index.IndexReader#unlock(Directory)}
043: * API. But, first be certain that no writer is in fact
044: * writing to the index otherwise you can easily corrupt
045: * your index.</p>
046: *
047: * <p>If you suspect that this or any other LockFactory is
048: * not working properly in your environment, you can easily
049: * test it by using {@link VerifyingLockFactory}, {@link
050: * LockVerifyServer} and {@link LockStressTest}.</p>
051: *
052: * @see LockFactory
053: */
054:
055: public class SimpleFSLockFactory extends LockFactory {
056:
057: /**
058: * Directory specified by <code>org.apache.lucene.lockDir</code>
059: * system property. If that is not set, then <code>java.io.tmpdir</code>
060: * system property is used.
061: */
062:
063: private File lockDir;
064:
065: /**
066: * Create a SimpleFSLockFactory instance, with null (unset)
067: * lock directory. This is package-private and is only
068: * used by FSDirectory when creating this LockFactory via
069: * the System property
070: * org.apache.lucene.store.FSDirectoryLockFactoryClass.
071: */
072: SimpleFSLockFactory() throws IOException {
073: this ((File) null);
074: }
075:
076: /**
077: * Instantiate using the provided directory (as a File instance).
078: * @param lockDir where lock files should be created.
079: */
080: public SimpleFSLockFactory(File lockDir) throws IOException {
081: setLockDir(lockDir);
082: }
083:
084: /**
085: * Instantiate using the provided directory name (String).
086: * @param lockDirName where lock files should be created.
087: */
088: public SimpleFSLockFactory(String lockDirName) throws IOException {
089: lockDir = new File(lockDirName);
090: setLockDir(lockDir);
091: }
092:
093: /**
094: * Set the lock directory. This is package-private and is
095: * only used externally by FSDirectory when creating this
096: * LockFactory via the System property
097: * org.apache.lucene.store.FSDirectoryLockFactoryClass.
098: */
099: void setLockDir(File lockDir) throws IOException {
100: this .lockDir = lockDir;
101: }
102:
103: public Lock makeLock(String lockName) {
104: if (lockPrefix != null) {
105: lockName = lockPrefix + "-" + lockName;
106: }
107: return new SimpleFSLock(lockDir, lockName);
108: }
109:
110: public void clearLock(String lockName) throws IOException {
111: if (lockDir.exists()) {
112: if (lockPrefix != null) {
113: lockName = lockPrefix + "-" + lockName;
114: }
115: File lockFile = new File(lockDir, lockName);
116: if (lockFile.exists() && !lockFile.delete()) {
117: throw new IOException("Cannot delete " + lockFile);
118: }
119: }
120: }
121: };
122:
123: class SimpleFSLock extends Lock {
124:
125: File lockFile;
126: File lockDir;
127:
128: public SimpleFSLock(File lockDir, String lockFileName) {
129: this .lockDir = lockDir;
130: lockFile = new File(lockDir, lockFileName);
131: }
132:
133: public boolean obtain() throws IOException {
134:
135: // Ensure that lockDir exists and is a directory:
136: if (!lockDir.exists()) {
137: if (!lockDir.mkdirs())
138: throw new IOException("Cannot create directory: "
139: + lockDir.getAbsolutePath());
140: } else if (!lockDir.isDirectory()) {
141: throw new IOException(
142: "Found regular file where directory expected: "
143: + lockDir.getAbsolutePath());
144: }
145: return lockFile.createNewFile();
146: }
147:
148: public void release() throws LockReleaseFailedException {
149: if (lockFile.exists() && !lockFile.delete())
150: throw new LockReleaseFailedException("failed to delete "
151: + lockFile);
152: }
153:
154: public boolean isLocked() {
155: return lockFile.exists();
156: }
157:
158: public String toString() {
159: return "SimpleFSLock@" + lockFile;
160: }
161: }
|