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) {

最低0.47元/天 解锁文章
2559

被折叠的 条评论
为什么被折叠?



