Lucene4.0选择段文件源码分析

lucene4.0中有两个文件保存了段的相关信息,分别是segments.gensegments_N.当打开一个索引文件的时候,首先要做的就是确定最后一次提交的段文件segments_N,然后再按照段来读取文档、词典等信息文件。下面直接开始。

1、从索引目录下的segments_N中选取N最大的,在从segments.gen中读取保存的最后提交的N,选择最大的作为结果

files = directory.listAll();

if (files != null) {
genA = getLastCommitGeneration(files);
}

从segments.gen中读取保存的最后提交的N,这个文件中N是保存了两遍的,可能就是为了防止有人随意修改吧,所以最后还有一个gen0==gen1的验证

long gen0 = genInput.readLong();
                long gen1 = genInput.readLong();
                if (infoStream != null) {
                  message("fallback check: " + gen0 + "; " + gen1);
                }
                if (gen0 == gen1) {
                  // The file is consistent.
                  genB = gen0;
                }
从genA和genB中挑出最大的

gen = Math.max(genA, genB);

构造段文件名,读取段文件,如果正常的话,到这里就结束了,但是有可能出现意外情况;所以lucene还有一些容错性的操作,可以做到尽可能的把当前的索引按照正确的读取出来

segmentFileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
                                                                "",
                                                                gen);
Object v = doBody(segmentFileName);

2、如果通过上边的操作没有读取到争取的段信息,那么lucene会自动尝试读取segmens_N-1文件

        if (useFirstMethod && lastGen == gen && retryCount >= 2) {  //第三次循环之后才会放弃使用第一种方法
          // Give up on first method -- this is 3rd cycle on
          // listing directory and checking gen file to
          // attempt to locate the segments file.
          useFirstMethod = false;
        }

        // Second method: since both directory cache and
        // file contents cache seem to be stale, just
        // advance the generation.
        if (!useFirstMethod) { // 4
          if (genLookaheadCount < defaultGenLookaheadCount) {
            gen++;
            genLookaheadCount++;
            if (infoStream != null) {
              message("look ahead increment gen to " + gen);
            }
          } else {
            // All attempts have failed -- throw first exc:
            throw exc;
          }
        } else if (lastGen == gen) { //2 3
          // This means we're about to try the same
          // segments_N last tried.
          retryCount++;
        } else { // 1
          // Segment file has advanced since our last loop
          // (we made "progress"), so reset retryCount:
          retryCount = 0;
        }

        lastGen = gen;

通过上边的代码可以知道,第一次循环之后,retryCount应该是0,如果没有成功的话,会进行第二次,第三次,也就是retryCount++操作,第四次开始执行 if (!useFirstMethod)这块;

第二次读取代码如下:

          if (gen > 1 && useFirstMethod && retryCount == 1) { // 第二次循环,N>1,尝试读取segments_N-1

            // This is our second time trying this same segments
            // file (because retryCount is 1), and, there is
            // possibly a segments_(N-1) (because gen > 1).
            // So, check if the segments_(N-1) exists and
            // try it if so:
            String prevSegmentFileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
                                                                               "",
                                                                               gen-1);

            final boolean prevExists;
            prevExists = directory.fileExists(prevSegmentFileName);

            if (prevExists) {
              if (infoStream != null) {
                message("fallback to prior segment file '" + prevSegmentFileName + "'");
              }
              try {
                Object v = doBody(prevSegmentFileName);
                if (infoStream != null) {
                  message("success on fallback " + prevSegmentFileName);
                }
                return v;
              } catch (IOException err2) {
                if (infoStream != null) {
                  message("secondary Exception on '" + prevSegmentFileName + "': " + err2 + "'; will retry");
                }
              }
            }
          }

3、如果通过segments_N-1还没有读取到正确的段信息呢,那么lucene还有一个判断,那就是N++,上边已经说了,从第四次循环开始,会开始执行

if (genLookaheadCount < defaultGenLookaheadCount) {
            gen++;
            genLookaheadCount++;
            if (infoStream != null) {
              message("look ahead increment gen to " + gen);
            }
          }

defaultGenLookaheadCount是一个全局变量,默认是10,也就是说,会对gen+1到gen+10之间的数做遍历,构造segments_N,看是否存在这样的段文件;如果一直到gen+10都没有找到正确的segments_N的话,就说明自定的索引不正确。

附加:senments.gen这个文件内容很简单的,一共包含三个数,分别是int,long,long,第一个int是索引文件格式版本,对应的lucene4.0的是-2;后边的两个long保存的最后一次提交的段文件名,senments_N,一般来说应该只有一个这样的文件




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值