SOLR-1198 moved updateHandler, updateprocessor to solrconfig

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@782885 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Noble Paul 2009-06-09 05:50:57 +00:00
parent 8f38d877fa
commit cbc9fae327
3 changed files with 154 additions and 101 deletions

View File

@ -19,6 +19,7 @@ package org.apache.solr.core;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.common.SolrException;
import org.apache.solr.handler.PingRequestHandler;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
@ -33,10 +34,13 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import java.util.*;
import java.util.regex.Pattern;
@ -169,6 +173,8 @@ public class SolrConfig extends Config {
maxWarmingSearchers = getInt("query/maxWarmingSearchers",Integer.MAX_VALUE);
loadPluginInfo();
updateProcessorChainInfo = loadUpdateProcessorInfo();
updateHandlerInfo = loadUpdatehandlerInfo();
Config.log.info("Loaded SolrConfig: " + name);
@ -176,27 +182,62 @@ public class SolrConfig extends Config {
config = this;
}
protected void loadPluginInfo() {
List<String> reqFields = Arrays.asList("name","class");
reqHandlerInfo = loadPluginInfo("requestHandler",reqFields);
respWriterInfo = loadPluginInfo("queryResponseWriter",reqFields);
valueSourceParserInfo = loadPluginInfo("valueSourceParser",reqFields);
queryParserInfo = loadPluginInfo("queryParser",reqFields);
searchComponentInfo = loadPluginInfo("searchComponent",reqFields);
List<PluginInfo> plugins = loadPluginInfo("directoryFactory",reqFields);
directoryfactoryInfo = plugins.isEmpty() ? null:plugins.get(0);
reqFields = Arrays.asList("class");
plugins = loadPluginInfo("mainIndex/deletionPolicy",reqFields);
deletionPolicyInfo = plugins.isEmpty() ? null : plugins.get(0);
firstSearcherListenerInfo = loadPluginInfo("//listener[@event='firstSearcher']",reqFields);
newSearcherListenerInfo = loadPluginInfo("//listener[@event='newSearcher']",reqFields);
protected UpdateHandlerInfo loadUpdatehandlerInfo() {
return new UpdateHandlerInfo(get("updateHandler/@class",null),
getInt("updateHandler/autoCommit/maxDocs",-1),
getInt("updateHandler/autoCommit/maxTime",-1),
getInt("updateHandler/commitIntervalLowerBound",-1));
}
private List<PluginInfo> loadPluginInfo(String tag, List<String> reqFields) {
protected void loadPluginInfo() {
reqHandlerInfo = loadPluginInfo("requestHandler",true);
respWriterInfo = loadPluginInfo("queryResponseWriter",true);
valueSourceParserInfo = loadPluginInfo("valueSourceParser",true);
queryParserInfo = loadPluginInfo("queryParser",true);
searchComponentInfo = loadPluginInfo("searchComponent",true);
List<PluginInfo> plugins = loadPluginInfo("directoryFactory",true);
directoryfactoryInfo = plugins.isEmpty() ? null:plugins.get(0);
plugins = loadPluginInfo("mainIndex/deletionPolicy",false);
deletionPolicyInfo = plugins.isEmpty() ? null : plugins.get(0);
firstSearcherListenerInfo = loadPluginInfo("//listener[@event='firstSearcher']",false);
newSearcherListenerInfo = loadPluginInfo("//listener[@event='newSearcher']",false);
}
protected Map<String, List<PluginInfo>> loadUpdateProcessorInfo() {
HashMap<String, List<PluginInfo>> chains = new HashMap<String, List<PluginInfo>>();
NodeList nodes = (NodeList) evaluate("updateRequestProcessorChain", XPathConstants.NODESET);
if (nodes != null) {
boolean requireName = nodes.getLength() > 1;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String name = DOMUtil.getAttr(node,"name", requireName ? "[solrconfig.xml] updateRequestProcessorChain":null);
boolean isDefault = "true".equals( DOMUtil.getAttr(node,"default", null ) );
XPath xpath = getXPath();
try {
NodeList nl = (NodeList) xpath.evaluate("processor",node, XPathConstants.NODESET);
if((nl.getLength() <1)) {
throw new RuntimeException( "updateRequestProcessorChain require at least one processor");
}
ArrayList<PluginInfo> result = new ArrayList<PluginInfo>();
for (int j=0; j<nl.getLength(); j++) {
result.add(new PluginInfo(nl.item(j) ,"[solrconfig.xml] processor",false));
}
chains.put(name,result);
if(isDefault || nodes.getLength() == 1) chains.put(null,result);
} catch (XPathExpressionException e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error reading processors",e,false);
}
}
}
return Collections.unmodifiableMap(chains);
}
private List<PluginInfo> loadPluginInfo(String tag, boolean requireName) {
ArrayList<PluginInfo> result = new ArrayList<PluginInfo>();
NodeList nodes = (NodeList) evaluate(tag, XPathConstants.NODESET);
for (int i=0; i<nodes.getLength(); i++) {
result.add(new PluginInfo(nodes.item(i) ,"[solrconfig.xml] "+tag,reqFields));
result.add(new PluginInfo(nodes.item(i) ,"[solrconfig.xml] "+tag,requireName));
}
return Collections.unmodifiableList(result) ;
}
@ -235,6 +276,8 @@ public class SolrConfig extends Config {
protected PluginInfo deletionPolicyInfo;
protected List<PluginInfo> newSearcherListenerInfo;
protected PluginInfo directoryfactoryInfo;
protected Map<String ,List<PluginInfo>> updateProcessorChainInfo ;
protected UpdateHandlerInfo updateHandlerInfo ;
public final int maxWarmingSearchers;
public final boolean unlockOnStartup;
@ -372,32 +415,59 @@ public class SolrConfig extends Config {
public LastModFrom getLastModFrom() { return lastModFrom; }
}
public static class UpdateHandlerInfo{
public final String className;
public final int autoCommmitMaxDocs,autoCommmitMaxTime,commitIntervalLowerBound;
/**
* @param className
* @param autoCommmitMaxDocs set -1 as default
* @param autoCommmitMaxTime set -1 as default
* @param commitIntervalLowerBound set -1 as default
*/
public UpdateHandlerInfo(String className, int autoCommmitMaxDocs, int autoCommmitMaxTime, int commitIntervalLowerBound) {
this.className = className;
this.autoCommmitMaxDocs = autoCommmitMaxDocs;
this.autoCommmitMaxTime = autoCommmitMaxTime;
this.commitIntervalLowerBound = commitIntervalLowerBound;
}
}
public static class PluginInfo {
final String startup, name, className;
final boolean isDefault;
final NamedList initArgs;
final Map<String ,String> otherAttributes;
public PluginInfo(String startup, String name, String className,
boolean isdefault, NamedList initArgs) {
boolean isdefault, NamedList initArgs, Map<String ,String> otherAttrs) {
this.startup = startup;
this.name = name;
this.className = className;
this.isDefault = isdefault;
this.initArgs = initArgs;
otherAttributes = otherAttrs == null ? Collections.<String ,String >emptyMap(): otherAttrs;
}
public PluginInfo(Node node, String err, List<String> reqFields) {
startup = getVal( node, "startup",reqFields,err);
name = getVal(node, "name", reqFields,err);
className = getVal(node, "class",reqFields,err);
isDefault = Boolean.parseBoolean(getVal(node,"default",reqFields,err));
public PluginInfo(Node node, String err, boolean requireName) {
name = DOMUtil.getAttr(node, "name", requireName ? err : null);
className = DOMUtil.getAttr(node, "class", err );
isDefault = Boolean.parseBoolean(DOMUtil.getAttr(node, "default", null));
startup = DOMUtil.getAttr(node, "startup",null);
initArgs = DOMUtil.childNodesToNamedList(node);
}
Map<String ,String> m = new HashMap<String, String>();
NamedNodeMap nnm = node.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
String name= nnm.item(i).getNodeName();
if(knownAttrs.contains(name)) continue;
m.put(name, nnm.item(i).getNodeValue());
}
otherAttributes = m.isEmpty() ?
Collections.<String ,String >emptyMap():
Collections.unmodifiableMap(m);
private String getVal(Node node, String name, List<String> required, String err) {
return DOMUtil.getAttr(node, name, required.contains(name) ? err : null);
}
}
@Override
public String toString() {
@ -405,10 +475,18 @@ public class SolrConfig extends Config {
if(name != null) sb.append("name = "+name +",");
if(className != null) sb.append("class = "+className +",");
if(isDefault) sb.append("default = "+isDefault +",");
if(startup != null) sb.append("startup = "+startup +",");
if(initArgs.size() >0) sb.append("args = "+initArgs);
sb.append("}");
return sb.toString();
}
private static final Set<String> knownAttrs = new HashSet<String>();
static {
knownAttrs.add("name");
knownAttrs.add("class");
knownAttrs.add("startup");
knownAttrs.add("default");
}
}
public List<PluginInfo> getReqHandlerInfo() { return reqHandlerInfo; }
@ -428,4 +506,8 @@ public class SolrConfig extends Config {
public PluginInfo getDirectoryfactoryInfo() { return directoryfactoryInfo; }
public PluginInfo getDeletionPolicyInfo() { return deletionPolicyInfo; }
public Map<String, List<PluginInfo>> getUpdateProcessorChainInfo() { return updateProcessorChainInfo; }
public UpdateHandlerInfo getUpdateHandlerInfo() { return updateHandlerInfo; }
}

View File

@ -86,6 +86,7 @@ public final class SolrCore implements SolrInfoMBean {
private final CoreDescriptor coreDescriptor;
private final SolrConfig solrConfig;
private final SolrResourceLoader resourceLoader;
private final IndexSchema schema;
private final String dataDir;
private final UpdateHandler updateHandler;
@ -126,7 +127,7 @@ public final class SolrCore implements SolrInfoMBean {
* @since solr 1.3
*/
public SolrResourceLoader getResourceLoader() {
return solrConfig.getResourceLoader();
return resourceLoader;
}
/**
@ -504,13 +505,13 @@ public final class SolrCore implements SolrInfoMBean {
public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd) {
coreDescriptor = cd;
this.setName( name );
SolrResourceLoader loader = config.getResourceLoader();
resourceLoader = config.getResourceLoader();
if (dataDir == null)
dataDir = config.get("dataDir",cd.getDataDir());
dataDir = SolrResourceLoader.normalizeDir(dataDir);
log.info(logid+"Opening new SolrCore at " + loader.getInstanceDir() + ", dataDir="+dataDir);
log.info(logid+"Opening new SolrCore at " + resourceLoader.getInstanceDir() + ", dataDir="+dataDir);
if (schema==null) {
schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);
@ -542,7 +543,7 @@ public final class SolrCore implements SolrInfoMBean {
initQParsers();
initValueSourceParsers();
this.searchComponents = loadSearchComponents( config );
this.searchComponents = loadSearchComponents();
// Processors initialized before the handlers
updateProcessorChains = loadUpdateProcessorChains();
@ -574,16 +575,15 @@ public final class SolrCore implements SolrInfoMBean {
// one in the middle.
// With lockless commits in Lucene now, this probably shouldn't be an issue anymore
getSearcher(false,false,null);
updateHandler = createUpdateHandler(
solrConfig.get("updateHandler/@class", DirectUpdateHandler2.class.getName())
);
String updateHandlerClass = solrConfig.getUpdateHandlerInfo().className;
updateHandler = createUpdateHandler(updateHandlerClass == null ? DirectUpdateHandler2.class.getName():updateHandlerClass);
infoRegistry.put("updateHandler", updateHandler);
// Finally tell anyone who wants to know
loader.inform( loader );
loader.inform( this );
resourceLoader.inform( resourceLoader );
resourceLoader.inform( this );
instance = this; // set singleton for backwards compatibility
} catch (IOException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
@ -597,79 +597,50 @@ public final class SolrCore implements SolrInfoMBean {
/**
* Load the request processors configured in solrconfig.xml
* Load the request processors
*/
private Map<String,UpdateRequestProcessorChain> loadUpdateProcessorChains() {
final Map<String,UpdateRequestProcessorChain> map = new HashMap<String, UpdateRequestProcessorChain>();
final String parsingErrorText = "Parsing Update Request Processor Chain";
private Map<String,UpdateRequestProcessorChain> loadUpdateProcessorChains() {
final Map<String, UpdateRequestProcessorChain> map = new HashMap<String, UpdateRequestProcessorChain>();
UpdateRequestProcessorChain def = null;
// This is kinda ugly, but at least it keeps the xpath logic in one place
// away from the Processors themselves.
XPath xpath = solrConfig.getXPath();
NodeList nodes = (NodeList)solrConfig.evaluate("updateRequestProcessorChain", XPathConstants.NODESET);
boolean requireName = nodes.getLength() > 1;
if (nodes !=null ) {
for (int i=0; i<nodes.getLength(); i++) {
Node node = nodes.item(i);
String name = DOMUtil.getAttr(node,"name", requireName?parsingErrorText:null);
boolean isDefault = "true".equals( DOMUtil.getAttr(node,"default", null ) );
NodeList links = null;
try {
links = (NodeList)xpath.evaluate("processor", node, XPathConstants.NODESET);
}
catch (XPathExpressionException e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error reading processors",e,false);
Map<String, List<SolrConfig.PluginInfo>> infos = solrConfig.getUpdateProcessorChainInfo();
System.out.println(infos);
if (!infos.isEmpty()) {
boolean defaultProcessed = false;
List<SolrConfig.PluginInfo> defProcessorChainInfo = infos.get(null);// this is the default one
for (Map.Entry<String, List<SolrConfig.PluginInfo>> e : solrConfig.getUpdateProcessorChainInfo().entrySet()) {
List<SolrConfig.PluginInfo> processorsInfo = e.getValue();
if (processorsInfo == defProcessorChainInfo && defaultProcessed) {
map.put(e.getKey(), def);
continue;
}
if( links == null || links.getLength() < 1 ) {
throw new RuntimeException( "updateRequestProcessorChain require at least one processor");
UpdateRequestProcessorFactory[] chain = new UpdateRequestProcessorFactory[processorsInfo.size()];
for (int i = 0; i < processorsInfo.size(); i++) {
SolrConfig.PluginInfo info = processorsInfo.get(i);
chain[i] = createInstance(info.className, UpdateRequestProcessorFactory.class, null);
chain[i].init(info.initArgs);
}
// keep a list of the factories...
final ArrayList<UpdateRequestProcessorFactory> factories = new ArrayList<UpdateRequestProcessorFactory>(links.getLength());
// Load and initialize the plugin chain
AbstractPluginLoader<UpdateRequestProcessorFactory> loader
= new AbstractPluginLoader<UpdateRequestProcessorFactory>( "processor chain", false, false ) {
@Override
protected void init(UpdateRequestProcessorFactory plugin, Node node) throws Exception {
plugin.init( (node==null)?null:DOMUtil.childNodesToNamedList(node) );
}
@Override
protected UpdateRequestProcessorFactory register(String name, UpdateRequestProcessorFactory plugin) throws Exception {
factories.add( plugin );
return null;
}
};
loader.load( solrConfig.getResourceLoader(), links );
UpdateRequestProcessorChain chain = new UpdateRequestProcessorChain(
factories.toArray( new UpdateRequestProcessorFactory[factories.size()] ) );
if( isDefault || nodes.getLength()==1 ) {
def = chain;
}
if( name != null ) {
map.put(name, chain);
UpdateRequestProcessorChain processorChain = new UpdateRequestProcessorChain(chain);
map.put(e.getKey(), processorChain);
if (e.getKey() == null || processorsInfo == defProcessorChainInfo) { //this is the default one
defaultProcessed = true;
def = processorChain;
}
}
}
if( def == null ) {
if (def == null) {
// construct the default chain
UpdateRequestProcessorFactory[] factories = new UpdateRequestProcessorFactory[] {
new RunUpdateProcessorFactory(),
new LogUpdateProcessorFactory()
UpdateRequestProcessorFactory[] factories = new UpdateRequestProcessorFactory[]{
new RunUpdateProcessorFactory(),
new LogUpdateProcessorFactory()
};
def = new UpdateRequestProcessorChain( factories );
def = new UpdateRequestProcessorChain(factories);
}
map.put( null, def );
map.put( "", def );
map.put(null, def);
map.put("", def);
return map;
}
/**
* @return an update processor registered to the given name. Throw an exception if this chain is undefined
*/
@ -849,13 +820,13 @@ public final class SolrCore implements SolrInfoMBean {
/**
* Register the default search components
*/
private Map<String, SearchComponent> loadSearchComponents( SolrConfig config )
private Map<String, SearchComponent> loadSearchComponents()
{
Map<String, SearchComponent> components = new HashMap<String, SearchComponent>();
String xpath = "searchComponent";
NamedListPluginLoader<SearchComponent> loader = new NamedListPluginLoader<SearchComponent>( xpath, components );
loader.load( config.getResourceLoader(), (NodeList)config.evaluate( xpath, XPathConstants.NODESET ) );
loader.load( solrConfig.getResourceLoader(), (NodeList)solrConfig.evaluate( xpath, XPathConstants.NODESET ) );
final Map<String,Class<? extends SearchComponent>> standardcomponents
= new HashMap<String, Class<? extends SearchComponent>>();

View File

@ -520,8 +520,8 @@ public class DirectUpdateHandler2 extends UpdateHandler {
docsSinceCommit = 0;
pending = null;
docsUpperBound = core.getSolrConfig().getInt("updateHandler/autoCommit/maxDocs", -1);
timeUpperBound = core.getSolrConfig().getInt("updateHandler/autoCommit/maxTime", -1);
docsUpperBound = core.getSolrConfig().getUpdateHandlerInfo().autoCommmitMaxDocs; //getInt("updateHandler/autoCommit/maxDocs", -1);
timeUpperBound = core.getSolrConfig().getUpdateHandlerInfo().autoCommmitMaxTime; //getInt("updateHandler/autoCommit/maxTime", -1);
SolrCore.log.info("AutoCommit: " + this);
}