📄 directoryindexreader.java
字号:
package org.apache.lucene.index;/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import java.io.IOException;import org.apache.lucene.store.Directory;import org.apache.lucene.store.Lock;import org.apache.lucene.store.LockObtainFailedException;/** * IndexReader implementation that has access to a Directory. * Instances that have a SegmentInfos object (i. e. segmentInfos != null) * "own" the directory, which means that they try to acquire a write lock * whenever index modifications are performed. */abstract class DirectoryIndexReader extends IndexReader { protected Directory directory; protected boolean closeDirectory; private IndexDeletionPolicy deletionPolicy; private SegmentInfos segmentInfos; private Lock writeLock; private boolean stale; /** Used by commit() to record pre-commit state in case * rollback is necessary */ private boolean rollbackHasChanges; private SegmentInfos rollbackSegmentInfos; void init(Directory directory, SegmentInfos segmentInfos, boolean closeDirectory) { this.directory = directory; this.segmentInfos = segmentInfos; this.closeDirectory = closeDirectory; } protected DirectoryIndexReader() {} DirectoryIndexReader(Directory directory, SegmentInfos segmentInfos, boolean closeDirectory) { super(); init(directory, segmentInfos, closeDirectory); } static DirectoryIndexReader open(final Directory directory, final boolean closeDirectory, final IndexDeletionPolicy deletionPolicy) throws CorruptIndexException, IOException { return (DirectoryIndexReader) new SegmentInfos.FindSegmentsFile(directory) { protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException { SegmentInfos infos = new SegmentInfos(); infos.read(directory, segmentFileName); DirectoryIndexReader reader; if (infos.size() == 1) { // index is optimized reader = SegmentReader.get(infos, infos.info(0), closeDirectory); } else { reader = new MultiSegmentReader(directory, infos, closeDirectory); } reader.setDeletionPolicy(deletionPolicy); return reader; } }.run(); } public final synchronized IndexReader reopen() throws CorruptIndexException, IOException { ensureOpen(); if (this.hasChanges || this.isCurrent()) { // the index hasn't changed - nothing to do here return this; } return (DirectoryIndexReader) new SegmentInfos.FindSegmentsFile(directory) { protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException { SegmentInfos infos = new SegmentInfos(); infos.read(directory, segmentFileName); DirectoryIndexReader newReader = doReopen(infos); if (DirectoryIndexReader.this != newReader) { newReader.init(directory, infos, closeDirectory); newReader.deletionPolicy = deletionPolicy; } return newReader; } }.run(); } /** * Re-opens the index using the passed-in SegmentInfos */ protected abstract DirectoryIndexReader doReopen(SegmentInfos infos) throws CorruptIndexException, IOException; public void setDeletionPolicy(IndexDeletionPolicy deletionPolicy) { this.deletionPolicy = deletionPolicy; } /** Returns the directory this index resides in. */ public Directory directory() { ensureOpen(); return directory; } /** * Version number when this IndexReader was opened. */ public long getVersion() { ensureOpen(); return segmentInfos.getVersion(); } /** * Check whether this IndexReader is still using the * current (i.e., most recently committed) version of the * index. If a writer has committed any changes to the * index since this reader was opened, this will return * <code>false</code>, in which case you must open a new * IndexReader in order to see the changes. See the * description of the <a href="IndexWriter.html#autoCommit"><code>autoCommit</code></a> * flag which controls when the {@link IndexWriter} * actually commits changes to the index. * * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error */ public boolean isCurrent() throws CorruptIndexException, IOException { ensureOpen(); return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion(); } /** * Checks is the index is optimized (if it has a single segment and no deletions) * @return <code>true</code> if the index is optimized; <code>false</code> otherwise */ public boolean isOptimized() { ensureOpen(); return segmentInfos.size() == 1 && hasDeletions() == false; } protected void doClose() throws IOException { if(closeDirectory) directory.close(); } /** * Commit changes resulting from delete, undeleteAll, or * setNorm operations * * If an exception is hit, then either no changes or all * changes will have been committed to the index * (transactional semantics). * @throws IOException if there is a low-level IO error */ protected void doCommit() throws IOException { if(hasChanges){ if (segmentInfos != null) { // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: IndexFileDeleter deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, null, null); // Checkpoint the state we are about to change, in // case we have to roll back: startCommit(); boolean success = false; try { commitChanges(); segmentInfos.write(directory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): rollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.checkpoint(segmentInfos, true); if (writeLock != null) { writeLock.release(); // release write lock writeLock = null; } } else commitChanges(); } hasChanges = false; } protected abstract void commitChanges() throws IOException; /** * Tries to acquire the WriteLock on this directory. * this method is only valid if this IndexReader is directory owner. * * @throws StaleReaderException if the index has changed * since this reader was opened * @throws CorruptIndexException if the index is corrupt * @throws LockObtainFailedException if another writer * has this index open (<code>write.lock</code> could not * be obtained) * @throws IOException if there is a low-level IO error */ protected void acquireWriteLock() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { if (segmentInfos != null) { ensureOpen(); if (stale) throw new StaleReaderException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); if (writeLock == null) { Lock writeLock = directory.makeLock(IndexWriter.WRITE_LOCK_NAME); if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT)) // obtain write lock throw new LockObtainFailedException("Index locked for write: " + writeLock); this.writeLock = writeLock; // we have to check whether index has changed since this reader was opened. // if so, this reader is no longer valid for deletion if (SegmentInfos.readCurrentVersion(directory) > segmentInfos.getVersion()) { stale = true; this.writeLock.release(); this.writeLock = null; throw new StaleReaderException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); } } } } /** * Should internally checkpoint state that will change * during commit so that we can rollback if necessary. */ void startCommit() { if (segmentInfos != null) { rollbackSegmentInfos = (SegmentInfos) segmentInfos.clone(); } rollbackHasChanges = hasChanges; } /** * Rolls back state to just before the commit (this is * called by commit() if there is some exception while * committing). */ void rollbackCommit() { if (segmentInfos != null) { for(int i=0;i<segmentInfos.size();i++) { // Rollback each segmentInfo. Because the // SegmentReader holds a reference to the // SegmentInfo we can't [easily] just replace // segmentInfos, so we reset it in place instead: segmentInfos.info(i).reset(rollbackSegmentInfos.info(i)); } rollbackSegmentInfos = null; } hasChanges = rollbackHasChanges; } /** Release the write lock, if needed. */ protected void finalize() throws Throwable { try { if (writeLock != null) { writeLock.release(); // release write lock writeLock = null; } } finally { super.finalize(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -