You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by ry...@apache.org on 2008/03/04 05:06:20 UTC
svn commit: r633360 - in /lucene/solr/trunk:
client/java/solrj/src/org/apache/solr/client/solrj/embedded/
client/java/solrj/src/org/apache/solr/client/solrj/request/
client/java/solrj/test/org/apache/solr/client/solrj/ example/multicore/
src/java/org/a...
Author: ryan
Date: Mon Mar 3 20:06:17 2008
New Revision: 633360
URL: http://svn.apache.org/viewvc?rev=633360&view=rev
Log:
SOLR-350 -- manage multiple cores. This implements persist, load and unload.
Added:
lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java (with props)
Modified:
lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java
lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java
lucene/solr/trunk/example/multicore/multicore.xml
lucene/solr/trunk/src/java/org/apache/solr/common/params/MultiCoreParams.java
lucene/solr/trunk/src/java/org/apache/solr/core/Config.java
lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java
lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java
lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
lucene/solr/trunk/src/java/org/apache/solr/core/SolrResourceLoader.java
lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java
lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java
lucene/solr/trunk/src/test/org/apache/solr/servlet/SolrRequestParserTest.java
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java
Modified: lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java (original)
+++ lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java Mon Mar 3 20:06:17 2008
@@ -84,7 +84,7 @@
_invariantParams.set( CommonParams.WT, _processor.getWriterType() );
_invariantParams.set( CommonParams.VERSION, "2.2" );
- return new SolrRequestParsers( true, Long.MAX_VALUE );
+ return new SolrRequestParsers( null );
}
@Override
Modified: lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java (original)
+++ lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java Mon Mar 3 20:06:17 2008
@@ -20,9 +20,9 @@
import java.io.IOException;
import java.util.Collection;
+import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.response.MultiCoreResponse;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.MultiCoreParams;
@@ -32,13 +32,50 @@
/**
*
- * @version $Id$
+ * @version $Id: MultiCoreRequest.java 606335 2007-12-21 22:23:39Z ryan $
* @since solr 1.3
*/
public class MultiCoreRequest extends SolrRequest
{
- private MultiCoreParams.MultiCoreAction action = null;
- private String core = null;
+ protected String core = null;
+ protected MultiCoreParams.MultiCoreAction action = null;
+
+ //a create core request
+ public static class Create extends MultiCoreRequest {
+ protected String instanceDir;
+ protected String configName = null;
+ protected String schemaName = null;
+
+ public Create() {
+ action = MultiCoreAction.CREATE;
+ }
+
+ public void setInstanceDir(String instanceDir) { this.instanceDir = instanceDir; }
+ public void setSchemaName(String schema) { this.schemaName = schema; }
+ public void setConfigName(String config) { this.configName = config; }
+
+ public String getInstanceDir() { return instanceDir; }
+ public String getSchemaName() { return schemaName; }
+ public String getConfigName() { return configName; }
+
+ @Override
+ public SolrParams getParams() {
+ if( action == null ) {
+ throw new RuntimeException( "no action specified!" );
+ }
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set( MultiCoreParams.ACTION, action.toString() );
+ params.set( MultiCoreParams.CORE, core );
+ params.set( MultiCoreParams.INSTANCE_DIR, instanceDir);
+ if (configName != null) {
+ params.set( MultiCoreParams.CONFIG, configName);
+ }
+ if (schemaName != null) {
+ params.set( MultiCoreParams.SCHEMA, schemaName);
+ }
+ return params;
+ }
+ }
public MultiCoreRequest()
{
@@ -88,7 +125,7 @@
public Collection<ContentStream> getContentStreams() throws IOException {
return null;
}
-
+
@Override
public MultiCoreResponse process(SolrServer server) throws SolrServerException, IOException
{
@@ -115,6 +152,14 @@
MultiCoreRequest req = new MultiCoreRequest();
req.setCoreParam( name );
req.setAction( MultiCoreAction.STATUS );
+ return req.process( server );
+ }
+
+ public static MultiCoreResponse createCore( String name, String instanceDir, SolrServer server ) throws SolrServerException, IOException
+ {
+ MultiCoreRequest.Create req = new MultiCoreRequest.Create();
+ req.setCoreParam( name );
+ req.setInstanceDir(instanceDir);
return req.process( server );
}
}
Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java (original)
+++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java Mon Mar 3 20:06:17 2008
@@ -17,6 +17,8 @@
package org.apache.solr.client.solrj;
+import java.io.File;
+
import org.apache.solr.client.solrj.request.MultiCoreRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -37,6 +39,12 @@
@Override public String getSchemaFile() { return getSolrHome()+"core0/conf/schema.xml"; }
@Override public String getSolrConfigFile() { return getSolrHome()+"core0/conf/solrconfig.xml"; }
+ @Override public void setUp() throws Exception {
+// File src = new File(getSolrHome(), "multicore-base.xml");
+// File dest = new File(getSolrHome(), "multicore.xml");
+// org.apache.solr.core.MultiCore.fileCopy(src, dest);
+ super.setUp();
+ }
@Override
protected final SolrServer getSolrServer()
Modified: lucene/solr/trunk/example/multicore/multicore.xml
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/example/multicore/multicore.xml?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/example/multicore/multicore.xml (original)
+++ lucene/solr/trunk/example/multicore/multicore.xml Mon Mar 3 20:06:17 2008
@@ -17,16 +17,15 @@
-->
<!--
- All paths are relative to the instaliation path
+ All (relative) paths are relative to the installation path
adminPath: RequestHandler path to manage multicores.
If 'null', cores will not be managable via REST
- persistent: Save changes made via the REST API to this file?
-
- sharedLib: path to a lib files that will be shared across all cores
+ persistent: Save changes made via the API to this file
+ sharedLib: path to a lib directory that will be shared across all cores
-->
<multicore adminPath="/admin/multicore" persistent="true" >
<core name="core0" instanceDir="core0" default="true"/>
- <core name="core1" instanceDir="core1" />
+ <core name="core1" instanceDir="core1"/>
</multicore>
Modified: lucene/solr/trunk/src/java/org/apache/solr/common/params/MultiCoreParams.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/common/params/MultiCoreParams.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/common/params/MultiCoreParams.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/common/params/MultiCoreParams.java Mon Mar 3 20:06:17 2008
@@ -32,14 +32,29 @@
/** The name of the the core to swap names with **/
public final static String WITH = "with";
+ /** If you rename something, what is the new name **/
+ public final static String NAME = "name";
+
/** What action **/
public final static String ACTION = "action";
+ /** If you specify a schema, what is its name **/
+ public final static String SCHEMA = "schema";
+
+ /** If you specify a config, what is its name **/
+ public final static String CONFIG = "config";
+
+ /** Specifies a core instance dir. */
+ public final static String INSTANCE_DIR = "instanceDir";
+
public enum MultiCoreAction {
STATUS,
LOAD,
UNLOAD,
RELOAD,
+ CREATE,
+ DROP,
+ PERSIST,
SWAP;
public static MultiCoreAction get( String p )
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/Config.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/Config.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/Config.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/Config.java Mon Mar 3 20:06:17 2008
@@ -51,11 +51,38 @@
this( null, name, is, prefix );
}
+ /**
+ * Builds a config from a resource name with no xpath prefix.
+ * @param loader
+ * @param name
+ * @throws javax.xml.parsers.ParserConfigurationException
+ * @throws java.io.IOException
+ * @throws org.xml.sax.SAXException
+ */
public Config(SolrResourceLoader loader, String name) throws ParserConfigurationException, IOException, SAXException
{
this( loader, name, null, null );
}
+ /**
+ * Builds a config:
+ * <p>
+ * Note that the 'name' parameter is used to obtain a valid input stream if no valid one is provided through 'is'.
+ * If no valid stream is provided, a valid SolrResourceLoader instance should be provided through 'loader' so
+ * the resource can be opened (@see SolrResourceLoader#openResource); if no SolrResourceLoader instance is provided, a default one
+ * will be created.
+ * </p>
+ * <p>
+ * Consider passing a non-null 'name' parameter in all use-cases since it is used for logging & exception reporting.
+ * </p>
+ * @param loader the resource loader used to obtain an input stream if 'is' is null
+ * @param name the resource name used if the input stream 'is' is null
+ * @param is the resource as a stream
+ * @param prefix an optional prefix that will be preprended to all non-absolute xpath expressions
+ * @throws javax.xml.parsers.ParserConfigurationException
+ * @throws java.io.IOException
+ * @throws org.xml.sax.SAXException
+ */
public Config(SolrResourceLoader loader, String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException
{
if( loader == null ) {
@@ -63,14 +90,12 @@
}
this.loader = loader;
this.name = name;
- this.prefix = prefix;
-
- if (prefix!=null && !prefix.endsWith("/")) prefix += '/';
+ this.prefix = (prefix != null && !prefix.endsWith("/"))? prefix + '/' : prefix;
InputStream lis = is;
try {
- if (lis == null)
- lis = loader.openResource(name);
-
+ if (lis == null) {
+ lis = loader.openConfig(name);
+ }
javax.xml.parsers.DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = builder.parse(lis);
@@ -80,8 +105,7 @@
throw e;
} finally {
// if this opens the resource, it also closes it
- if (lis != is)
- lis.close();
+ if (lis != is) lis.close();
}
}
@@ -93,6 +117,17 @@
return loader;
}
+ /**
+ * @since solr 1.3
+ */
+ public String getResourceName() {
+ return name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
public Document getDocument() {
return doc;
}
@@ -206,13 +241,6 @@
return val!=null ? Float.parseFloat(val) : def;
}
- /**
- * @return the XML filename
- */
- public String getName() {
- return name;
- }
-
// The following functions were moved to ResourceLoader
//-----------------------------------------------------------------------------
Added: lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java?rev=633360&view=auto
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java (added)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java Mon Mar 3 20:06:17 2008
@@ -0,0 +1,116 @@
+/**
+ * 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.
+ */
+
+package org.apache.solr.core;
+
+/**
+ * A Solr core descriptor
+ * @since solr 1.3
+ */
+public class CoreDescriptor implements Cloneable {
+ protected String name;
+ protected String instanceDir;
+ protected String configName;
+ protected String schemaName;
+ protected SolrCore core = null;
+
+ public CoreDescriptor() {}
+
+ /** Initialize defaults from instance directory. */
+ public void init(String name, String instanceDir) {
+ if (name == null) {
+ throw new RuntimeException("Core needs a name");
+ }
+ if (instanceDir == null) {
+ throw new NullPointerException("Missing required \'instanceDir\'");
+ }
+ this.name = name;
+ if (!instanceDir.endsWith("/")) instanceDir = instanceDir + "/";
+ this.instanceDir = instanceDir;
+ this.configName = getDefaultConfigName();
+ this.schemaName = getDefaultSchemaName();
+ }
+
+ public CoreDescriptor(CoreDescriptor descr) {
+ this.name = descr.name;
+ this.instanceDir = descr.instanceDir;
+ this.configName = descr.configName;
+ this.schemaName = descr.schemaName;
+ }
+
+ /**@return the default config name. */
+ public String getDefaultConfigName() {
+ return "solrconfig.xml";
+ }
+
+ /**@return the default schema name. */
+ public String getDefaultSchemaName() {
+ return "schema.xml";
+ }
+
+ /**@return the default data directory. */
+ public String getDefaultDataDir() {
+ return this.instanceDir + "data/";
+ }
+
+ /**@return the core name. */
+ public String getName() {
+ return name;
+ }
+
+ /** Sets the core name. */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**@return the core instance directory. */
+ public String getInstanceDir() {
+ return instanceDir;
+ }
+
+ /**Sets the core configuration resource name. */
+ public void setConfigName(String name) {
+ if (name == null || name.length() == 0)
+ throw new IllegalArgumentException("name can not be null or empty");
+ this.configName = name;
+ }
+
+ /**@return the core configuration resource name. */
+ public String getConfigName() {
+ return this.configName;
+ }
+
+ /**Sets the core schema resource name. */
+ public void setSchemaName(String name) {
+ if (name == null || name.length() == 0)
+ throw new IllegalArgumentException("name can not be null or empty");
+ this.schemaName = name;
+ }
+
+ /**@return the core schema resource name. */
+ public String getSchemaName() {
+ return this.schemaName;
+ }
+
+ public SolrCore getCore() {
+ return core;
+ }
+
+ public void setCore(SolrCore core) {
+ this.core = core;
+ }
+}
Propchange: lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/solr/trunk/src/java/org/apache/solr/core/CoreDescriptor.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/MultiCore.java Mon Mar 3 20:06:17 2008
@@ -17,12 +17,16 @@
package org.apache.solr.core;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.channels.FileChannel;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;
@@ -31,6 +35,7 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.DOMUtil;
+import org.apache.solr.common.util.XML;
import org.apache.solr.handler.admin.MultiCoreHandler;
import org.apache.solr.schema.IndexSchema;
import org.w3c.dom.Node;
@@ -48,10 +53,8 @@
private static final MultiCore instance = new MultiCore();
// Synchronized map of all cores
- private final Map<String, SolrCore> cores =
- Collections.synchronizedMap( new HashMap<String, SolrCore>() );
+ private final Map<String, CoreDescriptor> cores = new LinkedHashMap<String, CoreDescriptor>();
- private SolrCore defaultCore = null;
private boolean enabled = false;
private boolean persistent = false;
private String adminPath = null;
@@ -59,6 +62,7 @@
private File configFile = null;
private String libDir = null;
private ClassLoader libLoader = null;
+ private SolrResourceLoader loader = null;
// no one else can make the registry
private MultiCore() { }
@@ -72,71 +76,61 @@
*/
public void load(String dir, File configFile ) throws ParserConfigurationException, IOException, SAXException {
this.configFile = configFile;
- Config cfg = new Config( new SolrResourceLoader(dir),
- null, new FileInputStream( configFile ), null );
+ this.loader = new SolrResourceLoader(dir);
+ FileInputStream cfgis = new FileInputStream(configFile);
+ try {
+ Config cfg = new Config(loader, null, cfgis, null);
- persistent = cfg.getBool( "multicore/@persistent", false );
- adminPath = cfg.get( "multicore/@adminPath", null );
- libDir = cfg.get( "multicore/@sharedLib", null);
- if (libDir != null) {
- // relative dir to conf
- File f = new File(dir, libDir);
- libDir = f.getPath();
- log.info( "loading shared library: "+f.getAbsolutePath() );
- libLoader = SolrResourceLoader.createClassLoader(f, null);
- }
-
- if( adminPath != null ) {
- multiCoreHandler = new MultiCoreHandler();
- }
-
- boolean hasDefault = false;
- NodeList nodes = (NodeList)cfg.evaluate("multicore/core", XPathConstants.NODESET);
- for (int i=0; i<nodes.getLength(); i++) {
- Node node = nodes.item(i);
+ persistent = cfg.getBool( "multicore/@persistent", false );
+ adminPath = cfg.get( "multicore/@adminPath", null );
+ libDir = cfg.get( "multicore/@sharedLib", null);
- try {
- String name = DOMUtil.getAttr(node,"name", "Core needs a name" );
- String instanceDir = DOMUtil.getAttr(node,"instanceDir", "Missing required 'instanceDir'" );
- String dataDir = DOMUtil.getAttr(node,"dataDir", null );
- String defaultStr = DOMUtil.getAttr(node,"default", null );
-
- // Make the instanceDir relative to the core config
- File idir = new File( dir, instanceDir );
- instanceDir = idir.getPath();
-
- // Initialize the solr config
- SolrResourceLoader solrLoader = new SolrResourceLoader(instanceDir, libLoader);
- SolrConfig solrConfig = new SolrConfig( solrLoader, SolrConfig.DEFAULT_CONF_FILE, null );
- IndexSchema schema = new IndexSchema(solrConfig, instanceDir+"/conf/schema.xml");
- SolrCore core = new SolrCore( name, dataDir, solrConfig, schema );
-
- // Register the new core
- SolrCore old = this.register( core );
- if( old != null ) {
- throw new RuntimeException( cfg.getName() +
- " registers multiple cores to the same name: "+name );
- }
-
- if( "true".equalsIgnoreCase( defaultStr ) ) {
- if( hasDefault ) {
- throw new RuntimeException(
- "multicore.xml defines multiple default cores. "+
- getDefaultCore().getName() + " and " + core.getName() );
+ if (libDir != null) {
+ // relative dir to conf
+ File f = new File(dir, libDir);
+ libDir = f.getPath();
+ log.info( "loading shared library: "+f.getAbsolutePath() );
+ libLoader = SolrResourceLoader.createClassLoader(f, null);
+ }
+
+ if( adminPath != null ) {
+ multiCoreHandler = new MultiCoreHandler();
+ }
+
+ NodeList nodes = (NodeList)cfg.evaluate("multicore/core", XPathConstants.NODESET);
+ synchronized (cores) {
+ for (int i=0; i<nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ try {
+ CoreDescriptor p = new CoreDescriptor();
+ p.init(DOMUtil.getAttr(node, "name", null), DOMUtil.getAttr(node, "instanceDir", null));
+ // deal with optional settings
+ String opt = DOMUtil.getAttr(node, "config", null);
+ if (opt != null) {
+ p.setConfigName(opt);
+ }
+ opt = DOMUtil.getAttr(node, "schema", null);
+ if (opt != null) {
+ p.setSchemaName(opt);
+ }
+ CoreDescriptor old = cores.get(p.getName());
+ if (old != null && old.getName() != null && old.getName().equals(p.getName())) {
+ throw new RuntimeException( cfg.getName() +
+ " registers multiple cores to the same name: " + p.name);
+ }
+ p.setCore(create(p));
+ }
+ catch (Throwable ex) {
+ SolrConfig.severeErrors.add( ex );
+ SolrException.logOnce(log,null,ex);
}
- defaultCore = core;
- hasDefault = true;
}
- }
- catch( Throwable ex ) {
- SolrConfig.severeErrors.add( ex );
- SolrException.logOnce(log,null,ex);
}
}
-
- if( !hasDefault ) {
- throw new RuntimeException(
- "multicore.xml must define at least one default core" );
+ finally {
+ if (cfgis != null) {
+ try { cfgis.close(); } catch (Exception xany) {}
+ }
}
enabled = true;
}
@@ -144,7 +138,11 @@
/** Stops all cores. */
public void shutdown() {
synchronized(cores) {
- for( SolrCore core : cores.values() ) {
+ for(Map.Entry<String,CoreDescriptor> e : cores.entrySet()) {
+ SolrCore core = e.getValue().getCore();
+ if (core == null) continue;
+ String key = e.getKey();
+ if (core.getName().equals(key))
core.close();
}
cores.clear();
@@ -165,11 +163,11 @@
return instance;
}
- public SolrCore register( SolrCore core ) {
- if( core == null ) {
+ public CoreDescriptor register( CoreDescriptor descr ) {
+ if( descr == null ) {
throw new RuntimeException( "Can not register a null core." );
}
- String name = core.getName();
+ String name = descr.getName();
if( name == null ||
name.length() < 1 ||
name.indexOf( '/' ) >= 0 ||
@@ -177,16 +175,18 @@
throw new RuntimeException( "Invalid core name: "+name );
}
- SolrCore old = cores.put(name, core);
+ CoreDescriptor old = cores.put(name, descr);
if( old == null ) {
log.info( "registering core: "+name );
- } else {
+ return null;
+ }
+ else {
log.info( "replacing core: "+name );
+ return old;
}
- return old;
}
-
- public void swap(SolrCore c0, SolrCore c1) {
+
+ public void swap(CoreDescriptor c0, CoreDescriptor c1) {
if( c0 == null || c1 == null ) {
throw new RuntimeException( "Can not swap a null core." );
}
@@ -196,12 +196,45 @@
cores.put(n0, c1);
cores.put(n1, c0);
c0.setName( n1 );
+ if (c0.getCore() != null)
+ c0.getCore().setName(n1);
c1.setName( n0 );
+ if (c1.getCore() != null)
+ c1.getCore().setName(n0);
}
log.info( "swaped: "+c0.getName() + " with " + c1.getName() );
}
/**
+ * Creates a new core based on a descriptor.
+ *
+ * @param dcore a core descriptor
+ * @return the newly created core
+ * @throws javax.xml.parsers.ParserConfigurationException
+ * @throws java.io.IOException
+ * @throws org.xml.sax.SAXException
+ */
+ public SolrCore create(CoreDescriptor dcore) throws ParserConfigurationException, IOException, SAXException {
+ // Make the instanceDir relative to the multicore instanceDir if not absolute
+ File idir = new File(dcore.getInstanceDir());
+ if (!idir.isAbsolute()) {
+ idir = new File(loader.getInstanceDir(), dcore.getInstanceDir());
+ }
+ String instanceDir = idir.getPath();
+
+ // Initialize the solr config
+ SolrResourceLoader solrLoader = new SolrResourceLoader(instanceDir, libLoader);
+ SolrConfig config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
+ IndexSchema schema = new IndexSchema(config, dcore.getSchemaName(), null);
+ SolrCore core = new SolrCore(dcore.getName(), null, config, schema);
+ dcore.setCore(core);
+
+ // Register the new core
+ CoreDescriptor old = this.register(dcore);
+ return core;
+ }
+
+ /**
* While the new core is loading, requests will continue to be dispatched to
* and processed by the old core
*
@@ -210,36 +243,51 @@
* @throws IOException
* @throws SAXException
*/
- public void reload(SolrCore core) throws ParserConfigurationException, IOException, SAXException
- {
- SolrResourceLoader loader = new SolrResourceLoader( core.getResourceLoader().getInstanceDir() );
- SolrConfig config = new SolrConfig( loader, core.getConfigFile(), null );
- IndexSchema schema = new IndexSchema( config, core.getSchemaFile() );
- SolrCore loaded = new SolrCore( core.getName(), core.getDataDir(), config, schema );
- this.register( loaded );
-
- // TODO? -- add some kind of hook to close the core after all references are
- // gone... is finalize() enough?
- }
-
- public void remove( String name )
- {
- cores.remove( name );
+ public void reload(CoreDescriptor dcore) throws ParserConfigurationException, IOException, SAXException {
+ create(new CoreDescriptor(dcore));
}
- public SolrCore getDefaultCore() {
- return defaultCore;
+ // TODO? -- add some kind of hook to close the core after all references are
+ // gone... is finalize() enough?
+ public void remove( String name ) {
+ synchronized(cores) {
+ CoreDescriptor dcore = cores.remove( name );
+ if (dcore == null) {
+ return;
+ }
+
+ SolrCore core = dcore.getCore();
+ if (core != null) {
+ core.close();
+ }
+ }
}
/**
* @return a Collection of registered SolrCores
*/
public Collection<SolrCore> getCores() {
+ java.util.List<SolrCore> l = new java.util.ArrayList<SolrCore>();
+ for(CoreDescriptor descr : this.cores.values()) {
+ if (descr.getCore() != null)
+ l.add(descr.getCore());
+ }
+ return l;
+ }
+
+ public Collection<CoreDescriptor> getDescriptors() {
return cores.values();
}
public SolrCore getCore(String name) {
- return cores.get( name );
+ CoreDescriptor dcore = getDescriptor( name );
+ return (dcore == null) ? null : dcore.getCore();
+ }
+
+ public CoreDescriptor getDescriptor(String name) {
+ synchronized(cores) {
+ return cores.get( name );
+ }
}
public boolean isEnabled() {
@@ -272,5 +320,123 @@
public File getConfigFile() {
return configFile;
+ }
+
+ /** Persists the multicore config file. */
+ public void persist() {
+ File tmpFile = null;
+ try {
+ // write in temp first
+ tmpFile = File.createTempFile("multicore", ".xml", configFile.getParentFile());
+ java.io.FileOutputStream out = new java.io.FileOutputStream(tmpFile);
+ synchronized(cores) {
+ Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
+ persist(writer);
+ writer.flush();
+ writer.close();
+ out.close();
+ // rename over origin or copy it it this fails
+ if (tmpFile.renameTo(configFile))
+ tmpFile = null;
+ else
+ fileCopy(tmpFile, configFile);
+ }
+ }
+ catch(java.io.FileNotFoundException xnf) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, xnf);
+ }
+ catch(java.io.IOException xio) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, xio);
+ }
+ finally {
+ if (tmpFile != null) {
+ if (!tmpFile.delete())
+ tmpFile.deleteOnExit();
+ }
+ }
+ }
+
+ /** Write the multicore configuration through a writer.*/
+ void persist(Writer writer) throws IOException {
+ writer.write("<?xml version='1.0' encoding='UTF-8'?>");
+ writer.write("\n");
+ writer.write("<multicore adminPath='");
+ XML.escapeAttributeValue(adminPath, writer);
+ writer.write('\'');
+ if (this.libDir != null) {
+ writer.write(" libDir='");
+ XML.escapeAttributeValue(libDir, writer);
+ writer.write('\'');
+ }
+ writer.write(" persistent='");
+ if (isPersistent()) {
+ writer.write("true'");
+ }
+ else {
+ writer.write("false'");
+ }
+ writer.write(">\n");
+
+ // for all cores...(synchronized on cores by caller)
+ for (Map.Entry<String, CoreDescriptor> entry : cores.entrySet()) {
+ persist(writer, entry.getValue());
+ }
+ writer.write("</multicore>\n");
+ }
+
+ /** Writes the multicore configuration node for a given core. */
+ void persist(Writer writer, CoreDescriptor dcore) throws IOException {
+ writer.write(" <core");
+ writer.write (" name='");
+ XML.escapeAttributeValue(dcore.getName(), writer);
+ writer.write("' instanceDir='");
+ XML.escapeAttributeValue(dcore.getInstanceDir(), writer);
+ writer.write('\'');
+ //write config (if not default)
+ String opt = dcore.getConfigName();
+ if (opt != null && !opt.equals(dcore.getDefaultConfigName())) {
+ writer.write(" config='");
+ XML.escapeAttributeValue(opt, writer);
+ writer.write('\'');
+ }
+ //write schema (if not default)
+ opt = dcore.getSchemaName();
+ if (opt != null && !opt.equals(dcore.getDefaultSchemaName())) {
+ writer.write(" schema='");
+ XML.escapeAttributeValue(opt, writer);
+ writer.write('\'');
+ }
+ writer.write("/>\n"); // core
+ }
+
+ /** Copies a src file to a dest file:
+ * used to circumvent the platform discrepancies regarding renaming files.
+ */
+ public static void fileCopy(File src, File dest) throws IOException {
+ IOException xforward = null;
+ FileInputStream fis = null;
+ FileOutputStream fos = null;
+ FileChannel fcin = null;
+ FileChannel fcout = null;
+ try {
+ fis = new FileInputStream(src);
+ fos = new FileOutputStream(dest);
+ fcin = fis.getChannel();
+ fcout = fos.getChannel();
+ // do the file copy
+ fcin.transferTo(0, fcin.size(), fcout);
+ }
+ catch(IOException xio) {
+ xforward = xio;
+ }
+ finally {
+ if (fis != null) try { fis.close(); fis = null; } catch(IOException xio) {}
+ if (fos != null) try { fos.close(); fos = null; } catch(IOException xio) {}
+ if (fcin != null && fcin.isOpen() ) try { fcin.close(); fcin = null; } catch(IOException xio) {}
+ if (fcout != null && fcout.isOpen()) try { fcout.close(); fcout = null; } catch(IOException xio) {}
+ }
+ if (xforward != null) {
+ throw xforward;
+ }
}
}
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrConfig.java Mon Mar 3 20:06:17 2008
@@ -18,7 +18,6 @@
package org.apache.solr.core;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.handler.PingRequestHandler;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
@@ -52,19 +51,10 @@
public static final String DEFAULT_CONF_FILE = "solrconfig.xml";
- /**
- * Singleton containing all configuration.
- * Compatibility feature for single-core (pre-solr215 patch) code.
- * Most usage should be converted by:
- * - using the configuration directly when used in Abstract{Tokeinizer,TokenFilter}Factory.init().
- * - getting the configuration through the owning core if accessible (SolrCore.getSolrConfig()).
- * - getting the core by name then its configuration as above
- */
+ // Compatibility feature for single-core (pre-solr{215,350} patch); should go away at solr-2.0
@Deprecated
public static SolrConfig config = null;
- public final String configFile;
-
/**
* Singleton keeping track of configuration errors
*/
@@ -73,30 +63,50 @@
/** Creates a default instance from the solrconfig.xml. */
public SolrConfig()
throws ParserConfigurationException, IOException, SAXException {
- this( new SolrResourceLoader(null), DEFAULT_CONF_FILE, null );
+ this( (SolrResourceLoader) null, DEFAULT_CONF_FILE, null );
}
- /** Creates a configuration instance from a file. */
- public SolrConfig(String file)
+
+ /** Creates a configuration instance from a configuration name.
+ * A default resource loader will be created (@see SolrResourceLoader)
+ *@param name the configuration name used by the loader
+ */
+ public SolrConfig(String name)
throws ParserConfigurationException, IOException, SAXException {
- this( new SolrResourceLoader(null), file, null);
+ this( (SolrResourceLoader) null, name, null);
}
- @Deprecated
- public SolrConfig(String file, InputStream is)
+ /** Creates a configuration instance from a configuration name and stream.
+ * A default resource loader will be created (@see SolrResourceLoader).
+ * If the stream is null, the resource loader will open the configuration stream.
+ * If the stream is not null, no attempt to load the resource will occur (the name is not used).
+ *@param name the configuration name
+ *@param is the configuration stream
+ */
+ public SolrConfig(String name, InputStream is)
throws ParserConfigurationException, IOException, SAXException {
- this( new SolrResourceLoader(null), file, is );
+ this( (SolrResourceLoader) null, name, is );
}
- /** Creates a configuration instance from an input stream. */
- public SolrConfig(String instanceDir, String file, InputStream is)
+ /** Creates a configuration instance from an instance directory, configuration name and stream.
+ *@param instanceDir the directory used to create the resource loader
+ *@param name the configuration name used by the loader if the stream is null
+ *@param is the configuration stream
+ */
+ public SolrConfig(String instanceDir, String name, InputStream is)
throws ParserConfigurationException, IOException, SAXException {
- this(new SolrResourceLoader(instanceDir), file, is);
+ this(new SolrResourceLoader(instanceDir), name, is);
}
- SolrConfig(SolrResourceLoader loader, String file, InputStream is)
+ /** Creates a configuration instance from a resource loader, a configuration name and a stream.
+ * If the stream is null, the resource loader will open the configuration stream.
+ * If the stream is not null, no attempt to load the resource will occur (the name is not used).
+ *@param loader the resource loader
+ *@param name the configuration name
+ *@param is the configuration stream
+ */
+ SolrConfig(SolrResourceLoader loader, String name, InputStream is)
throws ParserConfigurationException, IOException, SAXException {
- super(loader, file, is, "/config/");
- this.configFile = file;
+ super(loader, name, is, "/config/");
defaultIndexConfig = new SolrIndexConfig(this, null, null);
mainIndexConfig = new SolrIndexConfig(this, "mainIndex", defaultIndexConfig);
@@ -123,7 +133,7 @@
pingQueryParams = readPingQueryParams(this);
httpCachingConfig = new HttpCachingConfig(this);
- Config.log.info("Loaded SolrConfig: " + file);
+ Config.log.info("Loaded SolrConfig: " + name);
// TODO -- at solr 2.0. this should go away
config = this;
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Mon Mar 3 20:06:17 2008
@@ -43,7 +43,6 @@
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.handler.PingRequestHandler;
import org.apache.solr.handler.component.DebugComponent;
import org.apache.solr.handler.component.FacetComponent;
import org.apache.solr.handler.component.HighlightComponent;
@@ -91,7 +90,6 @@
private final SolrConfig solrConfig;
private final IndexSchema schema;
private final String dataDir;
- private final String index_path;
private final UpdateHandler updateHandler;
private final long startTime;
private final RequestHandlers reqHandlers;
@@ -118,23 +116,68 @@
}
}
- public SolrConfig getSolrConfig() {
- return solrConfig;
- }
/**
+ * The SolrResourceLoader used to load all resources for this core.
* @since solr 1.3
*/
public SolrResourceLoader getResourceLoader() {
return solrConfig.getResourceLoader();
}
+ /**
+ * Gets the configuration resource name used by this core instance.
+ * @since solr 1.3
+ */
+ public String getConfigResource() {
+ return solrConfig.getResourceName();
+ }
+
+ /**
+ * Gets the configuration resource name used by this core instance.
+ * @see getConfigResource
+ */
+ @Deprecated
public String getConfigFile() {
- return solrConfig.configFile;
+ return solrConfig.getResourceName();
+ }
+ /**
+ * Gets the configuration object used by this core instance.
+ */
+ public SolrConfig getSolrConfig() {
+ return solrConfig;
}
+ /**
+ * Gets the schema resource name used by this core instance.
+ * @since solr 1.3
+ */
+ public String getSchemaResource() {
+ return schema.getResourceName();
+ }
+
+ /**
+ * Gets the schema resource name used by this core instance.
+ * @see getSchemaResource
+ */
+ @Deprecated
public String getSchemaFile() {
- return schema.getSchemaFile();
+ return schema.getResourceName();
+ }
+
+ /**
+ * Gets the schema object used by this core instance.
+ */
+ public IndexSchema getSchema() {
+ return schema;
+ }
+
+ public String getDataDir() {
+ return dataDir;
+ }
+
+ public String getIndexDir() {
+ return dataDir + "index/";
}
public String getName() {
@@ -183,9 +226,6 @@
newSearcherListeners = parseListener("//listener[@event=\"newSearcher\"]");
}
- public IndexSchema getSchema() { return schema; }
- public String getDataDir() { return dataDir; }
- public String getIndexDir() { return index_path; }
// gets a non-caching searcher
public SolrIndexSearcher newSearcher(String name) throws IOException {
@@ -305,19 +345,19 @@
instance = this; // set singleton
this.setName( name );
SolrResourceLoader loader = config.getResourceLoader();
- if (dataDir ==null) {
- dataDir = config.get("dataDir",loader.getInstanceDir()+"data");
- }
+ if (dataDir == null)
+ dataDir = config.get("dataDir",loader.getInstanceDir()+"data/");
+ else
+ dataDir = SolrResourceLoader.normalizeDir(dataDir);
log.info(logid+"Opening new SolrCore at " + loader.getInstanceDir() + ", dataDir="+dataDir);
if (schema==null) {
- schema = new IndexSchema(config, "schema.xml");
+ schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);
}
this.schema = schema;
this.dataDir = dataDir;
- this.index_path = dataDir + "/" + "index";
this.solrConfig = config;
this.startTime = System.currentTimeMillis();
this.maxWarmingSearchers = config.getInt("query/maxWarmingSearchers",Integer.MAX_VALUE);
@@ -665,7 +705,7 @@
// if this fails, we need to decrement onDeckSearchers again.
SolrIndexSearcher tmp;
try {
- tmp = new SolrIndexSearcher(this, schema, "main", index_path, true);
+ tmp = new SolrIndexSearcher(this, schema, "main", getIndexDir(), true);
} catch (Throwable th) {
synchronized(searcherLock) {
onDeckSearchers--;
Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrResourceLoader.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrResourceLoader.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrResourceLoader.java Mon Mar 3 20:06:17 2008
@@ -70,7 +70,8 @@
* <p>
* This loader will delegate to the context classloader when possible,
* otherwise it will attempt to resolve resources using any jar files
- * found in the "lib/" directory in the "Solr Home" directory.
+ * found in the "lib/" directory in the specified instance directory.
+ * If the instance directory is not specified (=null), SolrResourceLoader#locateInstanceDir will provide one.
* <p>
*/
public SolrResourceLoader( String instanceDir, ClassLoader parent )
@@ -110,37 +111,55 @@
this( instanceDir, null );
}
- protected static String normalizeDir(String path) {
- if (path==null) return null;
- if ( !(path.endsWith("/") || path.endsWith("\\")) ) {
- path+='/';
- }
- return path;
+ /** Ensures a directory name allways ends with a '/'. */
+ public static String normalizeDir(String path) {
+ return ( path != null && (!(path.endsWith("/") || path.endsWith("\\"))) )? path + '/' : path;
}
public String getConfigDir() {
return instanceDir + "conf/";
}
+ /** Opens a schema resource by its name.
+ * Override this method to customize loading schema resources.
+ *@return the stream for the named schema
+ */
+ public InputStream openSchema(String name) {
+ return openResource(name);
+ }
+
+ /** Opens a config resource by its name.
+ * Override this method to customize loading config resources.
+ *@return the stream for the named configuration
+ */
+ public InputStream openConfig(String name) {
+ return openResource(name);
+ }
+
+ /** Opens any resource by its name.
+ * By default, this will look in multiple locations to load the resource:
+ * $configDir/$resource (if resource is not absolute)
+ * $CWD/$resource
+ * otherwise, it will look for it in any jar accessible through the class loader.
+ * Override this method to customize loading resources.
+ *@return the stream for the named resource
+ */
public InputStream openResource(String resource) {
InputStream is=null;
-
try {
- File f = new File(resource);
+ File f0 = new File(resource);
+ File f = f0;
if (!f.isAbsolute()) {
- // try $CWD/conf/
+ // try $CWD/$configDir/$resource
f = new File(getConfigDir() + resource);
}
if (f.isFile() && f.canRead()) {
return new FileInputStream(f);
- } else {
- // try $CWD
- f = new File(resource);
- if (f.isFile() && f.canRead()) {
- return new FileInputStream(f);
- }
+ } else if (f != f0) { // no success with $CWD/$configDir/$resource
+ if (f0.isFile() && f0.canRead())
+ return new FileInputStream(f0);
}
-
+ // delegate to the class loader (looking into $INSTANCE_DIR/lib jars)
is = classLoader.getResourceAsStream(resource);
} catch (Exception e) {
throw new RuntimeException("Error opening " + resource, e);
@@ -257,7 +276,12 @@
}
waitingForResources.clear();
}
-
+ /**
+ * Determines the instanceDir from the environment.
+ * Tries JNDI (java:comp/env/solr/home) then system property (solr.solr.home);
+ * if both fail, defaults to solr/
+ * @return the instance directory name
+ */
/**
* Finds the instanceDir based on looking up the value in one of three places:
* <ol>
Modified: lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java Mon Mar 3 20:06:17 2008
@@ -28,6 +28,7 @@
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.MultiCore;
import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
@@ -64,6 +65,7 @@
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
"MultiCore support must be enabled at startup." );
}
+ boolean do_persist = false;
// Pick the action
SolrParams params = req.getParams();
@@ -78,68 +80,101 @@
}
}
- // Select the core
SolrCore core = null;
- String cname = params.get( MultiCoreParams.CORE );
- if( cname != null ) {
- core = manager.getCore( cname );
- if( core == null ) {
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
- "Unknown core: "+cname );
- }
- }
-
- // Handle a Status Request
+ // Handle a core creation
//---------------------------------------------------------
- if( action == MultiCoreAction.STATUS ) {
- SolrCore defaultCore = manager.getDefaultCore();
- NamedList<Object> status = new SimpleOrderedMap<Object>();
- if( core == null ) {
- for( SolrCore c : manager.getCores() ) {
- status.add( c.getName(), getCoreStatus( c, c==defaultCore ) );
- }
- }
- else {
- status.add( core.getName(), getCoreStatus( core, core==defaultCore ) );
- }
- rsp.add( "status", status );
- }
- else if( core == null ) {
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
- "Action '"+action+"' requires a core name." );
+ if (action == MultiCoreAction.CREATE) {
+ CoreDescriptor dcore = new CoreDescriptor();
+ dcore.init(params.get(MultiCoreParams.NAME),
+ params.get(MultiCoreParams.INSTANCE_DIR));
+
+ // fillup optional parameters
+ String opts = params.get(MultiCoreParams.CONFIG);
+ if (opts != null)
+ dcore.setConfigName(opts);
+
+ opts = params.get(MultiCoreParams.SCHEMA);
+ if (opts != null)
+ dcore.setSchemaName(opts);
+
+ core = manager.create(dcore);
+ rsp.add("core", core.getName());
+ do_persist = manager.isPersistent();
}
else {
- switch( action ) {
-
- case RELOAD: {
- manager.reload( core );
- break;
- }
-
- case SWAP: {
- String name = required.get( MultiCoreParams.WITH );
- SolrCore swap = manager.getCore( name );
- if( swap == null ) {
+ // Select the core
+ String cname = params.get( MultiCoreParams.CORE );
+ if( cname != null ) {
+ core = manager.getCore(cname);
+ if( core == null ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
- "Unknown core: "+name );
+ "Unknown core: "+cname );
}
- manager.swap( core, swap );
- break;
- }
-
- default:
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
- "TODO: IMPLEMENT: " + action );
}
- // Should we persist the changes?
- if( params.getBool( MultiCoreParams.PERSISTENT, manager.isPersistent() ) ) {
- rsp.add( "TODO", "SAVE THE CHANGES: "+manager.getConfigFile().getAbsolutePath() );
+ // Handle a Status Request
+ //---------------------------------------------------------
+ if( action == MultiCoreAction.STATUS ) {
+ do_persist = false; // no state change
+ NamedList<Object> status = new SimpleOrderedMap<Object>();
+ if( core == null ) {
+ for (CoreDescriptor d : manager.getDescriptors()) {
+ status.add(d.getName(), getCoreStatus( d.getCore() ) );
+ }
+ }
+ else {
+ status.add(core.getName(), getCoreStatus(core) );
+ }
+ rsp.add( "status", status );
+ }
+ else if (core == null) {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
+ "Action '"+action+"' requires a core name." );
+ }
+ else {
+ // Handle all other
+ //---------------------------------------------------------
+ do_persist = params.getBool(MultiCoreParams.PERSISTENT, manager.isPersistent());
+ switch( action ) {
+ case RELOAD: {
+ manager.reload( manager.getDescriptor( core.getName() ) );
+ do_persist = false; // no change on reload
+ break;
+ }
+
+ case SWAP: {
+ String name = required.get( MultiCoreParams.WITH );
+ CoreDescriptor swap = manager.getDescriptor( name );
+
+ if( swap == null ) {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
+ "Unknown core: "+name );
+ }
+ manager.swap( manager.getDescriptor( core.getName() ), swap );
+ break;
+ }
+
+ case PERSIST: {
+ do_persist = true;
+ break;
+ }
+
+ default: {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
+ "TODO: IMPLEMENT: " + action );
+ }
+ } // switch
}
}
+
+ // Should we persist the changes?
+ if (do_persist) {
+ manager.persist();
+ rsp.add("saved", manager.getConfigFile().getAbsolutePath());
+ }
}
- private static NamedList<Object> getCoreStatus( SolrCore core, boolean isDefault ) throws IOException
+ private static NamedList<Object> getCoreStatus( SolrCore core ) throws IOException
{
NamedList<Object> info = new SimpleOrderedMap<Object>();
info.add( "name", core.getName() );
@@ -147,7 +182,6 @@
info.add( "dataDir", core.getDataDir() );
info.add( "startTime", new Date( core.getStartTime() ) );
info.add( "uptime", System.currentTimeMillis()-core.getStartTime() );
- info.add( "isDefault", isDefault );
RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
info.add( "index", LukeRequestHandler.getIndexInfo( searcher.get().getReader(), false ) );
searcher.decref();
Modified: lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java Mon Mar 3 20:06:17 2008
@@ -45,6 +45,7 @@
import javax.xml.xpath.XPathFactory;
import java.io.InputStream;
import java.io.Reader;
+import java.io.IOException;
import java.util.*;
import java.util.logging.Logger;
@@ -59,7 +60,7 @@
final static Logger log = Logger.getLogger(IndexSchema.class.getName());
private final SolrConfig solrConfig;
- private final String schemaFile;
+ private final String resourceName;
private String name;
private float version;
@@ -70,17 +71,33 @@
* @see Config#openResource
*/
@Deprecated
- public IndexSchema(SolrConfig solrConfig, String schemaFile) {
- this(solrConfig, solrConfig.getResourceLoader().openResource(schemaFile));
+ public IndexSchema(SolrConfig solrConfig, String name) {
+ this(solrConfig, name, null);
}
-
- public IndexSchema(SolrConfig solrConfig, InputStream is) {
+ /**
+ * Constructs a schema using the specified resource name and stream.
+ * If the is stream is null, the resource loader will load the schema resource by name.
+ * @see SolrResourceLoader#openSchema
+ * By default, this follows the normal config path directory searching rules.
+ * @see Config#openResource
+ */
+ public IndexSchema(SolrConfig solrConfig, String name, InputStream is) {
this.solrConfig = solrConfig;
- this.schemaFile = DEFAULT_SCHEMA_FILE;
-
- readSchema(is);
-
+ if (name == null)
+ name = DEFAULT_SCHEMA_FILE;
+ this.resourceName = name;
SolrResourceLoader loader = solrConfig.getResourceLoader();
+ InputStream lis = is;
+ if (lis == null)
+ lis = loader.openSchema(name);
+ readSchema(lis);
+ if (lis != is) {
+ try {
+ lis.close();
+ }
+ catch(IOException xio) {} // ignore
+ }
+
loader.inform( loader );
}
@@ -88,26 +105,42 @@
return solrConfig;
}
+
+ /** Gets the name of the resource used to instantiate this schema. */
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ /** Gets the name of the schema as specified in the schema resource. */
+ public String getSchemaName() {
+ return name;
+ }
+
+ float getVersion() {
+ return version;
+ }
+
/**
* Direct access to the InputStream for the schemaFile used by this instance.
- *
* @see Config#openResource
*/
@Deprecated
public InputStream getInputStream() {
- return solrConfig.getResourceLoader().openResource(schemaFile);
+ return solrConfig.getResourceLoader().openResource(resourceName);
}
- /** Gets the name of the schema file. */
+ /** Gets the name of the schema file.
+ * @see IndexSchema#getResourceName
+ */
+ @Deprecated
public String getSchemaFile() {
- return schemaFile;
+ return resourceName;
}
- float getVersion() {
- return version;
- }
-
- /** The Name of this schema (as specified in the schema file) */
+ /** The Name of this schema (as specified in the schema file)
+ * @see IndexSchema#getSchemaName
+ */
+ @Deprecated
public String getName() { return name; }
private final HashMap<String, SchemaField> fields = new HashMap<String,SchemaField>();
@@ -282,6 +315,7 @@
return getAnalyzer(fieldName).tokenStream(fieldName,reader);
}
+ @Override
public int getPositionIncrementGap(String fieldName) {
return getAnalyzer(fieldName).getPositionIncrementGap(fieldName);
}
@@ -289,6 +323,7 @@
private class SolrQueryAnalyzer extends SolrIndexAnalyzer {
+ @Override
protected HashMap<String,Analyzer> analyzerCache() {
HashMap<String,Analyzer> cache = new HashMap<String,Analyzer>();
for (SchemaField f : getFields().values()) {
@@ -298,6 +333,7 @@
return cache;
}
+ @Override
protected Analyzer getAnalyzer(String fieldName)
{
Analyzer analyzer = analyzers.get(fieldName);
@@ -309,12 +345,9 @@
log.info("Reading Solr Schema");
try {
- /***
- DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- Document document = builder.parse(getInputStream());
- ***/
-
- Config schemaConf = new Config("schema", is, "/schema/");
+ // pass the config resource loader to avoid building an empty one for no reason:
+ // in the current case though, the stream is valid so we wont load the resource by name
+ Config schemaConf = new Config(solrConfig.getResourceLoader(), "schema", is, "/schema/");
Document document = schemaConf.getDocument();
final XPath xpath = schemaConf.getXPath();
Modified: lucene/solr/trunk/src/test/org/apache/solr/servlet/SolrRequestParserTest.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/org/apache/solr/servlet/SolrRequestParserTest.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/test/org/apache/solr/servlet/SolrRequestParserTest.java (original)
+++ lucene/solr/trunk/src/test/org/apache/solr/servlet/SolrRequestParserTest.java Mon Mar 3 20:06:17 2008
@@ -35,7 +35,6 @@
import org.apache.solr.common.params.MultiMapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream;
-import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.util.AbstractSolrTestCase;
@@ -48,7 +47,7 @@
public void setUp() throws Exception {
super.setUp();
- parser = new SolrRequestParsers( true, Long.MAX_VALUE );
+ parser = new SolrRequestParsers( h.getCore().getSolrConfig() );
}
public void testStreamBody() throws Exception
Modified: lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java (original)
+++ lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java Mon Mar 3 20:06:17 2008
@@ -41,7 +41,7 @@
* DirectSolrConnection provides an interface to solr that is similar to
* the the HTTP interface, but does not require an HTTP connection.
*
- * This class is designed to be as simple as possible and alow for more flexibility
+ * This class is designed to be as simple as possible and allow for more flexibility
* in how you interface to solr.
*
* @version $Id$
@@ -57,8 +57,7 @@
*/
public DirectSolrConnection()
{
- core = SolrCore.getSolrCore();
- parser = new SolrRequestParsers( true, Long.MAX_VALUE );
+ this( SolrCore.getSolrCore() );
}
/**
@@ -67,7 +66,7 @@
public DirectSolrConnection( SolrCore c )
{
core = c;
- parser = new SolrRequestParsers( true, Long.MAX_VALUE );
+ parser = new SolrRequestParsers( c.getSolrConfig() );
}
/**
@@ -99,16 +98,16 @@
}
}
- // Initalize SolrConfig
+ // Initialize SolrConfig
SolrConfig config = null;
try {
config = new SolrConfig(instanceDir, SolrConfig.DEFAULT_CONF_FILE, null);
instanceDir = config.getResourceLoader().getInstanceDir();
// If the Data directory is specified, initialize SolrCore directly
- IndexSchema schema = new IndexSchema(config, instanceDir+"/conf/schema.xml");
+ IndexSchema schema = new IndexSchema(config, instanceDir+"/conf/schema.xml", null);
core = new SolrCore( null, dataDir, config, schema );
- parser = new SolrRequestParsers( true, Long.MAX_VALUE );
+ parser = new SolrRequestParsers( config );
}
catch (Exception ee) {
throw new RuntimeException(ee);
Modified: lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java Mon Mar 3 20:06:17 2008
@@ -21,6 +21,8 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.Collection;
+import java.util.WeakHashMap;
import java.util.logging.Logger;
import java.util.logging.Level;
@@ -35,7 +37,6 @@
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.core.Config;
import org.apache.solr.core.MultiCore;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
@@ -49,6 +50,8 @@
/**
* This filter looks at the incoming URL maps them to handlers defined in solrconfig.xml
+ *
+ * @since solr 1.2
*/
public class SolrDispatchFilter implements Filter
{
@@ -56,10 +59,9 @@
protected SolrCore singlecore;
protected MultiCore multicore;
- protected SolrRequestParsers parsers;
- protected boolean handleSelect = false;
protected String pathPrefix = null; // strip this from the beginning of a path
protected String abortErrorMessage = null;
+ protected final WeakHashMap<SolrCore, SolrRequestParsers> parsers = new WeakHashMap<SolrCore, SolrRequestParsers>();
protected String solrConfigFilename = null;
public void init(FilterConfig config) throws ServletException
@@ -72,8 +74,6 @@
this.pathPrefix = config.getInitParameter( "path-prefix" );
this.solrConfigFilename = config.getInitParameter("solrconfig-filename");
- // Find a valid solr core
- SolrCore core = null;
multicore = MultiCore.getRegistry();
if( multicore.isEnabled() ) {
log.info( "Using existing multicore configuration" );
@@ -86,9 +86,18 @@
multicore.load( instanceDir, multiconfig );
}
}
+
+ abortOnConfigurationError = false;
if( multicore.isEnabled() ) {
singlecore = null;
- core = multicore.getDefaultCore();
+
+ // if any core aborts on startup, then abort
+ for( SolrCore c : multicore.getCores() ) {
+ if( c.getSolrConfig().getBool( "abortOnConfigurationError",false) ) {
+ abortOnConfigurationError = true;
+ break;
+ }
+ }
}
else {
if (this.solrConfigFilename==null) {
@@ -96,28 +105,8 @@
} else {
singlecore = new SolrCore( null, null, new SolrConfig(this.solrConfigFilename), null);
}
- core = singlecore;
}
-
log.info("user.dir=" + System.getProperty("user.dir"));
-
- // Read global configuration
- // Only the first registered core configures the following attributes
- Config globalConfig = core.getSolrConfig();
-
- long uploadLimitKB = globalConfig.getInt(
- "requestDispatcher/requestParsers/@multipartUploadLimitInKB", 2000 ); // 2MB default
-
- boolean enableRemoteStreams = globalConfig.getBool(
- "requestDispatcher/requestParsers/@enableRemoteStreaming", false );
-
- parsers = new SolrRequestParsers( enableRemoteStreams, uploadLimitKB );
-
- // Let this filter take care of /select?xxx format
- this.handleSelect = globalConfig.getBool( "requestDispatcher/@handleSelect", false );
-
- // should it keep going if we hit an error?
- abortOnConfigurationError = globalConfig.getBool("abortOnConfigurationError",true);
}
catch( Throwable t ) {
// catch this so our filter still works
@@ -197,50 +186,72 @@
SolrRequestHandler handler = null;
SolrCore core = singlecore;
if( core == null ) {
- // Perhaps this is a muli-core admin page?
+ // Perhaps this is a multi-core admin page?
+ if( path.equals( "/" ) ) {
+ chain.doFilter(request, response);
+ return;
+ }
if( path.equals( multicore.getAdminPath() ) ) {
handler = multicore.getMultiCoreHandler();
+
+ // pick a core to use for output
+ Collection<SolrCore> cores = multicore.getCores();
+ if( cores != null && cores.size() > 0 ) {
+ core = cores.iterator().next();
+ }
+ if( core == null ) {
+ throw new RuntimeException( "Can not find a valid core for the multicore admin handler" );
+ }
}
else {
idx = path.indexOf( "/", 1 );
- if( idx > 1 ) {
- // try to get the corename as a request parameter first
- String corename = path.substring( 1, idx );
- path = path.substring( idx );
- core = multicore.getCore( corename );
- // invalid core name is ok. It could fall through to some other request
+ if( idx <= 1 ) {
+ idx = path.length();
+ }
+
+ // try to get the corename as a request parameter first
+ String corename = path.substring( 1, idx );
+ path = path.substring( idx );
+ core = multicore.getCore( corename );
+
+ if( path.length() == 0 ) {
+ path = "/";
+ }
+
+ if( core == null ) {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown core: "+corename );
}
}
}
- if( core != null ) {
- // Only try to parse the handler *if* a valid core exists
- // when multi-core is enabled, the path can lead to a null core.
- if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
- handler = core.getRequestHandler( path );
- }
- if( handler == null && handleSelect ) {
- if( "/select".equals( path ) || "/select/".equals( path ) ) {
- solrReq = parsers.parse( core, path, req );
- String qt = solrReq.getParams().get( CommonParams.QT );
- if( qt != null && qt.startsWith( "/" ) ) {
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type. Do not use /select to access: "+qt);
- }
- handler = core.getRequestHandler( qt );
- if( handler == null ) {
- throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
- }
+ SolrRequestParsers parser = parsers.get( core );
+ if( parser == null ) {
+ parser = new SolrRequestParsers( core.getSolrConfig() );
+ parsers.put( core, parser );
+ }
+
+ // Only try to parse the handler *if* a valid core exists
+ // when multi-core is enabled, the path can lead to a null core.
+ if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
+ handler = core.getRequestHandler( path );
+ }
+ if( handler == null && parser.isHandleSelect() ) {
+ if( "/select".equals( path ) || "/select/".equals( path ) ) {
+ solrReq = parser.parse( core, path, req );
+ String qt = solrReq.getParams().get( CommonParams.QT );
+ if( qt != null && qt.startsWith( "/" ) ) {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type. Do not use /select to access: "+qt);
+ }
+ handler = core.getRequestHandler( qt );
+ if( handler == null ) {
+ throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
}
}
}
- if( handler != null ) {
- if( core == null ) {
- core = multicore.getDefaultCore();
- }
-
+ if( handler != null ) {
if( solrReq == null ) {
- solrReq = parsers.parse( core, path, req );
+ solrReq = parser.parse( core, path, req );
}
final SolrConfig conf = core.getSolrConfig();
@@ -253,8 +264,7 @@
// unless we have been explicitly told not to, do cache validation
if (!conf.getHttpCachingConfig().isNever304()) {
// if we've confirmed cache validation, return immediately
- if (HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq,
- req,resp)) {
+ if (HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req,resp)) {
return;
}
}
@@ -287,11 +297,11 @@
// the servlet/jsp can retrieve it
else {
req.setAttribute("org.apache.solr.SolrCore", core);
-
- // Modify the request so each core gets its own /admin
+
+ // Let each core have its own admin page...
if( singlecore == null && path.startsWith( "/admin" ) ) {
req.getRequestDispatcher( path ).forward( request, response );
- return;
+ return;
}
}
}
@@ -343,20 +353,6 @@
//---------------------------------------------------------------------
//---------------------------------------------------------------------
-
- /**
- * Should the filter handle /select even if it is not mapped in solrconfig.xml
- *
- * This will use consistent error handling for /select?qt=xxx and /update/xml
- *
- */
- public boolean isHandleSelect() {
- return handleSelect;
- }
-
- public void setHandleSelect(boolean handleSelect) {
- this.handleSelect = handleSelect;
- }
/**
* set the prefix for all paths. This is useful if you want to apply the
Modified: lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java?rev=633360&r1=633359&r2=633360&view=diff
==============================================================================
--- lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java (original)
+++ lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java Mon Mar 3 20:06:17 2008
@@ -42,6 +42,7 @@
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.core.Config;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.ServletSolrParams;
import org.apache.solr.request.SolrQueryRequest;
@@ -60,17 +61,38 @@
private HashMap<String, SolrRequestParser> parsers;
private boolean enableRemoteStreams = false;
+ private boolean handleSelect = true;
private StandardRequestParser standard;
- public SolrRequestParsers( boolean enableRemoteStreams, long uploadLimitKB )
+ /**
+ * Pass in an xml configuration. A null configuration will enable
+ * everythign with maximum values.
+ */
+ public SolrRequestParsers( Config globalConfig )
{
- this.enableRemoteStreams = enableRemoteStreams;
-
+ long uploadLimitKB = 1048; // 2MB default
+ if( globalConfig == null ) {
+ uploadLimitKB = Long.MAX_VALUE;
+ enableRemoteStreams = true;
+ handleSelect = true;
+ }
+ else {
+ uploadLimitKB = globalConfig.getInt(
+ "requestDispatcher/requestParsers/@multipartUploadLimitInKB", (int)uploadLimitKB );
+
+ enableRemoteStreams = globalConfig.getBool(
+ "requestDispatcher/requestParsers/@enableRemoteStreaming", false );
+
+ // Let this filter take care of /select?xxx format
+ handleSelect = globalConfig.getBool(
+ "requestDispatcher/@handleSelect", handleSelect );
+ }
+
MultipartRequestParser multi = new MultipartRequestParser( uploadLimitKB );
RawRequestParser raw = new RawRequestParser();
standard = new StandardRequestParser( multi, raw );
- // I don't see a need to have this publically configured just yet
+ // I don't see a need to have this publicly configured just yet
// adding it is trivial
parsers = new HashMap<String, SolrRequestParser>();
parsers.put( MULTIPART, multi );
@@ -178,6 +200,14 @@
}
}
return new MultiMapSolrParams( map );
+ }
+
+ public boolean isHandleSelect() {
+ return handleSelect;
+ }
+
+ public void setHandleSelect(boolean handleSelect) {
+ this.handleSelect = handleSelect;
}
}