1 package org.apache.lucene.store;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 import java.io.IOException;
22 import java.util.Collections;
23 import java.util.HashMap;
26 import org.apache.lucene.analysis.MockAnalyzer;
27 import org.apache.lucene.document.Document;
28 import org.apache.lucene.document.Field;
29 import org.apache.lucene.index.IndexWriter;
30 import org.apache.lucene.index.IndexWriterConfig;
31 import org.apache.lucene.index.Term;
32 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
33 import org.apache.lucene.search.IndexSearcher;
34 import org.apache.lucene.search.Query;
35 import org.apache.lucene.search.TermQuery;
36 import org.apache.lucene.util.LuceneTestCase;
37 import org.apache.lucene.util._TestUtil;
39 public class TestLockFactory extends LuceneTestCase {
41 // Verify: we can provide our own LockFactory implementation, the right
42 // methods are called at the right time, locks are created, etc.
44 public void testCustomLockFactory() throws IOException {
45 Directory dir = new MockDirectoryWrapper(random, new RAMDirectory());
46 MockLockFactory lf = new MockLockFactory();
47 dir.setLockFactory(lf);
49 // Lock prefix should have been set:
50 assertTrue("lock prefix was not set by the RAMDirectory", lf.lockPrefixSet);
52 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
54 // add 100 documents (so that commit lock is used)
55 for (int i = 0; i < 100; i++) {
59 // Both write lock and commit lock should have been created:
60 assertEquals("# of unique locks created (after instantiating IndexWriter)",
61 1, lf.locksCreated.size());
62 assertTrue("# calls to makeLock is 0 (after instantiating IndexWriter)",
63 lf.makeLockCount >= 1);
65 for(final String lockName : lf.locksCreated.keySet()) {
66 MockLockFactory.MockLock lock = (MockLockFactory.MockLock) lf.locksCreated.get(lockName);
67 assertTrue("# calls to Lock.obtain is 0 (after instantiating IndexWriter)",
68 lock.lockAttempts > 0);
74 // Verify: we can use the NoLockFactory with RAMDirectory w/ no
76 // Verify: NoLockFactory allows two IndexWriters
77 public void testRAMDirectoryNoLocking() throws IOException {
78 Directory dir = new MockDirectoryWrapper(random, new RAMDirectory());
79 dir.setLockFactory(NoLockFactory.getNoLockFactory());
81 assertTrue("RAMDirectory.setLockFactory did not take",
82 NoLockFactory.class.isInstance(dir.getLockFactory()));
84 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
85 writer.commit(); // required so the second open succeed
86 // Create a 2nd IndexWriter. This is normally not allowed but it should run through since we're not
88 IndexWriter writer2 = null;
90 writer2 = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
91 } catch (Exception e) {
92 e.printStackTrace(System.out);
93 fail("Should not have hit an IOException with no locking");
97 if (writer2 != null) {
102 // Verify: SingleInstanceLockFactory is the default lock for RAMDirectory
103 // Verify: RAMDirectory does basic locking correctly (can't create two IndexWriters)
104 public void testDefaultRAMDirectory() throws IOException {
105 Directory dir = new RAMDirectory();
107 assertTrue("RAMDirectory did not use correct LockFactory: got " + dir.getLockFactory(),
108 SingleInstanceLockFactory.class.isInstance(dir.getLockFactory()));
110 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
112 // Create a 2nd IndexWriter. This should fail:
113 IndexWriter writer2 = null;
115 writer2 = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
116 fail("Should have hit an IOException with two IndexWriters on default SingleInstanceLockFactory");
117 } catch (IOException e) {
121 if (writer2 != null) {
126 public void testSimpleFSLockFactory() throws IOException {
127 // test string file instantiation
128 new SimpleFSLockFactory("test");
131 // Verify: do stress test, by opening IndexReaders and
132 // IndexWriters over & over in 2 threads and making sure
133 // no unexpected exceptions are raised:
134 public void testStressLocks() throws Exception {
135 _testStressLocks(null, _TestUtil.getTempDir("index.TestLockFactory6"));
138 // Verify: do stress test, by opening IndexReaders and
139 // IndexWriters over & over in 2 threads and making sure
140 // no unexpected exceptions are raised, but use
141 // NativeFSLockFactory:
142 public void testStressLocksNativeFSLockFactory() throws Exception {
143 File dir = _TestUtil.getTempDir("index.TestLockFactory7");
144 _testStressLocks(new NativeFSLockFactory(dir), dir);
147 public void _testStressLocks(LockFactory lockFactory, File indexDir) throws Exception {
148 Directory dir = newFSDirectory(indexDir, lockFactory);
150 // First create a 1 doc index:
151 IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
155 WriterThread writer = new WriterThread(100, dir);
156 SearcherThread searcher = new SearcherThread(100, dir);
160 while(writer.isAlive() || searcher.isAlive()) {
164 assertTrue("IndexWriter hit unexpected exceptions", !writer.hitException);
165 assertTrue("IndexSearcher hit unexpected exceptions", !searcher.hitException);
169 _TestUtil.rmDir(indexDir);
172 // Verify: NativeFSLockFactory works correctly
173 public void testNativeFSLockFactory() throws IOException {
175 NativeFSLockFactory f = new NativeFSLockFactory(TEMP_DIR);
177 f.setLockPrefix("test");
178 Lock l = f.makeLock("commit");
179 Lock l2 = f.makeLock("commit");
181 assertTrue("failed to obtain lock", l.obtain());
182 assertTrue("succeeded in obtaining lock twice", !l2.obtain());
185 assertTrue("failed to obtain 2nd lock after first one was freed", l2.obtain());
188 // Make sure we can obtain first one again, test isLocked():
189 assertTrue("failed to obtain lock", l.obtain());
190 assertTrue(l.isLocked());
191 assertTrue(l2.isLocked());
193 assertFalse(l.isLocked());
194 assertFalse(l2.isLocked());
198 // Verify: NativeFSLockFactory works correctly if the lock file exists
199 public void testNativeFSLockFactoryLockExists() throws IOException {
201 File lockFile = new File(TEMP_DIR, "test.lock");
202 lockFile.createNewFile();
204 Lock l = new NativeFSLockFactory(TEMP_DIR).makeLock("test.lock");
205 assertTrue("failed to obtain lock", l.obtain());
207 assertFalse("failed to release lock", l.isLocked());
208 if (lockFile.exists()) {
213 public void testNativeFSLockReleaseByOtherLock() throws IOException {
215 NativeFSLockFactory f = new NativeFSLockFactory(TEMP_DIR);
217 f.setLockPrefix("test");
218 Lock l = f.makeLock("commit");
219 Lock l2 = f.makeLock("commit");
221 assertTrue("failed to obtain lock", l.obtain());
223 assertTrue(l2.isLocked());
225 fail("should not have reached here. LockReleaseFailedException should have been thrown");
226 } catch (LockReleaseFailedException e) {
233 // Verify: NativeFSLockFactory assigns null as lockPrefix if the lockDir is inside directory
234 public void testNativeFSLockFactoryPrefix() throws IOException {
235 File fdir1 = _TestUtil.getTempDir("TestLockFactory.8");
236 File fdir2 = _TestUtil.getTempDir("TestLockFactory.8.Lockdir");
237 Directory dir1 = newFSDirectory(fdir1, new NativeFSLockFactory(fdir1));
238 // same directory, but locks are stored somewhere else. The prefix of the lock factory should != null
239 Directory dir2 = newFSDirectory(fdir1, new NativeFSLockFactory(fdir2));
241 String prefix1 = dir1.getLockFactory().getLockPrefix();
242 assertNull("Lock prefix for lockDir same as directory should be null", prefix1);
244 String prefix2 = dir2.getLockFactory().getLockPrefix();
245 assertNotNull("Lock prefix for lockDir outside of directory should be not null", prefix2);
250 _TestUtil.rmDir(fdir1);
251 _TestUtil.rmDir(fdir2);
254 // Verify: default LockFactory has no prefix (ie
255 // write.lock is stored in index):
256 public void testDefaultFSLockFactoryPrefix() throws IOException {
257 // Make sure we get null prefix, which wont happen if setLockFactory is ever called.
258 File dirName = _TestUtil.getTempDir("TestLockFactory.10");
260 Directory dir = new SimpleFSDirectory(dirName);
261 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
264 dir = new MMapDirectory(dirName);
265 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
268 dir = new NIOFSDirectory(dirName);
269 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
272 _TestUtil.rmDir(dirName);
275 private class WriterThread extends Thread {
276 private Directory dir;
277 private int numIteration;
278 public boolean hitException = false;
279 public WriterThread(int numIteration, Directory dir) {
280 this.numIteration = numIteration;
285 IndexWriter writer = null;
286 for(int i=0;i<this.numIteration;i++) {
288 writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
289 } catch (IOException e) {
290 if (e.toString().indexOf(" timed out:") == -1) {
292 System.out.println("Stress Test Index Writer: creation hit unexpected IOException: " + e.toString());
293 e.printStackTrace(System.out);
295 // lock obtain timed out
296 // NOTE: we should at some point
297 // consider this a failure? The lock
298 // obtains, across IndexReader &
299 // IndexWriters should be "fair" (ie
302 } catch (Exception e) {
304 System.out.println("Stress Test Index Writer: creation hit unexpected exception: " + e.toString());
305 e.printStackTrace(System.out);
308 if (writer != null) {
311 } catch (IOException e) {
313 System.out.println("Stress Test Index Writer: addDoc hit unexpected exception: " + e.toString());
314 e.printStackTrace(System.out);
319 } catch (IOException e) {
321 System.out.println("Stress Test Index Writer: close hit unexpected exception: " + e.toString());
322 e.printStackTrace(System.out);
331 private class SearcherThread extends Thread {
332 private Directory dir;
333 private int numIteration;
334 public boolean hitException = false;
335 public SearcherThread(int numIteration, Directory dir) {
336 this.numIteration = numIteration;
341 IndexSearcher searcher = null;
342 Query query = new TermQuery(new Term("content", "aaa"));
343 for(int i=0;i<this.numIteration;i++) {
345 searcher = new IndexSearcher(dir, false);
346 } catch (Exception e) {
348 System.out.println("Stress Test Index Searcher: create hit unexpected exception: " + e.toString());
349 e.printStackTrace(System.out);
353 searcher.search(query, null, 1000);
354 } catch (IOException e) {
356 System.out.println("Stress Test Index Searcher: search hit unexpected exception: " + e.toString());
357 e.printStackTrace(System.out);
360 // System.out.println(hits.length() + " total results");
363 } catch (IOException e) {
365 System.out.println("Stress Test Index Searcher: close hit unexpected exception: " + e.toString());
366 e.printStackTrace(System.out);
373 public class MockLockFactory extends LockFactory {
375 public boolean lockPrefixSet;
376 public Map<String,Lock> locksCreated = Collections.synchronizedMap(new HashMap<String,Lock>());
377 public int makeLockCount = 0;
380 public void setLockPrefix(String lockPrefix) {
381 super.setLockPrefix(lockPrefix);
382 lockPrefixSet = true;
386 synchronized public Lock makeLock(String lockName) {
387 Lock lock = new MockLock();
388 locksCreated.put(lockName, lock);
394 public void clearLock(String specificLockName) {}
396 public class MockLock extends Lock {
397 public int lockAttempts;
400 public boolean obtain() {
405 public void release() {
409 public boolean isLocked() {
415 private void addDoc(IndexWriter writer) throws IOException {
416 Document doc = new Document();
417 doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
418 writer.addDocument(doc);