文档提交之flush(六)

  本文承接文档提交之flush(五),继续依次介绍每一个流程点。

文档提交之flush的整体流程图

图1:

强制发布生成的段

图2:

  文档提交之flush(五)中我们还剩余发布FlushedSegment发布FlushedSegment两个流程点未介绍。

发布FlushedSegment的流程图

  图3的流程图描述的是一个FlushTicket执行发布FlushedSegment流程所涉及的处理过程。

图3:

处理全局删除信息

图4:

  首先给出FlushTicket类,类中包含的主要变量如下:

  从前面的文章(见文档提交之flush(二))中我们了解到,不是每一个FlushTicket都有全局删除信息,即FrozenBufferedUpdates可能为null。如果不为空,我们首先要获得一个nextGen。

  nextGen有什么作用

  由于根据nextGen能保证正确的处理删除信息,所以真正的从别的段中处理删除信息的操作,即处理删除信息,就可以作为一个事件添加到eventQueue(见文档提交之flush(四)),使得可以多线程并发执行,在下篇文章中我们将会了解到,处理删除信息的过程是开销较大的工作。

处理段内的删除信息

图5:

  文档提交之flush(四)中我们简单介绍了FlushTicket 中的FlushedSegment中包含的几个信息,至少包含了一个DWPT处理的文档对应的索引信息(SegmentCommitInfo)、段中被删除的文档信息(FixedBitSet对象)、未处理的删除信息FrozenBufferedUpdates(见文档提交之flush(三))、Sorter.DocMap对象,以上内容在文档提交之flush(三)的文章中已介绍。在当前流程点,FlushedSegment中的FrozenBufferedUpdates(非FlushTicket中的FrozenBufferedUpdates)中包含了段内的删除信息。

  另外,在文档提交之flush(三)中我们介绍了,在生成索引文件的过程中,我们只处理了部分满足删除信息(见下文处理丢弃的段的介绍)的文档,到此流程点,我们需要处理剩余的删除信息。

  无论当前FlushTicket中是否还有段内删除信息,当前段都需要获得一个nextGen,之后任何大于nextGen值的删除信息都需要作用到当前段。

将当前段的SegmentCommitInfo添加到SegmentInfos中

图6:

  将FlushedSegment中的SegmentCommitInfo,即索引信息添加到SegmentInfos中。SegmentInfos即所有段的索引信息的集合, 在commit( )阶段,SegmentInfos中的信息对应生成Segment_N的索引文件。

处理丢弃的段

图7:

  如果当前段中的文档的总个数maxDoc与被标记为删除的(deleted)文档的个数相同,那么该段需要被丢弃,判断条件如下:

  从上文介绍中我们知道,当前段的SegmentCommitInfo已经被添加到SegmentInfos中,由于段的合并跟flush是异步操作,故运行到此流程点时,当前段可能正在执行段的合并。如果正在合并当前段,那么就不处理,在合并结束后,会自动丢弃该段,否则将此段对应SegmentCommitInfo从SegmentInfos中移除。

执行flush后的工作

图8:

  同图1中的执行flush前的工作的流程点,Lucene在此流程点预留了一个钩子函数(hook function),使用者可以实现在此实现自己的方法。

结束

  至此,强制发布生成的段中的发布FlushedSegment流程介绍结束,另外发布FrozenBufferedUpdates的流程逻辑即上文中的处理全局删除信息

IndexWriter处理事件

  在执行该流程之前,需要先执行下面的几个收尾工作,即执行源码中DocumentsWriterFlushControl.finishFullFlush( )的方法:

  上面的收尾工作结束后,接着还需要尝试处理newQueue中的删除信息。

  为什么此时需要尝试处理newQueue中的删除信息

  为什么此时能尝试处理newQueue中的删除信息

  执行完收尾工作后,当前线程从eventQueue队列中逐个取出所有的事件,即执行事件对应的函数调用,关于事件的概念见文档提交之flush(四)

  总结前几篇文章中的内容,eventQueue中包含以下几种事件类型:

结语

  在下篇文章中,将会介绍图1中剩下的几个流程点以及发布生成的段中生成的处理删除信息事件的逻辑。

点击下载附件