SOLR-243: Add configurable IndexReaderFactory so that alternate IndexReader implementations can be specified via solrconfig.xml.

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@782660 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Robert Miller 2009-06-08 14:56:31 +00:00
parent 5f02ccf9ec
commit 0502d82893
9 changed files with 221 additions and 19 deletions

View File

@ -235,6 +235,9 @@ New Features
59. SOLR-1189: Support providing username and password for basic HTTP authentication in Java replication 59. SOLR-1189: Support providing username and password for basic HTTP authentication in Java replication
(Matthew Gregg, shalin) (Matthew Gregg, shalin)
60. SOLR-243: Add configurable IndexReaderFactory so that alternate IndexReader implementations
can be specified via solrconfig.xml. (Andrzej Bialecki, hossman, Mark Miller, John Wang)
Optimizations Optimizations
---------------------- ----------------------
1. SOLR-374: Use IndexReader.reopen to save resources by re-using parts of the 1. SOLR-374: Use IndexReader.reopen to save resources by re-using parts of the

View File

@ -436,6 +436,13 @@
<copyField source="features" dest="text"/> <copyField source="features" dest="text"/>
<copyField source="includes" dest="text"/> <copyField source="includes" dest="text"/>
<!-- Above, multiple specific fields are copied to the [text] field.
Another option is to use the dynamic field syntax. A maxChars to
copy setting is also available. -->
<!-- <copyField source="*" dest="text" maxChars="3000"/> -->
<copyField source="manu" dest="manu_exact"/> <copyField source="manu" dest="manu_exact"/>
<copyField source="name" dest="spell"/> <copyField source="name" dest="spell"/>

View File

@ -206,6 +206,13 @@
</updateHandler> </updateHandler>
<!-- Use the following format to specify a custom IndexReaderFactory - allows for alternate
IndexReader implementations.
<indexReaderFactory name="IndexReaderFactory" class="package.class">
Parameters as required by the implementation
</indexReaderFactory >
-->
<query> <query>
<!-- Maximum number of clauses in a boolean query... can affect <!-- Maximum number of clauses in a boolean query... can affect

View File

@ -0,0 +1,51 @@
package org.apache.solr.core;
/**
* 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.index.IndexReader;
import org.apache.lucene.store.Directory;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
/**
* Factory used to build a new IndexReader instance.
*/
public abstract class IndexReaderFactory implements NamedListInitializedPlugin {
/**
* <code>init</code> will be called just once, immediately after creation.
* <p>
* The args are user-level initialization parameters that may be specified
* when declaring an indexReaderFactory in solrconfig.xml
*/
public void init(NamedList args) {
/* :NOOP: */
}
/**
* Creates a new IndexReader instance using the given Directory.
*
* @param indexDir indexDir index location
* @param readOnly return readOnly IndexReader
* @return An IndexReader instance
* @throws IOException
*/
public abstract IndexReader newReader(Directory indexDir, boolean readOnly)
throws IOException;
}

View File

@ -97,6 +97,7 @@ public final class SolrCore implements SolrInfoMBean {
private final Map<String, SolrInfoMBean> infoRegistry; private final Map<String, SolrInfoMBean> infoRegistry;
private IndexDeletionPolicyWrapper solrDelPolicy; private IndexDeletionPolicyWrapper solrDelPolicy;
private DirectoryFactory directoryFactory; private DirectoryFactory directoryFactory;
private IndexReaderFactory indexReaderFactory;
public long getStartTime() { return startTime; } public long getStartTime() { return startTime; }
@ -223,6 +224,10 @@ public final class SolrCore implements SolrInfoMBean {
return directoryFactory; return directoryFactory;
} }
public IndexReaderFactory getIndexReaderFactory() {
return indexReaderFactory;
}
public String getName() { public String getName() {
return name; return name;
} }
@ -341,6 +346,24 @@ public final class SolrCore implements SolrInfoMBean {
directoryFactory = dirFactory; directoryFactory = dirFactory;
} }
private void initIndexReaderFactory() {
String xpath = "indexReaderFactory";
Node node = (Node) solrConfig.evaluate(xpath, XPathConstants.NODE);
IndexReaderFactory indexReaderFactory;
if (node != null) {
Map<String, IndexReaderFactory> registry = new HashMap<String, IndexReaderFactory>();
NamedListPluginLoader<IndexReaderFactory> indexReaderFactoryLoader = new NamedListPluginLoader<IndexReaderFactory>(
"[solrconfig.xml] " + xpath, registry);
indexReaderFactory = indexReaderFactoryLoader.loadSingle(solrConfig
.getResourceLoader(), node);
} else {
indexReaderFactory = new StandardIndexReaderFactory();
}
this.indexReaderFactory = indexReaderFactory;
}
// protect via synchronized(SolrCore.class) // protect via synchronized(SolrCore.class)
private static Set<String> dirs = new HashSet<String>(); private static Set<String> dirs = new HashSet<String>();
@ -355,6 +378,7 @@ public final class SolrCore implements SolrInfoMBean {
boolean removeLocks = solrConfig.unlockOnStartup; boolean removeLocks = solrConfig.unlockOnStartup;
initDirectoryFactory(); initDirectoryFactory();
initIndexReaderFactory();
if (indexExists && firstTime && removeLocks) { if (indexExists && firstTime && removeLocks) {
// to remove locks, the directory must already exist... so we create it // to remove locks, the directory must already exist... so we create it
@ -1048,9 +1072,12 @@ public final class SolrCore implements SolrInfoMBean {
try { try {
newestSearcher = getNewestSearcher(false); newestSearcher = getNewestSearcher(false);
String newIndexDir = getNewIndexDir(); String newIndexDir = getNewIndexDir();
if (newestSearcher != null) { File indexDirFile = new File(getIndexDir()).getCanonicalFile();
File newIndexDirFile = new File(newIndexDir).getCanonicalFile();
if (newestSearcher != null && solrConfig.reopenReaders
&& indexDirFile.equals(newIndexDirFile)) {
IndexReader currentReader = newestSearcher.get().getReader(); IndexReader currentReader = newestSearcher.get().getReader();
if(solrConfig.reopenReaders && new File(getIndexDir()).getCanonicalFile().equals(new File(newIndexDir).getCanonicalFile())) {
IndexReader newReader = currentReader.reopen(); IndexReader newReader = currentReader.reopen();
if (newReader == currentReader) { if (newReader == currentReader) {
@ -1059,10 +1086,8 @@ public final class SolrCore implements SolrInfoMBean {
tmp = new SolrIndexSearcher(this, schema, "main", newReader, true, true); tmp = new SolrIndexSearcher(this, schema, "main", newReader, true, true);
} else { } else {
tmp = new SolrIndexSearcher(this, schema, "main", getDirectoryFactory().open(newIndexDir), true, true); IndexReader reader = getIndexReaderFactory().newReader(getDirectoryFactory().open(newIndexDir), true);
} tmp = new SolrIndexSearcher(this, schema, "main", reader, true, true);
} else {
tmp = new SolrIndexSearcher(this, schema, "main", getDirectoryFactory().open(newIndexDir), true, true);
} }
} catch (Throwable th) { } catch (Throwable th) {
synchronized(searcherLock) { synchronized(searcherLock) {

View File

@ -0,0 +1,39 @@
package org.apache.solr.core;
/**
* 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.index.IndexReader;
import org.apache.lucene.store.Directory;
/**
* Default IndexReaderFactory implementation. Returns a standard Lucene
* IndexReader.
*
* @see IndexReader#open(Directory)
*/
public class StandardIndexReaderFactory extends IndexReaderFactory {
/* (non-Javadoc)
* @see org.apache.solr.core.IndexReaderFactory#newReader(org.apache.lucene.store.Directory, boolean)
*/
public IndexReader newReader(Directory indexDir, boolean readOnly)
throws IOException {
return IndexReader.open(indexDir, readOnly);
}
}

View File

@ -24,7 +24,6 @@ import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.*; import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory; import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.PriorityQueue;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrConfig;
@ -33,7 +32,6 @@ import org.apache.solr.core.SolrInfoMBean;
import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField; import org.apache.solr.schema.SchemaField;
import org.apache.solr.request.UnInvertedField; import org.apache.solr.request.UnInvertedField;
import org.apache.solr.search.function.BoostedQuery;
import org.apache.lucene.util.OpenBitSet; import org.apache.lucene.util.OpenBitSet;
import java.io.IOException; import java.io.IOException;
@ -92,17 +90,23 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
* @deprecated use alternate constructor * @deprecated use alternate constructor
*/ */
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, String path, boolean enableCache) throws IOException { public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, String path, boolean enableCache) throws IOException {
this(core, schema,name,IndexReader.open(path), true, enableCache); this(core, schema,name, core.getIndexReaderFactory().newReader(core.getDirectoryFactory().open(path), false), true, enableCache);
} }
/** Creates a searcher searching the index in the provided directory. */ /*
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, Directory directory, boolean enableCache) throws IOException { * Creates a searcher searching the index in the provided directory. Note:
this(core, schema,name,IndexReader.open(directory), true, enableCache); * uses the main IndexReaderFactory for the specified SolrCore.
*
* @see SolrCore#getMainIndexReaderFactory
*/
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name,
Directory directory, boolean enableCache) throws IOException {
this(core, schema,name, core.getIndexReaderFactory().newReader(directory, false), true, enableCache);
} }
/** Creates a searcher searching the index in the provided directory. */ /** Creates a searcher searching the index in the provided directory. */
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, Directory directory, boolean readOnly, boolean enableCache) throws IOException { public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, Directory directory, boolean readOnly, boolean enableCache) throws IOException {
this(core, schema,name,IndexReader.open(directory, readOnly), true, enableCache); this(core, schema,name, core.getIndexReaderFactory().newReader(directory, readOnly), true, enableCache);
} }
/** Creates a searcher searching the provided index. */ /** Creates a searcher searching the provided index. */

View File

@ -0,0 +1,61 @@
package org.apache.solr.core;
/**
* 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.index.IndexReader;
import org.apache.lucene.store.Directory;
import org.apache.solr.util.AbstractSolrTestCase;
public class AlternateIndexReaderTest extends AbstractSolrTestCase {
public String getSchemaFile() {
return "schema.xml";
}
public String getSolrConfigFile() {
return "solrconfig-altdirectory.xml";
}
/**
* Simple test to ensure that alternate IndexReaderFactory is being used.
*
* @throws Exception
*/
public void testAltReaderUsed() throws Exception {
assertTrue(TestIndexReaderFactory.newReaderCalled);
}
static public class TestIndexReaderFactory extends IndexReaderFactory {
static boolean newReaderCalled = false;
public IndexReader newReader(Directory indexDir) throws IOException {
TestIndexReaderFactory.newReaderCalled = true;
return IndexReader.open(indexDir);
}
public IndexReader newReader(Directory indexDir, boolean readOnly)
throws IOException {
TestIndexReaderFactory.newReaderCalled = true;
return IndexReader.open(indexDir, readOnly);
}
}
}

View File

@ -134,6 +134,11 @@
<!-- Parameters as required by the implementation --> <!-- Parameters as required by the implementation -->
</directoryFactory> </directoryFactory>
<indexReaderFactory name="IndexReaderFactory" class="org.apache.solr.core.AlternateIndexReaderTest$TestIndexReaderFactory">
<!-- Parameters as required by the implementation -->
</indexReaderFactory >
<query> <query>
<!-- Maximum number of clauses in a boolean query... can affect <!-- Maximum number of clauses in a boolean query... can affect
range or wildcard queries that expand to big boolean range or wildcard queries that expand to big boolean