Solr.IndexWriter源码分析.2

2021SC@SDUSC

/**
   * 返回只读阅读器,涵盖所有
   * 提交和未提交的对索引的更改。
   * 这提供了“近乎实时”的搜索,因为
   * 在 IndexWriter 会话期间所做的更改可以
   * 无需关闭即可快速搜索
   * 作者也不调用 {@link #commit}。
   *
   * <p>注意,这在功能上等同于调用
   * {#flush} 然后打开一个新的阅读器。但是这个周转时间
   * 方法应该更快,因为它避免了潜在的
   * 代价高昂的 {@link #commit}。</p>
   *
   * <p>您必须关闭返回的{@link IndexReader}
   * 用完这个方法。</p>
   *
   * <p>它<i>接近</i>实时,因为没有硬
   * 保证您能以多快的速度获得新读者
   * 使用 IndexWriter 进行更改。你必须
   * 在您的情况下进行实验,以确定它是否
   * 足够快。由于这是一个新的和实验性的
   * 功能,请报告您的发现,以便我们
   * 学习、改进和迭代。</p>
   *
   * <p>生成的阅读器支持{@link
   * DirectoryReader#openIfChanged},但该调用只会转发
   * 回到这个方法(虽然这可能会在
   * 未来)。</p>
   *
   * <p>第一次调用这个方法时,这个
   * writer 实例将尽一切努力汇集
   * 它打开进行合并的读者,申请
   * 删除等。这意味着额外的资源(RAM、
   * 文件描述符、CPU 时间)将被消耗。</p>
   *
   * <p>为了降低重新打开阅读器的延迟,您应该
   * 调用 {@link IndexWriterConfig#setMergedSegmentWarmer} 到
   * 在提交之前预热新合并的段
   * 到索引。这对于最小化很重要
   * 大型合并后的索引到搜索延迟。 </p>
   *
   * <p>如果 addIndexes* 调用正在另一个线程中运行,
   * 那么这个读者将只搜索这些片段
   * 复制成功的外部索引
   * 到此为止</p>。
   *
   * <p><b>注意</b>:一旦写入器关闭,任何
   * 优秀的读者可能会继续使用。然而,
   * 如果您尝试重新打开这些阅读器中的任何一个,您将
   * 遇到 {@link AlreadyClosedException}。</p>
   *
   * @lucene.experimental
   *
   * @return IndexReader 覆盖整个索引加上所有
   * 到目前为止此 IndexWriter 实例所做的更改
   *
   * @throws IOException 如果存在低级 I/O 错误
   */
   */
  DirectoryReader getReader(boolean applyAllDeletes, boolean writeAllDeletes) throws IOException {
   
   
    ensureOpen();

    if (writeAllDeletes && applyAllDeletes == false) {
   
   
      throw new IllegalArgumentException("applyAllDeletes must be true when writeAllDeletes=true");
    }

    final long tStart = System.currentTimeMillis();

    if (infoStream.isEnabled("IW")) {
   
   
      infoStream.message("IW", "flush at getReader");
    }

    // 在刷新之前预先执行此操作,以便读者
    // 在此刷新期间获得的第一次被合并
    // 这个方法被调用:
    readerPool.enableReaderPooling();
    StandardDirectoryReader r = null;
    doBeforeFlush();
    boolean anyChanges;
    final long maxFullFlushMergeWaitMillis = config.getMaxFullFlushMergeWaitMillis();
    /*
     * 要发布 NRT 阅读器,我们必须确保
     * DW 不会添加任何段或删除,直到我们
     * 完成创建 NRT DirectoryReader。
     * 我们在完成打开后释放两阶段全冲
     * 目录阅读器!
     */
    MergePolicy.MergeSpecification onGetReaderMerges = null;
    final AtomicBoolean stopCollectingMergedReaders = new AtomicBoolean(false);
    final Map<String, SegmentReader> mergedReaders = new HashMap<>();
    final Map<String, SegmentReader> openedReadOnlyClones = new HashMap<>();
    // 此函数用于控制打开哪些SR,以便对其进行跟踪
     // 并在我们在此 getReader 调用中等待合并的情况下重用它们。
    IOUtils.IOFunction<SegmentCommitInfo, SegmentReader> readerFactory = sci -> {
   
   
      final ReadersAndUpdates rld = getPooledInstance(sci, true);
      try {
   
   
        assert Thread.holdsLock(IndexWriter.this);
        SegmentReader segmentReader = rld.getReadOnlyClone(IOContext.READ);
        if (maxFullFlushMergeWaitMillis > 0) {
   
    // only track this if we actually do fullFlush merges
          openedReadOnlyClones.put(sci.info.name, segmentReader);
        }
        return segmentReader;
      } finally {
   
   
        release(rld);
      }
    };
    Closeable onGetReaderMergeResources = null;
    SegmentInfos openingSegmentInfos = null;
    boolean success2 = false;
    try {
   
   
      /*
       *这是 getReader 方法的基本部分。我们需要注意以下几点:
       * - 将所有当前内存中的 DWPT 刷新到磁盘
       * - 将所有删除和更新应用于新的和现有的 DWPT
       * - 防止对要应用的并发索引 DWPT 进行刷新和应用删除
       * - 在更新的 SIS 上打开 SDR
       *
       * 为了防止并发刷新,我们调用 DocumentsWriter#flushAllThreads 来交换 deleteQueue
       *(这会强制发生在此与随后的完全刷新之间的关系之前)并通知
       * FlushControl (#markForFullFlush()) 它应该防止任何新的 DWPT 刷新,直到我们\
       * 完成 (DocumentsWriter#finishFullFlush(boolean))。所有这些都由 fullFlushLock 保护以防止多个
       * 同时发生的完全刷新。一旦 DocWriter 启动了完全刷新,我们就可以顺序刷新
       * 并对写入的段应用删除和更新,而不必担心并发索引 DWPT。重要的
       * 方面是这一切都发生在 DocumentsWriter#flushAllThread() 和 DocumentsWriter#finishFullFlush(boolean) 之间
       * 因为一旦刷新被标记为完成,删除就开始应用于磁盘上的段,而不能保证
       * 打开 SDR 时,相应添加的文档(在更新情况下)会刷新并可见。
       */
      boolean success = false;
      synchronized (fullFlushLock) {
   
   
        try {
   
   
          // TODO: should we somehow make the seqNo available in the returned NRT reader?
          anyChanges = docWriter.flushAllThreads() < 0;
          if (anyChanges == false) {
   
   
            
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值