can not delete write.lock 这种错误-lucene web
这几天在学习lucene,学习过程中我首先写了一个程序,我们看一下
1 package app;
2 /**
3 * @author wrh 2011/10/11
4 */
5 import java.io.File;
6 import java.io.FileFilter;
7 import java.io.FileReader;
8 import java.io.IOException;
9
10 import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
11 import org.apache.lucene.analysis.standard.StandardAnalyzer;
12 import org.apache.lucene.document.Document;
13 import org.apache.lucene.document.Field;
14 import org.apache.lucene.index.IndexWriter;
15 import org.apache.lucene.store.Directory;
16 import org.apache.lucene.store.FSDirectory;
17 import org.apache.lucene.util.Version;
18
19 public class Indexer1 {
20 private IndexWriter writer;
21 private String indexDir = "D:\\jj";
22
23 public static void main(String[] args) throws Exception {
24
25 int numIndexed;
26 Indexer1 indexer = new Indexer1(indexDir);
27 System.out.println("Index begin");
28 try {
29 numIndexed = indexer.index(indexDir, new TextFilesFilter());
30 System.out.println(numIndexed);
31 } finally {
32 indexer.close();
33 }
34 }
35
36 //constructor
37 public Indexer1(String indexDir) throws IOException {
38 this.indexDir = indexDir;
39
40 Directory dir = FSDirectory.open(new File(indexDir));
41 writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED);
42 //writer.close();
43 //dir.close();
44 }
45
46 //close the indexwriter
47 public void close() throws IOException {
48 writer.close();
49 }
50
51 public int index(String dataDir, FileFilter filter) throws Exception {
52 File[] files = new File(dataDir).listFiles();
53
54 for (File f : files) {
55 if (!f.isDirectory() && !f.isHidden() && f.exists() && f.canRead() &&(filter == null || filter.accept(f))) {
56 indexFile(f);
57 }
58 }
59
60 return writer.numDocs();
61 }
62
63 //filter class
64 private static class TextFilesFilter implements FileFilter {
65 public boolean accept(File path) {
66 return path.getName().toLowerCase().endsWith(".txt");
67 }
68 }
69
70 //the contents of the index file
71 protected Document getDocument(File f) throws Exception {
72 Document doc = new Document();
73 doc.add(new Field("contents", new FileReader(f)));
74 doc.add(new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
75 doc.add(new Field("fullpath", f.getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
76 return doc;
77 }
78
79 private void indexFile(File f) throws Exception {
80 System.out.println("Indexing .." + f.getCanonicalPath());
81 Document doc = getDocument(f);
87 writer.addDocument(doc);
88 }
89
90 }
我们将它稍加修改,把main()改名为create()部署到web上去的时候,它会报一个错误:
can not delete writer.lock
我们查一下lucene3.0.3的API,我们会发现这样的一段的description:
IndexWriter
public IndexWriter(Directory d,
Analyzer a,
boolean create,
IndexWriter.MaxFieldLength mfl)
throws CorruptIndexException,
LockObtainFailedException,
IOException
Constructs an IndexWriter for the index in d. Text will be analyzed with a. If create is true, then a new, empty index will be created in d, replacing the index already there, if any.
Parameters:
d - the index directory
a - the analyzer to use
create - true to create the index or overwrite the existing one; false to append to the existing index
mfl - Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified via the MaxFieldLength constructor.
Throws:
CorruptIndexException - if the index is corrupt
LockObtainFailedException - if another writer has this index open (write.lock could not be obtained)
IOException - if the directory cannot be read/written to, or if it does not exist and create is false or if there is any other low-level IO error
这是什么问题呢?我们先看一下write.lock文件的作用:
write.lock用于防止对一个索引同时进行的修改。
IndexWriter打开的时候会获取一个write.lock,当IndexReader删除文档的时候也会获取,在它们关闭的时候会释放。
在lucene里,如果一个writer被打开了,没有关闭另一个再希望创建一个的话它会抛出异常。
我们上面的代码,是哪个地方在web应用中出现了问题了呢?
第26行首先我们new了一个对象,这个对象已经开了一个IndexWriter,在constructor里,因为我们是开了一个的。
然后我们再通过servlet调用这个create()方法的时候,还是需要new一个 IndexWriter,然后又开一个,这就矛盾了,问题出现了。也就是错误所在了。
所以正确的合理的代码应该是这样的:
1 package app;
2 /**
3 * @author wrh 2011/10/11
4 */
5 import java.io.File;
6 import java.io.FileFilter;
7 import java.io.FileReader;
8 import java.io.IOException;
9
10 import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
11 import org.apache.lucene.analysis.standard.StandardAnalyzer;
12 import org.apache.lucene.document.Document;
13 import org.apache.lucene.document.Field;
14 import org.apache.lucene.index.IndexWriter;
15 import org.apache.lucene.store.Directory;
16 import org.apache.lucene.store.FSDirectory;
17 import org.apache.lucene.util.Version;
18
19 public class Indexer1 {
20
21 private String indexDir = "";
22
23 public void create() throws Exception {
24
25 int numIndexed;
26 Indexer1 indexer = new Indexer1(indexDir);
27 System.out.println("Index begin");
28 try {
29 numIndexed = indexer.index(indexDir, new TextFilesFilter());
30 System.out.println(numIndexed);
31 } finally {
32 System.out.println("create index must go on");
33 }
34 }
35
36 //constructor
37 public Indexer1(String indexDir) throws IOException {
38 this.indexDir = indexDir;
39 }
40
41 public int index(String dataDir, FileFilter filter) throws Exception {
42 File[] files = new File(dataDir).listFiles();
43
44 Directory dir = FSDirectory.open(new File(indexDir));
45 IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED);
46
47 for (File f : files) {
48 if (!f.isDirectory() && !f.isHidden() && f.exists() && f.canRead() &&(filter == null || filter.accept(f))) {
49
50 System.out.println("Indexing .." + f.getCanonicalPath());
51
52 Document doc = getDocument(f);
53 writer.addDocument(doc);
54 }
55 }
56 writer.close();
57 System.out.println("Create index success");
58 return writer.numDocs();
59 }
60
61 //filter class
62 private static class TextFilesFilter implements FileFilter {
63 public boolean accept(File path) {
64 return path.getName().toLowerCase().endsWith(".txt");
65 }
66 }
67
68 //the contents of the index file
69 protected Document getDocument(File f) throws Exception {
70 Document doc = new Document();
71 doc.add(new Field("contents", new FileReader(f)));
72 doc.add(new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
73 doc.add(new Field("fullpath", f.getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
74 return doc;
75 }
76
77 }
这样不要在constructor里新建一个IndexWriter,在需要的地方建,这样就可以准确的实现功能了。
所以有的时候我们不得不考虑这些类加载过程中产生的问题与lucene本身的程序机理。
跟我走啊~~