mirror of https://github.com/apache/lucene.git
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:
parent
5f02ccf9ec
commit
0502d82893
|
@ -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
|
||||||
|
|
|
@ -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"/>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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. */
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue