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.IndexReader;
30 import org.apache.lucene.index.IndexWriter;
31 import org.apache.lucene.index.IndexWriterConfig;
32 import org.apache.lucene.index.Term;
33 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
34 import org.apache.lucene.search.IndexSearcher;
35 import org.apache.lucene.search.Query;
36 import org.apache.lucene.search.TermQuery;
37 import org.apache.lucene.util.LuceneTestCase;
38 import org.apache.lucene.util._TestUtil;
40 public class TestLockFactory extends LuceneTestCase {
42 // Verify: we can provide our own LockFactory implementation, the right
43 // methods are called at the right time, locks are created, etc.
45 public void testCustomLockFactory() throws IOException {
46 Directory dir = new MockDirectoryWrapper(random, new RAMDirectory());
47 MockLockFactory lf = new MockLockFactory();
48 dir.setLockFactory(lf);
50 // Lock prefix should have been set:
51 assertTrue("lock prefix was not set by the RAMDirectory", lf.lockPrefixSet);
53 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
55 // add 100 documents (so that commit lock is used)
56 for (int i = 0; i < 100; i++) {
60 // Both write lock and commit lock should have been created:
61 assertEquals("# of unique locks created (after instantiating IndexWriter)",
62 1, lf.locksCreated.size());
63 assertTrue("# calls to makeLock is 0 (after instantiating IndexWriter)",
64 lf.makeLockCount >= 1);
66 for(final String lockName : lf.locksCreated.keySet()) {
67 MockLockFactory.MockLock lock = (MockLockFactory.MockLock) lf.locksCreated.get(lockName);
68 assertTrue("# calls to Lock.obtain is 0 (after instantiating IndexWriter)",
69 lock.lockAttempts > 0);
75 // Verify: we can use the NoLockFactory with RAMDirectory w/ no
77 // Verify: NoLockFactory allows two IndexWriters
78 public void testRAMDirectoryNoLocking() throws IOException {
79 Directory dir = new MockDirectoryWrapper(random, new RAMDirectory());
80 dir.setLockFactory(NoLockFactory.getNoLockFactory());
82 assertTrue("RAMDirectory.setLockFactory did not take",
83 NoLockFactory.class.isInstance(dir.getLockFactory()));
85 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
86 writer.commit(); // required so the second open succeed
87 // Create a 2nd IndexWriter. This is normally not allowed but it should run through since we're not
89 IndexWriter writer2 = null;
91 writer2 = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
92 } catch (Exception e) {
93 e.printStackTrace(System.out);
94 fail("Should not have hit an IOException with no locking");
98 if (writer2 != null) {
103 // Verify: SingleInstanceLockFactory is the default lock for RAMDirectory
104 // Verify: RAMDirectory does basic locking correctly (can't create two IndexWriters)
105 public void testDefaultRAMDirectory() throws IOException {
106 Directory dir = new RAMDirectory();
108 assertTrue("RAMDirectory did not use correct LockFactory: got " + dir.getLockFactory(),
109 SingleInstanceLockFactory.class.isInstance(dir.getLockFactory()));
111 IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
113 // Create a 2nd IndexWriter. This should fail:
114 IndexWriter writer2 = null;
116 writer2 = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
117 fail("Should have hit an IOException with two IndexWriters on default SingleInstanceLockFactory");
118 } catch (IOException e) {
122 if (writer2 != null) {
127 public void testSimpleFSLockFactory() throws IOException {
128 // test string file instantiation
129 new SimpleFSLockFactory("test");
132 // Verify: do stress test, by opening IndexReaders and
133 // IndexWriters over & over in 2 threads and making sure
134 // no unexpected exceptions are raised:
135 public void testStressLocks() throws Exception {
136 _testStressLocks(null, _TestUtil.getTempDir("index.TestLockFactory6"));
139 // Verify: do stress test, by opening IndexReaders and
140 // IndexWriters over & over in 2 threads and making sure
141 // no unexpected exceptions are raised, but use
142 // NativeFSLockFactory:
143 public void testStressLocksNativeFSLockFactory() throws Exception {
144 File dir = _TestUtil.getTempDir("index.TestLockFactory7");
145 _testStressLocks(new NativeFSLockFactory(dir), dir);
148 public void _testStressLocks(LockFactory lockFactory, File indexDir) throws Exception {
149 Directory dir = newFSDirectory(indexDir, lockFactory);
151 // First create a 1 doc index:
152 IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
156 WriterThread writer = new WriterThread(100, dir);
157 SearcherThread searcher = new SearcherThread(100, dir);
161 while(writer.isAlive() || searcher.isAlive()) {
165 assertTrue("IndexWriter hit unexpected exceptions", !writer.hitException);
166 assertTrue("IndexSearcher hit unexpected exceptions", !searcher.hitException);
170 _TestUtil.rmDir(indexDir);
173 // Verify: NativeFSLockFactory works correctly
174 public void testNativeFSLockFactory() throws IOException {
176 NativeFSLockFactory f = new NativeFSLockFactory(TEMP_DIR);
178 f.setLockPrefix("test");
179 Lock l = f.makeLock("commit");
180 Lock l2 = f.makeLock("commit");
182 assertTrue("failed to obtain lock", l.obtain());
183 assertTrue("succeeded in obtaining lock twice", !l2.obtain());
186 assertTrue("failed to obtain 2nd lock after first one was freed", l2.obtain());
189 // Make sure we can obtain first one again, test isLocked():
190 assertTrue("failed to obtain lock", l.obtain());
191 assertTrue(l.isLocked());
192 assertTrue(l2.isLocked());
194 assertFalse(l.isLocked());
195 assertFalse(l2.isLocked());
199 // Verify: NativeFSLockFactory works correctly if the lock file exists
200 public void testNativeFSLockFactoryLockExists() throws IOException {
202 File lockFile = new File(TEMP_DIR, "test.lock");
203 lockFile.createNewFile();
205 Lock l = new NativeFSLockFactory(TEMP_DIR).makeLock("test.lock");
206 assertTrue("failed to obtain lock", l.obtain());
208 assertFalse("failed to release lock", l.isLocked());
209 if (lockFile.exists()) {
214 public void testNativeFSLockReleaseByOtherLock() throws IOException {
216 NativeFSLockFactory f = new NativeFSLockFactory(TEMP_DIR);
218 f.setLockPrefix("test");
219 Lock l = f.makeLock("commit");
220 Lock l2 = f.makeLock("commit");
222 assertTrue("failed to obtain lock", l.obtain());
224 assertTrue(l2.isLocked());
226 fail("should not have reached here. LockReleaseFailedException should have been thrown");
227 } catch (LockReleaseFailedException e) {
234 // Verify: NativeFSLockFactory assigns null as lockPrefix if the lockDir is inside directory
235 public void testNativeFSLockFactoryPrefix() throws IOException {
236 File fdir1 = _TestUtil.getTempDir("TestLockFactory.8");
237 File fdir2 = _TestUtil.getTempDir("TestLockFactory.8.Lockdir");
238 Directory dir1 = newFSDirectory(fdir1, new NativeFSLockFactory(fdir1));
239 // same directory, but locks are stored somewhere else. The prefix of the lock factory should != null
240 Directory dir2 = newFSDirectory(fdir1, new NativeFSLockFactory(fdir2));
242 String prefix1 = dir1.getLockFactory().getLockPrefix();
243 assertNull("Lock prefix for lockDir same as directory should be null", prefix1);
245 String prefix2 = dir2.getLockFactory().getLockPrefix();
246 assertNotNull("Lock prefix for lockDir outside of directory should be not null", prefix2);
251 _TestUtil.rmDir(fdir1);
252 _TestUtil.rmDir(fdir2);
255 // Verify: default LockFactory has no prefix (ie
256 // write.lock is stored in index):
257 public void testDefaultFSLockFactoryPrefix() throws IOException {
258 // Make sure we get null prefix, which wont happen if setLockFactory is ever called.
259 File dirName = _TestUtil.getTempDir("TestLockFactory.10");
261 Directory dir = new SimpleFSDirectory(dirName);
262 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
265 dir = new MMapDirectory(dirName);
266 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
269 dir = new NIOFSDirectory(dirName);
270 assertNull("Default lock prefix should be null", dir.getLockFactory().getLockPrefix());
273 _TestUtil.rmDir(dirName);
276 private class WriterThread extends Thread {
277 private Directory dir;
278 private int numIteration;
279 public boolean hitException = false;
280 public WriterThread(int numIteration, Directory dir) {
281 this.numIteration = numIteration;
286 IndexWriter writer = null;
287 for(int i=0;i<this.numIteration;i++) {
289 writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
290 } catch (IOException e) {
291 if (e.toString().indexOf(" timed out:") == -1) {
293 System.out.println("Stress Test Index Writer: creation hit unexpected IOException: " + e.toString());
294 e.printStackTrace(System.out);
296 // lock obtain timed out
297 // NOTE: we should at some point
298 // consider this a failure? The lock
299 // obtains, across IndexReader &
300 // IndexWriters should be "fair" (ie
303 } catch (Exception e) {
305 System.out.println("Stress Test Index Writer: creation hit unexpected exception: " + e.toString());
306 e.printStackTrace(System.out);
309 if (writer != null) {
312 } catch (IOException e) {
314 System.out.println("Stress Test Index Writer: addDoc hit unexpected exception: " + e.toString());
315 e.printStackTrace(System.out);
320 } catch (IOException e) {
322 System.out.println("Stress Test Index Writer: close hit unexpected exception: " + e.toString());
323 e.printStackTrace(System.out);
332 private class SearcherThread extends Thread {
333 private Directory dir;
334 private int numIteration;
335 public boolean hitException = false;
336 public SearcherThread(int numIteration, Directory dir) {
337 this.numIteration = numIteration;
342 IndexReader reader = null;
343 IndexSearcher searcher = null;
344 Query query = new TermQuery(new Term("content", "aaa"));
345 for(int i=0;i<this.numIteration;i++) {
347 reader = IndexReader.open(dir, false);
348 searcher = new IndexSearcher(reader);
349 } catch (Exception e) {
351 System.out.println("Stress Test Index Searcher: create hit unexpected exception: " + e.toString());
352 e.printStackTrace(System.out);
356 searcher.search(query, null, 1000);
357 } catch (IOException e) {
359 System.out.println("Stress Test Index Searcher: search hit unexpected exception: " + e.toString());
360 e.printStackTrace(System.out);
363 // System.out.println(hits.length() + " total results");
367 } catch (IOException e) {
369 System.out.println("Stress Test Index Searcher: close hit unexpected exception: " + e.toString());
370 e.printStackTrace(System.out);
377 public class MockLockFactory extends LockFactory {
379 public boolean lockPrefixSet;
380 public Map<String,Lock> locksCreated = Collections.synchronizedMap(new HashMap<String,Lock>());
381 public int makeLockCount = 0;
384 public void setLockPrefix(String lockPrefix) {
385 super.setLockPrefix(lockPrefix);
386 lockPrefixSet = true;
390 synchronized public Lock makeLock(String lockName) {
391 Lock lock = new MockLock();
392 locksCreated.put(lockName, lock);
398 public void clearLock(String specificLockName) {}
400 public class MockLock extends Lock {
401 public int lockAttempts;
404 public boolean obtain() {
409 public void release() {
413 public boolean isLocked() {
419 private void addDoc(IndexWriter writer) throws IOException {
420 Document doc = new Document();
421 doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
422 writer.addDocument(doc);