blob: d56d614e7c2df7642338e7c21a306270d705665b [file] [log] [blame]
Index: src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentReader.java (revision 927380)
+++ src/java/org/apache/lucene/index/SegmentReader.java (working copy)
@@ -58,6 +58,9 @@
private boolean normsDirty = false;
private int pendingDeleteCount;
+ // The registered plugins
+ private Map<String, SegmentPlugin> plugins = new HashMap<String, SegmentPlugin>();
+
private boolean rollbackHasChanges = false;
private boolean rollbackDeletedDocsDirty = false;
private boolean rollbackNormsDirty = false;
@@ -290,6 +293,13 @@
}
/**
+ * Get a plugin by name.
+ */
+ public SegmentPlugin getPlugin(String name) {
+ return plugins.get(name);
+ }
+
+ /**
* Sets the initial value
*/
private class FieldsReaderLocal extends CloseableThreadLocal<FieldsReader> {
@@ -558,6 +568,14 @@
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
*/
+ public static SegmentReader get(boolean readOnly, SegmentInfo si, int termInfosIndexDivisor, Map<String, SegmentPluginFactory> plugins) throws CorruptIndexException, IOException {
+ return get(readOnly, si.dir, si, BufferedIndexInput.BUFFER_SIZE, true, termInfosIndexDivisor, plugins);
+ }
+
+ /**
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
public static SegmentReader get(boolean readOnly,
Directory dir,
SegmentInfo si,
@@ -565,6 +583,22 @@
boolean doOpenStores,
int termInfosIndexDivisor)
throws CorruptIndexException, IOException {
+ return get(readOnly, dir, si, readBufferSize, doOpenStores, termInfosIndexDivisor, null);
+ }
+
+
+ /**
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ public static SegmentReader get(boolean readOnly,
+ Directory dir,
+ SegmentInfo si,
+ int readBufferSize,
+ boolean doOpenStores,
+ int termInfosIndexDivisor,
+ Map<String, SegmentPluginFactory> plugins)
+ throws CorruptIndexException, IOException {
SegmentReader instance = readOnly ? new ReadOnlySegmentReader() : new SegmentReader();
instance.readOnly = readOnly;
instance.si = si;
@@ -579,6 +613,17 @@
}
instance.loadDeletedDocs();
instance.openNorms(instance.core.cfsDir, readBufferSize);
+
+ // Initialize plugins
+ if (plugins != null) {
+ for (Map.Entry<String, SegmentPluginFactory> entry : plugins.entrySet()) {
+ final SegmentPlugin plugin = entry.getValue().open(instance);
+ if (plugin != null) {
+ instance.plugins.put(entry.getKey(), plugin);
+ }
+ }
+ }
+
success = true;
} finally {
@@ -730,6 +775,14 @@
// any norms that have changed:
clone.openNorms(si.getUseCompoundFile() ? core.getCFSReader() : directory(), readBufferSize);
+ // Reopen plugins
+ for (Map.Entry<String, SegmentPlugin> entry : plugins.entrySet()) {
+ final SegmentPlugin plugin = entry.getValue().reopen(clone);
+ if (plugin != null) {
+ clone.plugins.put(entry.getKey(), entry.getValue().reopen(clone));
+ }
+ }
+
success = true;
} finally {
if (!success) {
@@ -795,6 +848,11 @@
if (core != null) {
core.decRef();
}
+
+ // Close the plugins
+ for (SegmentPlugin plugin : plugins.values()) {
+ plugin.close();
+ }
}
static boolean hasDeletions(SegmentInfo si) throws IOException {
Index: src/java/org/apache/lucene/index/ReadOnlyDirectoryReader.java
===================================================================
--- src/java/org/apache/lucene/index/ReadOnlyDirectoryReader.java (revision 927380)
+++ src/java/org/apache/lucene/index/ReadOnlyDirectoryReader.java (working copy)
@@ -23,13 +23,13 @@
import java.util.Map;
class ReadOnlyDirectoryReader extends DirectoryReader {
- ReadOnlyDirectoryReader(Directory directory, SegmentInfos sis, IndexDeletionPolicy deletionPolicy, int termInfosIndexDivisor) throws IOException {
- super(directory, sis, deletionPolicy, true, termInfosIndexDivisor);
+ ReadOnlyDirectoryReader(Directory directory, SegmentInfos sis, IndexDeletionPolicy deletionPolicy, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws IOException {
+ super(directory, sis, deletionPolicy, true, termInfosIndexDivisor, plugins);
}
ReadOnlyDirectoryReader(Directory directory, SegmentInfos infos, SegmentReader[] oldReaders, int[] oldStarts, Map<String,byte[]> oldNormsCache, boolean doClone,
- int termInfosIndexDivisor) throws IOException {
- super(directory, infos, oldReaders, oldStarts, oldNormsCache, true, doClone, termInfosIndexDivisor);
+ int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws IOException {
+ super(directory, infos, oldReaders, oldStarts, oldNormsCache, true, doClone, termInfosIndexDivisor, plugins);
}
ReadOnlyDirectoryReader(IndexWriter writer, SegmentInfos infos, int termInfosIndexDivisor) throws IOException {
Index: src/java/org/apache/lucene/index/SegmentPluginFactory.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentPluginFactory.java (revision 0)
+++ src/java/org/apache/lucene/index/SegmentPluginFactory.java (revision 0)
@@ -0,0 +1,15 @@
+package org.apache.lucene.index;
+
+import java.io.IOException;
+
+/**
+ * Factory for creating a plugin for SegmentReader.
+ */
+public abstract class SegmentPluginFactory {
+
+ /**
+ * Initialize a segment plugin for <code>reader</code>.
+ */
+ public abstract SegmentPlugin open(SegmentReader reader) throws IOException;
+
+}
\ No newline at end of file
Property changes on: src/java/org/apache/lucene/index/SegmentPluginFactory.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/java/org/apache/lucene/index/DirectoryReader.java
===================================================================
--- src/java/org/apache/lucene/index/DirectoryReader.java (revision 927380)
+++ src/java/org/apache/lucene/index/DirectoryReader.java (working copy)
@@ -63,25 +63,32 @@
private int maxDoc = 0;
private int numDocs = -1;
private boolean hasDeletions = false;
+ private Map<String, SegmentPluginFactory> plugins; // factory for initializing SegmentReaders
static IndexReader open(final Directory directory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit, final boolean readOnly,
final int termInfosIndexDivisor) throws CorruptIndexException, IOException {
+ return open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor, null);
+ }
+
+ static IndexReader open(final Directory directory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit, final boolean readOnly,
+ final int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws CorruptIndexException, IOException {
return (IndexReader) new SegmentInfos.FindSegmentsFile(directory) {
@Override
protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
SegmentInfos infos = new SegmentInfos();
infos.read(directory, segmentFileName);
if (readOnly)
- return new ReadOnlyDirectoryReader(directory, infos, deletionPolicy, termInfosIndexDivisor);
+ return new ReadOnlyDirectoryReader(directory, infos, deletionPolicy, termInfosIndexDivisor, plugins);
else
- return new DirectoryReader(directory, infos, deletionPolicy, false, termInfosIndexDivisor);
+ return new DirectoryReader(directory, infos, deletionPolicy, false, termInfosIndexDivisor, plugins);
}
}.run(commit);
}
/** Construct reading the named set of readers. */
- DirectoryReader(Directory directory, SegmentInfos sis, IndexDeletionPolicy deletionPolicy, boolean readOnly, int termInfosIndexDivisor) throws IOException {
+ DirectoryReader(Directory directory, SegmentInfos sis, IndexDeletionPolicy deletionPolicy, boolean readOnly, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws IOException {
this.directory = directory;
+ this.plugins = plugins;
this.readOnly = readOnly;
this.segmentInfos = sis;
this.deletionPolicy = deletionPolicy;
@@ -102,7 +109,7 @@
for (int i = sis.size()-1; i >= 0; i--) {
boolean success = false;
try {
- readers[i] = SegmentReader.get(readOnly, sis.info(i), termInfosIndexDivisor);
+ readers[i] = SegmentReader.get(readOnly, sis.info(i), termInfosIndexDivisor, plugins);
success = true;
} finally {
if (!success) {
@@ -125,6 +132,7 @@
DirectoryReader(IndexWriter writer, SegmentInfos infos, int termInfosIndexDivisor) throws IOException {
this.directory = writer.getDirectory();
this.readOnly = true;
+ this.plugins = writer.getSegmentPlugins();
this.segmentInfos = infos;
segmentInfosStart = (SegmentInfos) infos.clone();
this.termInfosIndexDivisor = termInfosIndexDivisor;
@@ -178,9 +186,10 @@
/** This constructor is only used for {@link #reopen()} */
DirectoryReader(Directory directory, SegmentInfos infos, SegmentReader[] oldReaders, int[] oldStarts,
- Map<String,byte[]> oldNormsCache, boolean readOnly, boolean doClone, int termInfosIndexDivisor) throws IOException {
+ Map<String,byte[]> oldNormsCache, boolean readOnly, boolean doClone, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws IOException {
this.directory = directory;
this.readOnly = readOnly;
+ this.plugins = plugins;
this.segmentInfos = infos;
this.termInfosIndexDivisor = termInfosIndexDivisor;
if (!readOnly) {
@@ -226,7 +235,7 @@
assert !doClone;
// this is a new reader; in case we hit an exception we can close it safely
- newReader = SegmentReader.get(readOnly, infos.info(i), termInfosIndexDivisor);
+ newReader = SegmentReader.get(readOnly, infos.info(i), termInfosIndexDivisor, plugins);
} else {
newReader = newReaders[i].reopenSegment(infos.info(i), doClone, readOnly);
}
@@ -438,9 +447,9 @@
private synchronized DirectoryReader doReopen(SegmentInfos infos, boolean doClone, boolean openReadOnly) throws CorruptIndexException, IOException {
DirectoryReader reader;
if (openReadOnly) {
- reader = new ReadOnlyDirectoryReader(directory, infos, subReaders, starts, normsCache, doClone, termInfosIndexDivisor);
+ reader = new ReadOnlyDirectoryReader(directory, infos, subReaders, starts, normsCache, doClone, termInfosIndexDivisor, plugins);
} else {
- reader = new DirectoryReader(directory, infos, subReaders, starts, normsCache, false, doClone, termInfosIndexDivisor);
+ reader = new DirectoryReader(directory, infos, subReaders, starts, normsCache, false, doClone, termInfosIndexDivisor, plugins);
}
return reader;
}
Index: src/java/org/apache/lucene/index/SegmentPlugin.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentPlugin.java (revision 0)
+++ src/java/org/apache/lucene/index/SegmentPlugin.java (revision 0)
@@ -0,0 +1,24 @@
+package org.apache.lucene.index;
+
+import java.io.IOException;
+
+/**
+ * Base class for plugins for SegmentReader.
+ */
+public abstract class SegmentPlugin {
+
+
+ /**
+ * Reopen this SegmentPlugin for <code>newReader</code>.
+ */
+ public abstract SegmentPlugin reopen(SegmentReader newReader) throws IOException;
+
+
+ /**
+ * Close this SegmentPlugin.
+ */
+ public abstract void close() throws IOException;
+
+
+}
+
Property changes on: src/java/org/apache/lucene/index/SegmentPlugin.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/IndexReader.java (revision 927380)
+++ src/java/org/apache/lucene/index/IndexReader.java (working copy)
@@ -263,6 +263,36 @@
}
/** Expert: returns an IndexReader reading the index in
+ * the given Directory, with a custom {@link
+ * IndexDeletionPolicy}. You should pass readOnly=true,
+ * since it gives much better concurrent performance,
+ * unless you intend to do write operations (delete
+ * documents or change norms) with the reader.
+ * @param directory the index directory
+ * @param deletionPolicy a custom deletion policy (only used
+ * if you use this reader to perform deletes or to set
+ * norms); see {@link IndexWriter} for details.
+ * @param readOnly true if no changes (deletions, norms) will be made with this IndexReader
+ * @param termInfosIndexDivisor Subsamples which indexed
+ * terms are loaded into RAM. This has the same effect as {@link
+ * IndexWriter#setTermIndexInterval} except that setting
+ * must be done at indexing time while this setting can be
+ * set per reader. When set to N, then one in every
+ * N*termIndexInterval terms in the index is loaded into
+ * memory. By setting this to a value > 1 you can reduce
+ * memory usage, at the expense of higher latency when
+ * loading a TermInfo. The default value is 1. Set this
+ * to -1 to skip loading the terms index entirely.
+ * @param plugins map of plugins to initialize for SegmentReaders
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ public static IndexReader open(final Directory directory, IndexDeletionPolicy deletionPolicy, boolean readOnly, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws CorruptIndexException, IOException {
+ return open(directory, deletionPolicy, null, readOnly, termInfosIndexDivisor, plugins);
+ }
+
+
+ /** Expert: returns an IndexReader reading the index in
* the given Directory, using a specific commit and with
* a custom {@link IndexDeletionPolicy}. You should pass
* readOnly=true, since it gives much better concurrent
@@ -312,10 +342,46 @@
return open(commit.getDirectory(), deletionPolicy, commit, readOnly, termInfosIndexDivisor);
}
+ /** Expert: returns an IndexReader reading the index in
+ * the given Directory, using a specific commit and with
+ * a custom {@link IndexDeletionPolicy}. You should pass
+ * readOnly=true, since it gives much better concurrent
+ * performance, unless you intend to do write operations
+ * (delete documents or change norms) with the reader.
+ * @param commit the specific {@link IndexCommit} to open;
+ * see {@link IndexReader#listCommits} to list all commits
+ * in a directory
+ * @param deletionPolicy a custom deletion policy (only used
+ * if you use this reader to perform deletes or to set
+ * norms); see {@link IndexWriter} for details.
+ * @param readOnly true if no changes (deletions, norms) will be made with this IndexReader
+ * @param termInfosIndexDivisor Subsamples which indexed
+ * terms are loaded into RAM. This has the same effect as {@link
+ * IndexWriter#setTermIndexInterval} except that setting
+ * must be done at indexing time while this setting can be
+ * set per reader. When set to N, then one in every
+ * N*termIndexInterval terms in the index is loaded into
+ * memory. By setting this to a value > 1 you can reduce
+ * memory usage, at the expense of higher latency when
+ * loading a TermInfo. The default value is 1. Set this
+ * to -1 to skip loading the terms index entirely.
+ * @param plugins map of plugins to initialize for segments
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ public static IndexReader open(final IndexCommit commit, IndexDeletionPolicy deletionPolicy, boolean readOnly, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws CorruptIndexException, IOException {
+ return open(commit.getDirectory(), deletionPolicy, commit, readOnly, termInfosIndexDivisor, plugins);
+ }
+
+
private static IndexReader open(final Directory directory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit, final boolean readOnly, int termInfosIndexDivisor) throws CorruptIndexException, IOException {
- return DirectoryReader.open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor);
+ return DirectoryReader.open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor, null);
}
+ private static IndexReader open(final Directory directory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit, final boolean readOnly, int termInfosIndexDivisor, final Map<String, SegmentPluginFactory> plugins) throws CorruptIndexException, IOException {
+ return DirectoryReader.open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor, plugins);
+ }
+
/**
* Refreshes an IndexReader if the index has changed since this instance
* was (re)opened.
Index: src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- src/java/org/apache/lucene/index/IndexWriter.java (revision 927380)
+++ src/java/org/apache/lucene/index/IndexWriter.java (working copy)
@@ -265,6 +265,7 @@
private DocumentsWriter docWriter;
private IndexFileDeleter deleter;
+ private Map<String, SegmentPluginFactory> segmentPlugins = java.util.Collections.emptyMap();
private Set<SegmentInfo> segmentsToOptimize = new HashSet<SegmentInfo>(); // used by optimize to note those needing optimization
@@ -606,7 +607,7 @@
// TODO: we may want to avoid doing this while
// synchronized
// Returns a ref, which we xfer to readerMap:
- sr = SegmentReader.get(false, info.dir, info, readBufferSize, doOpenStores, termsIndexDivisor);
+ sr = SegmentReader.get(false, info.dir, info, readBufferSize, doOpenStores, termsIndexDivisor, segmentPlugins);
readerMap.put(info, sr);
} else {
if (doOpenStores) {
@@ -4850,6 +4851,21 @@
return mergedSegmentWarmer;
}
+ /**
+ * Set the plugins to initialize for a newly opened segment.
+ */
+ public void setSegmentPlugins(Map<String, SegmentPluginFactory> plugins) {
+ segmentPlugins = plugins;
+ }
+
+ /**
+ * Get the plugins for newly opened segments
+ */
+ public Map<String, SegmentPluginFactory> getSegmentPlugins() {
+ return segmentPlugins;
+ }
+
+
private void handleOOM(OutOfMemoryError oom, String location) {
if (infoStream != null) {
message("hit OutOfMemoryError inside " + location);