Index: contrib/splitindex/src/java/org/apache/lucene/index/MirroringSplitPolicy.java =================================================================== --- contrib/splitindex/src/java/org/apache/lucene/index/MirroringSplitPolicy.java (revision 0) +++ contrib/splitindex/src/java/org/apache/lucene/index/MirroringSplitPolicy.java (revision 0) @@ -0,0 +1,135 @@ +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 java.io.Serializable; +import java.util.Map; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.store.Directory; + +/** + * The MirroringSplitPolicy builds on the + * {@link RemotingSplitPolicy}, and treats each sub-index as a mirror of the + * super-index (upon which the {@link SplitWriter} is built). + * + * @author Karthick Sankarachary + */ +public class MirroringSplitPolicy extends RemotingSplitPolicy implements + SplitPolicy { + + /** + * Construct a mirroring split policy with the given options. + * + * @param options + * the configuration options for this policy + */ + public MirroringSplitPolicy(Map options) { + super(options); + } + + /** + * When an index reader is obtained from the split writer (using one of its + * {@link SplitWriter#getReader} methods), then return a + * {@link ParallelReader} based on each of the sub-index and (optionally) the + * super-index. + * + * @param reader + * the split reader that would normally've been returned + * @return a vote that contains the parallel reader that will actually be + * returned + */ + @Override + public SplitVote onGetReader(SplitReader reader) + throws CorruptIndexException, IOException { + final ParallelReader parallelReader = new ParallelReader(); + try { + for (IndexReader subReader : reader.getSequentialSubReaders()) { + parallelReader.add(subReader); + } + if (includeSuper) { + parallelReader.add(writer.getSuperReader()); + } + } catch (Exception e) { + System.out + .println("Could not create parallel reader for mirroring split index (" + + e.getMessage() + ")"); + } + return new SplitVote() { + public Object getReturnValue() { + return parallelReader; + }; + }; + } + + /** + * When a document is added to the split writer, add it to each of of the + * sub-indices as well. + * + * @param document + * the document being added + * @param analyzer + * the analyzer to use + * @return a vote that tells the split writer to carry on as usual + */ + @Override + public SplitVote onAddDocument(Document document, Analyzer analyzer) + throws CorruptIndexException, IOException { + for (IndexWriter subWriter : subWriters.values()) { + subWriter.addDocument(document, analyzer); + } + return super.onAddDocument(document, analyzer); + } + + /** + * When an index is added to the split writer, add it to each of of the + * sub-indices as well. + * + * @param readers + * the list of readers being added + * @return a vote that tells the split writer to carry on as usual + */ + @Override + public SplitVote onAddIndexes(IndexReader... readers) + throws CorruptIndexException, IOException { + for (IndexWriter subWriter : subWriters.values()) { + subWriter.addIndexes(readers); + } + return super.onAddIndexes(readers); + } + + /** + * When an index is added to the split writer, add it to each of of the + * sub-indices as well. + * + * @param directories + * the list of directories being added + * @return a vote that tells the split writer to carry on as usual + */ + @Override + public SplitVote onAddIndexesNoOptimize(Directory[] directories) + throws CorruptIndexException, IOException { + for (IndexWriter subWriter : subWriters.values()) { + subWriter.addIndexesNoOptimize(directories); + } + return super.onAddIndexesNoOptimize(directories); + } + +} Index: contrib/splitindex/src/test/org/apache/lucene/index/TestMirroringSplitPolicy.java =================================================================== --- contrib/splitindex/src/test/org/apache/lucene/index/TestMirroringSplitPolicy.java (revision 0) +++ contrib/splitindex/src/test/org/apache/lucene/index/TestMirroringSplitPolicy.java (revision 0) @@ -0,0 +1,40 @@ +package org.apache.lucene.index; + +import org.apache.lucene.search.IndexSearcher; + +/** + * Test cases for the {@link MirroringSplitPolicy}. + */ +public class TestMirroringSplitPolicy extends TestRemotingSplitPolicy { + + /** + * Indicate that we're testing the mirroring split policy. + */ + @Override + protected Class getSplitPolicyClass() { + return MirroringSplitPolicy.class; + } + + /** + * Verify that each of the mirrors has a copy of the initial term written into + * the writer. + * + * @throws Exception + */ + public void testReadFromMirror() throws Exception { + ParallelReader splitReader = (ParallelReader) getPrimaryReader(); + for (IndexReader subReader : splitReader.getSubReaders()) { + assertHits(1, new Term("name1", "value1"), new IndexSearcher(subReader)); + } + } + + /** + * Verify that the split reader returns only one hit for the initial term, + * despite the fact that each of the mirrors have a copy. + * + * @throws Exception + */ + public void testReadFromSplitReader() throws Exception { + assertHits(1, new Term("name1", "value1"), getPrimarySearcher()); + } +}