lucene 源码小析

转:http://zbszone.iteye.com/admin/blogs/622232

 

lucene3.0 

源代码流程:   index 
IndexWriter: 
1, setMessageID:  基本没用 
2, DocumentWriter: 写多个document的writer。 
3, directory.clearLock        NativeFSLockFactory     
(其中Directory的生成根据系统 
if (Constants.WINDOWS) { 
      return new SimpleFSDirectory(path, lockFactory); 
    } else { 
      return new NIOFSDirectory(path, lockFactory); 
    } 
) 

4, Lock writeLock = directory.makeLock   (NativeFSLockFactory来完成clearlock和getlock) 
5, writeLock.obtain(writeLockTimeout)     也就是说我觉得以上工作都只是init一个lock,但是并没有去obtain 

6, if create is true:        以下读取的应该是原有的directory中的index 
7, Segmentinfo seg = new Segmentinfos(); 
8, clear();         把以前的segment clear 
9, checksum;   应该是核查文件的正确性 
10, lastgeneration = generation = generationFromSegmentFileName(String filename);    generation是个int 
11, int format = input.readInt();   格式都是负数,至于保存在哪个文件中,目前还未知,应该是Segments那个 
if(format < 0){     // file contains explicit format info 
        // check that it is a format we can understand 
        if (format < CURRENT_FORMAT) 
          throw new CorruptIndexException("Unknown format version: " + format); 
        version = input.readLong(); // read version 
        counter = input.readInt(); // read counter 
      } 
      else{     // file is in old format without explicit format info 
        counter = format; 
      } 

if(format >= 0){    // in old format the version number may be at the end of the file 
        if (input.getFilePointer() >= input.length()) 
          version = System.currentTimeMillis(); // old file format without version number 
        else 
          version = input.readLong(); // read version 
      } 

12,segmentInfos.clear();      应该是读取之前存在的directory之后执行的clear()操作 
13,deleter = new IndexFileDeleter 
14,pushMaxBufferedDocs();       这个似乎只是让LogDocMergePolicy设置一个minMergeSize 
final MergePolicy mp = mergePolicy; 
LogDocMergePolicy lmp = (LogDocMergePolicy) mp;
lmp.setMinMergeDocs(maxBufferedDocs);

addDocument: 
1, DocumentsWriter: 
# 得到一个线程,在lucene2.3之后,DocumentWriter多线程写document 
final DocumentsWriterThreadState state = getThreadState(doc, delTerm); 
state.consumer.processDocument(); 
processDocument方法里面 startDocument              好像没有什么用 

重要: 
init:  DocFieldProcessorPerThread extends DocConsumerPerThread 
DocFieldProcessorPerField       单独的class 
DocFieldConsumersPerThread extends DocFieldConsumerPerThread 
DocInverterPerThread extends DocFieldConsumerPerThread 
DocFieldConsumersPerField extends DocFieldConsumerPerField 
DocInverterPerField extends DocFieldConsumerPerField 
调用过程: 
DocFieldProcessorPerThread 调用DocFieldConsumerPerThread 作为自己的consumer 
然后调用DocFieldProcessorPerField 处理每一个Field的hash和QuictSort 
然后调用每一个Field的Consumer,也就最终是DocInverterPerField 的processFields方法 

2, finishDocument(state, perDoc);        完成后续工作,具体内容没完全看完。 
其中第一步进行   balanceRam    系统中有3块内存,posting table, byte blocks, char blocks. 应该是调节3者的平衡,因为一个document如果分词太多,可能占据了posting 的绝大部分。 
3, flush(boolean triggerMerge, boolean flushDocStores, boolean flushDeletes);      
ensureOpen(false) 
doFlush() doFlushInternal    做了很多flush、delete、写混合index等工作,还有flush后处理工作以及checkpoint(); 
docwriter.clearFlushPending 
maybeMerge() 
updatePendingMerges              做一个merge前准备工作 
mergeScheduler.merge(this);   this表示DocumentsWriter 


optimize               没有仔细看,主要工作就是merge 
如文档所说,optimize(boolean doWait)      : you can specify whether the call should block until the optimize completes          应该指的是在optimize完成之前,整个indexwriter的call被block了。 
代码: 
if (doWait) 
      synchronized(this) 

close 
从文档看因为lock的原因,如果在close过程中发生Exception,即使是在flush部分后发生Exception,也一样会保证原disk上的index不变 
另外,从eg看writer.close()都只是放在try中,而没有放在finally中 


IndexReader.deleteDocument(int doc)/deleteDocuments(Term term) 
本质调用doDelete() 
DirectoryReader.doDelete()      调用subReader,也就是segmentReader 
SegmentReader.doDelete()      
     deletedDocs.getAndSet(docNum)    实际上在deleteDocs这个BitVector中添加要删除的docNum 
和IndexWriter一样,close的时候会提交一个commit,commit的工作很多,包括减少本身(IndexReader)引用,用IndexFileDeleter删除需要删除的文件等等。pending的工作,正好和上面的doDelete符合,上面的doDelete删除的时候,如果失败,就会添加到pending中。 

重要: 
这里有一个结构很不错: 例子中IndexReader实际上是DirectoryReader,通过以下方法调用SegmentReader。这种自身不同类别调用,方法得到重用,结构清晰。 
for (int i = 0; i < subReaders.length; i++) 
        subReaders[i].commit();        subReader即segmentReader 

另外,整个lucene中用了很多checkpoint机制,例如startCommit()即开始一个checkpoint。这样一旦出错,可以rollback.   例如在IndexReader.close的时候,DirectoryReader.commit --> startCommit --> segmentReader(startCommit) -->  segmentReader.commit --> if (!success) rollbackCommit --> segmentReader.rollbackCommit 




Deleter: 
几个重要的方法: 
1, deleter.checkpoint 
2, deleter.close 
3, deleter.refresh

posted on 2013-06-03 09:17  Bo.Zhang  阅读(276)  评论(0)    收藏  举报