From f14885cf0b3c6cb6dbc911eb994b2ca1c9c1e5a8 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Fri, 7 Dec 2007 03:49:52 +0000 Subject: [PATCH] SOLR-350, SOLR-409 -- adding configurable support for running multiple cores in one sole instance git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@601975 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/solr/client/solrj/SolrRequest.java | 1 + .../solrj/embedded/EmbeddedSolrServer.java | 47 ++- .../solrj/impl/CommonsHttpSolrServer.java | 5 + .../solrj/request/MultiCoreRequest.java | 127 ++++++++ .../client/solrj/request/RequestBase.java | 9 + .../client/solrj/request/UpdateRequest.java | 9 +- .../solrj/response/MultiCoreResponse.java | 60 ++++ .../solrj/MultiCoreExampleTestBase.java | 120 ++++++++ .../client/solrj/SolrExampleTestBase.java | 15 +- .../solrj/embedded/LargeVolumeJettyTest.java | 15 - .../solrj/embedded/MultiCoreEmbeddedTest.java | 59 ++++ .../embedded/MultiCoreExampleJettyTest.java | 78 +++++ example/multicore/README.txt | 5 + example/multicore/core0/conf/schema.xml | 41 +++ example/multicore/core0/conf/solrconfig.xml | 44 +++ example/multicore/core1/conf/schema.xml | 41 +++ example/multicore/core1/conf/solrconfig.xml | 44 +++ example/multicore/multicore.xml | 32 +++ .../solr/common/params/MultiCoreParams.java | 53 ++++ src/java/org/apache/solr/core/Config.java | 6 +- src/java/org/apache/solr/core/MultiCore.java | 271 ++++++++++++++++++ .../org/apache/solr/core/RequestHandlers.java | 2 +- src/java/org/apache/solr/core/SolrConfig.java | 19 +- src/java/org/apache/solr/core/SolrCore.java | 54 ++-- .../apache/solr/core/SolrResourceLoader.java | 28 +- .../handler/admin/LukeRequestHandler.java | 2 +- .../solr/handler/admin/MultiCoreHandler.java | 173 +++++++++++ .../solr/update/DirectUpdateHandler.java | 8 +- .../solr/update/DirectUpdateHandler2.java | 6 +- .../org/apache/solr/util/TestHarness.java | 2 +- src/webapp/resources/admin/_info.jsp | 12 +- src/webapp/resources/admin/action.jsp | 2 +- src/webapp/resources/admin/analysis.jsp | 1 + .../resources/admin/distributiondump.jsp | 2 +- src/webapp/resources/admin/form.jsp | 2 +- src/webapp/resources/admin/header.jsp | 2 +- src/webapp/resources/admin/index.jsp | 40 ++- src/webapp/resources/admin/logging.jsp | 9 + src/webapp/resources/admin/logging.xsl | 208 ++++++++------ src/webapp/resources/admin/ping.jsp | 26 +- src/webapp/resources/admin/ping.xsl | 141 ++++----- src/webapp/resources/admin/raw-schema.jsp | 10 +- src/webapp/resources/admin/registry.jsp | 1 + src/webapp/resources/admin/registry.xsl | 5 +- src/webapp/resources/admin/stats.jsp | 1 + src/webapp/resources/admin/stats.xsl | 5 +- src/webapp/resources/admin/threaddump.jsp | 14 +- src/webapp/resources/admin/threaddump.xsl | 205 ++++++------- .../solr/servlet/DirectSolrConnection.java | 2 +- .../solr/servlet/SolrDispatchFilter.java | 78 ++++- 50 files changed, 1755 insertions(+), 387 deletions(-) create mode 100644 client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java create mode 100644 client/java/solrj/src/org/apache/solr/client/solrj/response/MultiCoreResponse.java create mode 100644 client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java create mode 100644 client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java create mode 100644 client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreExampleJettyTest.java create mode 100644 example/multicore/README.txt create mode 100644 example/multicore/core0/conf/schema.xml create mode 100644 example/multicore/core0/conf/solrconfig.xml create mode 100644 example/multicore/core1/conf/schema.xml create mode 100644 example/multicore/core1/conf/solrconfig.xml create mode 100644 example/multicore/multicore.xml create mode 100644 src/java/org/apache/solr/common/params/MultiCoreParams.java create mode 100644 src/java/org/apache/solr/core/MultiCore.java create mode 100644 src/java/org/apache/solr/handler/admin/MultiCoreHandler.java diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/SolrRequest.java b/client/java/solrj/src/org/apache/solr/client/solrj/SolrRequest.java index 4b442e66c89..cdb2c78f18f 100644 --- a/client/java/solrj/src/org/apache/solr/client/solrj/SolrRequest.java +++ b/client/java/solrj/src/org/apache/solr/client/solrj/SolrRequest.java @@ -37,6 +37,7 @@ public interface SolrRequest extends Serializable }; public String getPath(); + public String getCore(); // the name of requested core public METHOD getMethod(); public SolrParams getParams(); public Collection getContentStreams() throws IOException; diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java b/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java index a90a2214863..3dcf5117cd7 100644 --- a/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java +++ b/client/java/solrj/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java @@ -32,6 +32,7 @@ import org.apache.solr.common.params.DefaultSolrParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; +import org.apache.solr.core.MultiCore; import org.apache.solr.core.SolrCore; import org.apache.solr.request.QueryResponseWriter; import org.apache.solr.request.SolrQueryRequest; @@ -55,18 +56,33 @@ public class EmbeddedSolrServer extends BaseSolrServer protected final SolrCore core; protected final SolrRequestParsers parser; + protected boolean useMultiCore; public EmbeddedSolrServer( SolrCore core ) { this.core = core; - this.parser = new SolrRequestParsers( true, Long.MAX_VALUE ); + this.useMultiCore = false; + this.parser = init(); + } - // by default use the XML one + public EmbeddedSolrServer() + { + this( null ); + if( MultiCore.getRegistry().getDefaultCore() == null ) { + throw new RuntimeException( "Must initialize multicore if you want to use this" ); + } + this.useMultiCore = true; + } + + private SolrRequestParsers init() + { _processor = new XMLResponseParser(); _invariantParams = new ModifiableSolrParams(); _invariantParams.set( CommonParams.WT, _processor.getWriterType() ); _invariantParams.set( CommonParams.VERSION, "2.2" ); + + return new SolrRequestParsers( true, Long.MAX_VALUE ); } public NamedList request(SolrRequest request) throws SolrServerException, IOException @@ -76,6 +92,26 @@ public class EmbeddedSolrServer extends BaseSolrServer path = "/select"; } + // Check for multicore action + SolrCore core = this.core; + MultiCore multicore = MultiCore.getRegistry(); + if( useMultiCore ) { + if( request.getCore() != null ) { + if( !multicore.isEnabled() ) { + throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, + "multicore access is not enabled" ); + } + core = multicore.getCore( request.getCore() ); + if( core == null ) { + throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, + "Unknown core: "+request.getCore() ); + } + } + else { + core = multicore.getDefaultCore(); + } + } + SolrParams params = request.getParams(); if( params == null ) { params = new ModifiableSolrParams(); @@ -94,6 +130,13 @@ public class EmbeddedSolrServer extends BaseSolrServer throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt); } } + // Perhaps the path is to manage the cores + if( handler == null && + useMultiCore && + path.equals( multicore.getAdminPath() ) && + multicore.isEnabled() ) { + handler = multicore.getMultiCoreHandler(); + } } if( handler == null ) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+path ); diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/impl/CommonsHttpSolrServer.java b/client/java/solrj/src/org/apache/solr/client/solrj/impl/CommonsHttpSolrServer.java index 48fcebb3093..f898e74a2d0 100644 --- a/client/java/solrj/src/org/apache/solr/client/solrj/impl/CommonsHttpSolrServer.java +++ b/client/java/solrj/src/org/apache/solr/client/solrj/impl/CommonsHttpSolrServer.java @@ -116,6 +116,11 @@ public class CommonsHttpSolrServer extends BaseSolrServer path = "/select"; } + // modify the path for multicore access + if( request.getCore() != null ) { + path = "/@"+request.getCore()+path; + } + if( params == null ) { params = new ModifiableSolrParams(); } diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java b/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java new file mode 100644 index 00000000000..f265b388b41 --- /dev/null +++ b/client/java/solrj/src/org/apache/solr/client/solrj/request/MultiCoreRequest.java @@ -0,0 +1,127 @@ +/** + * 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.client.solrj.request; + +import java.io.IOException; +import java.util.Collection; + +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.MultiCoreResponse; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.MultiCoreParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.params.MultiCoreParams.MultiCoreAction; +import org.apache.solr.common.util.ContentStream; + +/** + * + * @version $Id$ + * @since solr 1.3 + */ +public class MultiCoreRequest extends RequestBase +{ + private MultiCoreParams.MultiCoreAction action = null; + private String core = null; + + public MultiCoreRequest() + { + super( METHOD.GET, "/admin/multicore" ); + } + + public MultiCoreRequest( String path ) + { + super( METHOD.GET, path ); + } + + @Override + public final void setCore( String v ) + { + this.core = v; + // this does not change the path! + } + + //--------------------------------------------------------------------------------------- + // + //--------------------------------------------------------------------------------------- + + public void setAction( MultiCoreAction action ) + { + this.action = action; + } + + //--------------------------------------------------------------------------------------- + // + //--------------------------------------------------------------------------------------- + + 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 ); + return params; + } + + //--------------------------------------------------------------------------------------- + // + //--------------------------------------------------------------------------------------- + + public Collection getContentStreams() throws IOException { + return null; + } + + public MultiCoreResponse process(SolrServer server) throws SolrServerException, IOException + { + long startTime = System.currentTimeMillis(); + MultiCoreResponse res = new MultiCoreResponse( server.request( this ) ); + res.setElapsedTime( System.currentTimeMillis()-startTime ); + return res; + } + + //--------------------------------------------------------------------------------------- + // + //--------------------------------------------------------------------------------------- + + public static MultiCoreResponse setDefault( String name, SolrServer server ) throws SolrServerException, IOException + { + MultiCoreRequest req = new MultiCoreRequest(); + req.setCore( name ); + req.setAction( MultiCoreAction.SETASDEFAULT ); + return req.process( server ); + } + + public static MultiCoreResponse reloadCore( String name, SolrServer server ) throws SolrServerException, IOException + { + MultiCoreRequest req = new MultiCoreRequest(); + req.setCore( name ); + req.setAction( MultiCoreAction.RELOAD ); + return req.process( server ); + } + + public static MultiCoreResponse getStatus( String name, SolrServer server ) throws SolrServerException, IOException + { + MultiCoreRequest req = new MultiCoreRequest(); + req.setAction( MultiCoreAction.STATUS ); + req.setCore( name ); + return req.process( server ); + } +} + diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/request/RequestBase.java b/client/java/solrj/src/org/apache/solr/client/solrj/request/RequestBase.java index 0c775ad70b7..6c5d474522d 100644 --- a/client/java/solrj/src/org/apache/solr/client/solrj/request/RequestBase.java +++ b/client/java/solrj/src/org/apache/solr/client/solrj/request/RequestBase.java @@ -28,6 +28,7 @@ public abstract class RequestBase implements SolrRequest { private METHOD method = METHOD.GET; private String path = null; + private String core = null; //--------------------------------------------------------- //--------------------------------------------------------- @@ -54,4 +55,12 @@ public abstract class RequestBase implements SolrRequest public void setPath(String path) { this.path = path; } + + public String getCore() { + return core; + } + + public void setCore(String core) { + this.core = core; + } } diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java b/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java index 7d499c8cdf4..f2297f3a2c4 100644 --- a/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java +++ b/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java @@ -150,16 +150,18 @@ public class UpdateRequest extends RequestBase } // Add the delete commands - if( deleteById != null || deleteQuery != null ) { + boolean deleteI = deleteById != null && deleteById.size() > 0; + boolean deleteQ = deleteQuery != null && deleteQuery.size() > 0; + if( deleteI || deleteQ ) { writer.append( "" ); - if( deleteById != null ) { + if( deleteI ) { for( String id : deleteById ) { writer.append( "" ); XML.escapeCharData( id, writer ); writer.append( "" ); } } - if( deleteQuery != null ) { + if( deleteQ ) { for( String q : deleteQuery ) { writer.append( "" ); XML.escapeCharData( q, writer ); @@ -171,6 +173,7 @@ public class UpdateRequest extends RequestBase // If action is COMMIT or OPTIMIZE, it is sent with params String xml = writer.toString(); + //System.out.println( "SEND:"+xml ); return (xml.length() > 0) ? xml : null; } diff --git a/client/java/solrj/src/org/apache/solr/client/solrj/response/MultiCoreResponse.java b/client/java/solrj/src/org/apache/solr/client/solrj/response/MultiCoreResponse.java new file mode 100644 index 00000000000..fe15e1e8331 --- /dev/null +++ b/client/java/solrj/src/org/apache/solr/client/solrj/response/MultiCoreResponse.java @@ -0,0 +1,60 @@ +/** + * 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.client.solrj.response; + +import java.util.Date; +import java.util.List; + +import org.apache.solr.common.util.NamedList; + + +public class MultiCoreResponse extends SolrResponseBase +{ + public MultiCoreResponse(NamedList res) { + super(res); + } + + @SuppressWarnings("unchecked") + public NamedList> getCoreStatus() + { + return (NamedList>) getResponse().get( "status" ); + } + + public NamedList getCoreStatus( String core ) + { + return getCoreStatus().get( core ); + } + + public Date getStartTime( String core ) + { + NamedList v = getCoreStatus( core ); + if( v == null ) { + return null; + } + return (Date) v.get( "startTime" ); + } + + public Long getUptime( String core ) + { + NamedList v = getCoreStatus( core ); + if( v == null ) { + return null; + } + return (Long) v.get( "uptime" ); + } +} \ No newline at end of file diff --git a/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java b/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java new file mode 100644 index 00000000000..489aadd3819 --- /dev/null +++ b/client/java/solrj/test/org/apache/solr/client/solrj/MultiCoreExampleTestBase.java @@ -0,0 +1,120 @@ +/** + * 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.client.solrj; + +import org.apache.solr.client.solrj.request.LukeRequest; +import org.apache.solr.client.solrj.request.MultiCoreRequest; +import org.apache.solr.client.solrj.request.QueryRequest; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.client.solrj.request.UpdateRequest.ACTION; +import org.apache.solr.client.solrj.response.LukeResponse; +import org.apache.solr.client.solrj.response.MultiCoreResponse; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + + +/** + * @version $Id$ + * @since solr 1.3 + */ +public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase +{ + @Override public String getSolrHome() { return "../../../example/multicore/"; } + + @Override public String getSchemaFile() { return getSolrHome()+"core0/conf/schema.xml"; } + @Override public String getSolrConfigFile() { return getSolrHome()+"core0/conf/solrconfig.xml"; } + + + public void testMultiCore() throws Exception + { + SolrServer solr = getSolrServer(); + + MultiCoreRequest.setDefault( "core1", solr ); + MultiCoreRequest.setDefault( "core0", solr ); + + UpdateRequest up = new UpdateRequest(); + up.setAction( ACTION.COMMIT, true, true ); + up.setCore( "core0" ); + up.deleteByQuery( "*:*" ); + up.process( solr ); + up.setCore( "core1" ); + up.process( solr ); + up.clear(); + + // Add something to each core + SolrInputDocument doc = new SolrInputDocument(); + doc.setField( "id", "AAA" ); + doc.setField( "core0", "yup" ); + + // Add to core0 + up.setCore( "core0" ); + up.add( doc ); + up.process( solr ); + + // You can't add it to core1 + try { + up.setCore( "core1" ); + up.process( solr ); + fail( "Can't add core0 field to core1!" ); + } + catch( Exception ex ) {} + + // Add to core1 + up.setCore( "core1" ); + doc.setField( "id", "BBB" ); + doc.setField( "core1", "yup" ); + doc.removeField( "core0" ); + up.add( doc ); + up.process( solr ); + + // You can't add it to core1 + try { + up.setCore( "core0" ); + up.process( solr ); + fail( "Can't add core1 field to core0!" ); + } + catch( Exception ex ) {} + + // now Make sure AAA is in 0 and BBB in 1 + SolrQuery q = new SolrQuery(); + QueryRequest r = new QueryRequest( q ); + r.setCore( "core0" ); + q.setQuery( "id:AAA" ); + assertEquals( 1, r.process( solr ).getResults().size() ); + r.setCore( "core1" ); + assertEquals( 0, r.process( solr ).getResults().size() ); + + // Now test Changing the default core + assertEquals( 1, solr.query( new SolrQuery( "id:AAA" ) ).getResults().size() ); + assertEquals( 0, solr.query( new SolrQuery( "id:BBB" ) ).getResults().size() ); + MultiCoreRequest.setDefault( "core1", solr ); + assertEquals( 0, solr.query( new SolrQuery( "id:AAA" ) ).getResults().size() ); + assertEquals( 1, solr.query( new SolrQuery( "id:BBB" ) ).getResults().size() ); + + // Now test reloading it should have a newer open time + String name = "core0"; + MultiCoreResponse mcr = MultiCoreRequest.getStatus( name, solr ); + long before = mcr.getStartTime( name ).getTime(); + MultiCoreRequest.reloadCore( name, solr ); + + mcr = MultiCoreRequest.getStatus( name, solr ); + long after = mcr.getStartTime( name ).getTime(); + assertTrue( "should have more recent time: "+after+","+before, after > before ); + } +} diff --git a/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTestBase.java b/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTestBase.java index 307a9271d99..f2717ad624c 100644 --- a/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTestBase.java +++ b/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTestBase.java @@ -30,8 +30,19 @@ import org.apache.solr.util.AbstractSolrTestCase; */ abstract public class SolrExampleTestBase extends AbstractSolrTestCase { - @Override public String getSchemaFile() { return "../../../example/solr/conf/schema.xml"; } - @Override public String getSolrConfigFile() { return "../../../example/solr/conf/solrconfig.xml"; } + public String getSolrHome() { return "../../../example/solr/"; } + + @Override public String getSchemaFile() { return getSolrHome()+"conf/schema.xml"; } + @Override public String getSolrConfigFile() { return getSolrHome()+"conf/solrconfig.xml"; } + + @Override + public void setUp() throws Exception + { + super.setUp(); + + // this sets the property for jetty starting SolrDispatchFilter + System.setProperty( "solr.solr.home", this.getSolrHome() ); + } /** * Subclasses need to initialize the server impl diff --git a/client/java/solrj/test/org/apache/solr/client/solrj/embedded/LargeVolumeJettyTest.java b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/LargeVolumeJettyTest.java index a938435d6be..b7c87b8d3a5 100644 --- a/client/java/solrj/test/org/apache/solr/client/solrj/embedded/LargeVolumeJettyTest.java +++ b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/LargeVolumeJettyTest.java @@ -40,21 +40,6 @@ public class LargeVolumeJettyTest extends LargeVolumeTestBase { { super.setUp(); - SolrCore c = SolrCore.getSolrCore(); - System.out.println( c.getConfigFile() ); - System.out.println( c.getSolrConfig().configFile ); - System.out.println( c.getSchema().getFields() ); - - try { - SchemaField f = c.getSchema().getField( "cat" ); - System.out.println( f ); - } - catch( Exception ex ) { - ex.printStackTrace(); - } - System.out.println( "---" ); - - jetty = new JettySolrRunner( context, port ); jetty.start(); diff --git a/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java new file mode 100644 index 00000000000..e209dd79fe4 --- /dev/null +++ b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreEmbeddedTest.java @@ -0,0 +1,59 @@ +/** + * 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.client.solrj.embedded; + +import java.io.File; + +import org.apache.solr.client.solrj.MultiCoreExampleTestBase; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.core.MultiCore; + +/** + * This runs SolrServer test using + * + * @version $Id$ + * @since solr 1.3 + */ +public class MultiCoreEmbeddedTest extends MultiCoreExampleTestBase { + + SolrServer server; + + @Override public void setUp() throws Exception + { + super.setUp(); + + File home = new File( getSolrHome() ); + File f = new File( home, "multicore.xml" ); + MultiCore.getRegistry().load( getSolrHome(), f ); + + // setup the server... + server = createNewSolrServer(); + } + + @Override + protected SolrServer getSolrServer() + { + return server; + } + + @Override + protected SolrServer createNewSolrServer() + { + return new EmbeddedSolrServer(); + } +} diff --git a/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreExampleJettyTest.java b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreExampleJettyTest.java new file mode 100644 index 00000000000..7297de3dca2 --- /dev/null +++ b/client/java/solrj/test/org/apache/solr/client/solrj/embedded/MultiCoreExampleJettyTest.java @@ -0,0 +1,78 @@ +/** + * 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.client.solrj.embedded; + +import org.apache.solr.client.solrj.MultiCoreExampleTestBase; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; + +/** + * TODO? perhaps use: + * http://docs.codehaus.org/display/JETTY/ServletTester + * rather then open a real connection? + * + * @version $Id$ + * @since solr 1.3 + */ +public class MultiCoreExampleJettyTest extends MultiCoreExampleTestBase { + + SolrServer server; + JettySolrRunner jetty; + + static final int port = 8984; // not 8983 + static final String context = "/example"; + + @Override public void setUp() throws Exception + { + super.setUp(); + + jetty = new JettySolrRunner( context, port ); + jetty.start(); + + server = this.createNewSolrServer(); + } + + @Override public void tearDown() throws Exception + { + super.tearDown(); + jetty.stop(); // stop the server + } + + @Override + protected SolrServer getSolrServer() + { + return server; + } + + @Override + protected SolrServer createNewSolrServer() + { + try { + // setup the server... + String url = "http://localhost:"+port+context; + CommonsHttpSolrServer s = new CommonsHttpSolrServer( url ); + s.setConnectionTimeout(100); // 1/10th sec + s.setDefaultMaxConnectionsPerHost(100); + s.setMaxTotalConnections(100); + return s; + } + catch( Exception ex ) { + throw new RuntimeException( ex ); + } + } +} diff --git a/example/multicore/README.txt b/example/multicore/README.txt new file mode 100644 index 00000000000..99cf5f43993 --- /dev/null +++ b/example/multicore/README.txt @@ -0,0 +1,5 @@ +This is an alternative setup structure to support multipel cores. +This is an alternative setup structure to support multipel cores. + +For general examples on standard solr configuration, see the "solr" directory. +For general examples on standard solr configuration, see the "solr" directory. \ No newline at end of file diff --git a/example/multicore/core0/conf/schema.xml b/example/multicore/core0/conf/schema.xml new file mode 100644 index 00000000000..106f21c6734 --- /dev/null +++ b/example/multicore/core0/conf/schema.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + id + + + name + + + + + diff --git a/example/multicore/core0/conf/solrconfig.xml b/example/multicore/core0/conf/solrconfig.xml new file mode 100644 index 00000000000..f476fb5816d --- /dev/null +++ b/example/multicore/core0/conf/solrconfig.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + solr + solrconfig.xml schema.xml admin-extra.html + + qt=standard&q=solrpingquery + + + + + diff --git a/example/multicore/core1/conf/schema.xml b/example/multicore/core1/conf/schema.xml new file mode 100644 index 00000000000..44ffa852bc9 --- /dev/null +++ b/example/multicore/core1/conf/schema.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + id + + + name + + + + + diff --git a/example/multicore/core1/conf/solrconfig.xml b/example/multicore/core1/conf/solrconfig.xml new file mode 100644 index 00000000000..f476fb5816d --- /dev/null +++ b/example/multicore/core1/conf/solrconfig.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + solr + solrconfig.xml schema.xml admin-extra.html + + qt=standard&q=solrpingquery + + + + + diff --git a/example/multicore/multicore.xml b/example/multicore/multicore.xml new file mode 100644 index 00000000000..362ab042e6c --- /dev/null +++ b/example/multicore/multicore.xml @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/src/java/org/apache/solr/common/params/MultiCoreParams.java b/src/java/org/apache/solr/common/params/MultiCoreParams.java new file mode 100644 index 00000000000..96f23e194b9 --- /dev/null +++ b/src/java/org/apache/solr/common/params/MultiCoreParams.java @@ -0,0 +1,53 @@ +/** +/** + * 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.common.params; + +/** + * @since solr 1.3 + */ +public interface MultiCoreParams +{ + /** What Core are we talking about **/ + public final static String CORE = "core"; + + /** Persistent -- should it save the multicore state? **/ + public final static String PERSISTENT = "persistent"; + + /** What action **/ + public final static String ACTION = "action"; + + public enum MultiCoreAction { + STATUS, + STOP, + LOAD, + RELOAD, + SETASDEFAULT; + + public static MultiCoreAction get( String p ) + { + if( p != null ) { + try { + return MultiCoreAction.valueOf( p.toUpperCase() ); + } + catch( Exception ex ) {} + } + return null; + } + } +} \ No newline at end of file diff --git a/src/java/org/apache/solr/core/Config.java b/src/java/org/apache/solr/core/Config.java index b213aefd8f4..480eea96fd7 100644 --- a/src/java/org/apache/solr/core/Config.java +++ b/src/java/org/apache/solr/core/Config.java @@ -53,12 +53,12 @@ public class Config { public Config(String instanceDir, String name) throws ParserConfigurationException, IOException, SAXException { - this( instanceDir, name, null, null ); + this( new SolrResourceLoader( instanceDir ), name, null, null ); } - public Config(String instanceDir, String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException + public Config(SolrResourceLoader loader, String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException { - this.loader = new SolrResourceLoader( instanceDir ); + this.loader = loader; this.name = name; this.prefix = prefix; diff --git a/src/java/org/apache/solr/core/MultiCore.java b/src/java/org/apache/solr/core/MultiCore.java new file mode 100644 index 00000000000..fa68a3feea1 --- /dev/null +++ b/src/java/org/apache/solr/core/MultiCore.java @@ -0,0 +1,271 @@ +/** + * 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; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPathConstants; + +import org.apache.solr.common.SolrException; +import org.apache.solr.common.util.DOMUtil; +import org.apache.solr.handler.admin.MultiCoreHandler; +import org.apache.solr.schema.IndexSchema; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + + +/** + * @version $Id$ + * @since solr 1.3 + */ +public class MultiCore +{ + private static Logger log = Logger.getLogger(MultiCore.class.getName()); + private static final MultiCore instance = new MultiCore(); + + // Synchronized map of all cores + private final Map cores = + Collections.synchronizedMap( new HashMap() ); + + private SolrCore defaultCore = null; + private boolean enabled = false; + private boolean persistent = false; + private String adminPath = null; + private MultiCoreHandler multiCoreHandler = null; + private File configFile = null; + private String libDir = null; + private ClassLoader libLoader = null; + + // no one else can make the registry + private MultiCore() { } + + //------------------------------------------------------------------- + // Initialization / Cleanup + //------------------------------------------------------------------- + + /** + * Load a config file listing the available solr cores + */ + 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 ); + + 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 getCores() { + ArrayList c = new ArrayList(cores.size()); + for( Map.Entry entry : cores.entrySet() ) { + if( entry.getKey() != null && entry.getKey().length() > 0 ) { + c.add( entry.getValue() ); + } + } + return c; + } + + public SolrCore getCore(String name) { + return cores.get( name ); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isPersistent() { + return persistent; + } + + public void setPersistent(boolean persistent) { + this.persistent = persistent; + } + + public String getAdminPath() { + return adminPath; + } + + public void setAdminPath(String adminPath) { + this.adminPath = adminPath; + } + + public MultiCoreHandler getMultiCoreHandler() { + return multiCoreHandler; + } + + public File getConfigFile() { + return configFile; + } + +} diff --git a/src/java/org/apache/solr/core/RequestHandlers.java b/src/java/org/apache/solr/core/RequestHandlers.java index 5be57bb4b22..f83eaa198fe 100644 --- a/src/java/org/apache/solr/core/RequestHandlers.java +++ b/src/java/org/apache/solr/core/RequestHandlers.java @@ -232,7 +232,7 @@ final class RequestHandlers { { if( _handler == null ) { try { - _handler = (SolrRequestHandler)core.createRequestHandler(_className); + _handler = core.createRequestHandler(_className); _handler.init( _args ); if( _handler instanceof ResourceLoaderAware ) { diff --git a/src/java/org/apache/solr/core/SolrConfig.java b/src/java/org/apache/solr/core/SolrConfig.java index 4177d483353..7be1286b125 100644 --- a/src/java/org/apache/solr/core/SolrConfig.java +++ b/src/java/org/apache/solr/core/SolrConfig.java @@ -69,26 +69,29 @@ public class SolrConfig extends Config { /** Creates a default instance from the solrconfig.xml. */ public SolrConfig() throws ParserConfigurationException, IOException, SAXException { - this( null, DEFAULT_CONF_FILE, null ); + this( new SolrResourceLoader(null), DEFAULT_CONF_FILE, null ); } /** Creates a configuration instance from a file. */ public SolrConfig(String file) throws ParserConfigurationException, IOException, SAXException { - this( null, file, null); + this( new SolrResourceLoader(null), file, null); } @Deprecated public SolrConfig(String file, InputStream is) - throws ParserConfigurationException, IOException, SAXException - { - this( null, file, is ); + throws ParserConfigurationException, IOException, SAXException { + this( new SolrResourceLoader(null), file, is ); } /** Creates a configuration instance from an input stream. */ public SolrConfig(String instanceDir, String file, InputStream is) - throws ParserConfigurationException, IOException, SAXException - { - super(instanceDir, file, is, "/config/"); + throws ParserConfigurationException, IOException, SAXException { + this(new SolrResourceLoader(instanceDir), file, is); + } + + SolrConfig(SolrResourceLoader loader, String file, InputStream is) + throws ParserConfigurationException, IOException, SAXException { + super(loader, file, is, "/config/"); this.configFile = file; defaultIndexConfig = new SolrIndexConfig(this, null, null); mainIndexConfig = new SolrIndexConfig(this, "mainIndex", defaultIndexConfig); diff --git a/src/java/org/apache/solr/core/SolrCore.java b/src/java/org/apache/solr/core/SolrCore.java index 70f873e62c7..4b1e44c4e3a 100644 --- a/src/java/org/apache/solr/core/SolrCore.java +++ b/src/java/org/apache/solr/core/SolrCore.java @@ -29,13 +29,13 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.logging.Logger; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; -import org.apache.solr.common.ResourceLoader; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.SolrParams; @@ -66,6 +66,7 @@ import org.apache.solr.util.plugin.AbstractPluginLoader; import org.apache.solr.util.plugin.NamedListPluginLoader; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; /** @@ -76,12 +77,13 @@ public final class SolrCore { public static Logger log = Logger.getLogger(SolrCore.class.getName()); + private final String name; 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 = System.currentTimeMillis(); + private final long startTime; private final RequestHandlers reqHandlers; private final SolrHighlighter highlighter; private final Map updateProcessors; @@ -124,6 +126,9 @@ public final class SolrCore { return schema.getSchemaFile(); } + public String getName() { + return name; + } /** * @since solr 1.3 @@ -135,7 +140,7 @@ public final class SolrCore { public List parseListener(String path) { List lst = new ArrayList(); - log.info("Searching for listeners: " +path); + log.info( "["+name+"] Searching for listeners: " +path); NodeList nodes = (NodeList)solrConfig.evaluate(path, XPathConstants.NODESET); if (nodes!=null) { for (int i=0; i maxWarmingSearchers) { onDeckSearchers--; String msg="Error opening new searcher. exceeded limit of maxWarmingSearchers="+maxWarmingSearchers + ", try again later."; - log.warning(msg); + log.warning("["+name+"] "+ msg); // HTTP 503==service unavailable, or 409==Conflict throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,msg,true); } else if (onDeckSearchers > 1) { - log.info("PERFORMANCE WARNING: Overlapping onDeckSearchers=" + onDeckSearchers); + log.info("["+name+"] PERFORMANCE WARNING: Overlapping onDeckSearchers=" + onDeckSearchers); } } @@ -739,7 +747,7 @@ public final class SolrCore { } if (onDeckSearchers < 0) { // sanity check... should never happen - log.severe("ERROR!!! onDeckSearchers after decrement=" + onDeckSearchers); + log.severe("["+name+"] ERROR!!! onDeckSearchers after decrement=" + onDeckSearchers); onDeckSearchers=0; // try and recover } // if we failed, we need to wake up at least one waiter to continue the process @@ -788,7 +796,7 @@ public final class SolrCore { SolrIndexSearcher newSearcher = newSearcherHolder.get(); newSearcher.register(); // register subitems (caches) - log.info("Registered new searcher " + newSearcher); + log.info("["+name+"] Registered new searcher " + newSearcher); } catch (Throwable e) { log(e); @@ -804,7 +812,7 @@ public final class SolrCore { public void closeSearcher() { - log.info("Closing main searcher on request."); + log.info("["+name+"] Closing main searcher on request."); synchronized (searcherLock) { if (_searcher != null) { _searcher.decref(); // dec refcount for this._searcher @@ -817,7 +825,7 @@ public final class SolrCore { public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) { if (handler==null) { - log.warning("Null Request Handler '" + req.getQueryType() +"' :" + req); + log.warning("["+name+"] Null Request Handler '" + req.getQueryType() +"' :" + req); throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"Null Request Handler '" + req.getQueryType() + "'", true); } // setup response header and handle request @@ -826,7 +834,7 @@ public final class SolrCore { handler.handleRequest(req,rsp); setResponseHeaderValues(handler,responseHeader,req,rsp); - log.info(req.getContext().get("path") + " " + log.info("["+name+"] " + req.getContext().get("path") + " " + req.getParamString()+ " 0 "+ (int)(rsp.getEndTime() - req.getStartTime())); } @@ -835,7 +843,7 @@ public final class SolrCore { public void execute(SolrQueryRequest req, SolrQueryResponse rsp) { SolrRequestHandler handler = getRequestHandler(req.getQueryType()); if (handler==null) { - log.warning("Unknown Request Handler '" + req.getQueryType() +"' :" + req); + log.warning("["+name+"] Unknown Request Handler '" + req.getQueryType() +"' :" + req); throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Unknown Request Handler '" + req.getQueryType() + "'", true); } execute(handler, req, rsp); diff --git a/src/java/org/apache/solr/core/SolrResourceLoader.java b/src/java/org/apache/solr/core/SolrResourceLoader.java index 3588f961b7e..22748f863e0 100644 --- a/src/java/org/apache/solr/core/SolrResourceLoader.java +++ b/src/java/org/apache/solr/core/SolrResourceLoader.java @@ -73,20 +73,19 @@ public class SolrResourceLoader implements ResourceLoader * found in the "lib/" directory in the "Solr Home" directory. *

*/ - public SolrResourceLoader( String instanceDir, ClassLoader loader ) + public SolrResourceLoader( String instanceDir, ClassLoader parent ) { - if( instanceDir == null ) { + if( instanceDir == null ) instanceDir = SolrResourceLoader.locateInstanceDir(); - } this.instanceDir = normalizeDir(instanceDir); log.info("Solr home set to '" + this.instanceDir + "'"); + this.classLoader = createClassLoader(new File(this.instanceDir + "lib/"), parent); + } + static ClassLoader createClassLoader(File f, ClassLoader loader) { if( loader == null ) { - // NB5.5/win32/1.5_10: need to go thru local var or classLoader is not set! loader = Thread.currentThread().getContextClassLoader(); } - - File f = new File(instanceDir + "lib/"); if (f.canRead() && f.isDirectory()) { File[] jarFiles = f.listFiles(); URL[] jars = new URL[jarFiles.length]; @@ -95,12 +94,13 @@ public class SolrResourceLoader implements ResourceLoader jars[j] = jarFiles[j].toURI().toURL(); log.info("Adding '" + jars[j].toString() + "' to Solr classloader"); } - loader = URLClassLoader.newInstance(jars, loader); + return URLClassLoader.newInstance(jars, loader); } catch (MalformedURLException e) { SolrException.log(log,"Can't construct solr lib class loader", e); } } - this.classLoader = loader; + log.info("Reusing parent classloader"); + return loader; } public SolrResourceLoader( String instanceDir ) @@ -126,7 +126,7 @@ public class SolrResourceLoader implements ResourceLoader try { File f = new File(resource); if (!f.isAbsolute()) { - // try $CWD/solrconf/ + // try $CWD/conf/ f = new File(getConfigDir() + resource); } if (f.isFile() && f.canRead()) { @@ -262,12 +262,12 @@ public class SolrResourceLoader implements ResourceLoader // Try JNDI try { Context c = new InitialContext(); - home = (String)c.lookup("java:comp/env/solr/home"); + home = (String)c.lookup("java:comp/env/"+project+"/home"); log.info("Using JNDI solr.home: "+home ); } catch (NoInitialContextException e) { - log.info("JNDI not configured for Solr (NoInitialContextEx)"); + log.info("JNDI not configured for "+project+" (NoInitialContextEx)"); } catch (NamingException e) { - log.info("No /solr/home in JNDI"); + log.info("No /"+project+"/home in JNDI"); } catch( RuntimeException ex ) { log.warning("Odd RuntimeException while testing for JNDI: " + ex.getMessage()); } @@ -277,14 +277,14 @@ public class SolrResourceLoader implements ResourceLoader String prop = project + ".solr.home"; home = normalizeDir(System.getProperty(prop)); if( home != null ) { - log.info("using system property solr.home: " + home ); + log.info("using system property "+prop+": " + home ); } } // if all else fails, try if( home == null ) { home = project + '/'; - log.info("Solr home defaulted to '" + home + "' (could not find system property or JNDI)"); + log.info(project + " home defaulted to '" + home + "' (could not find system property or JNDI)"); } return normalizeDir( home ); } diff --git a/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java b/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java index 117905f6b9c..51052bd1e98 100644 --- a/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java +++ b/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java @@ -378,7 +378,7 @@ public class LukeRequestHandler extends RequestHandlerBase return finfo; } - private static SimpleOrderedMap getIndexInfo( IndexReader reader, boolean countTerms ) throws IOException + public static SimpleOrderedMap getIndexInfo( IndexReader reader, boolean countTerms ) throws IOException { Directory dir = reader.directory(); SimpleOrderedMap indexInfo = new SimpleOrderedMap(); diff --git a/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java b/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java new file mode 100644 index 00000000000..9eb8da80802 --- /dev/null +++ b/src/java/org/apache/solr/handler/admin/MultiCoreHandler.java @@ -0,0 +1,173 @@ +/** + * 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.handler.admin; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.MultiCoreParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.params.MultiCoreParams.MultiCoreAction; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.core.MultiCore; +import org.apache.solr.core.SolrCore; +import org.apache.solr.handler.RequestHandlerBase; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.request.SolrQueryResponse; +import org.apache.solr.search.SolrIndexSearcher; +import org.apache.solr.util.RefCounted; + +/** + * @version $Id$ + * @since solr 1.3 + */ +public class MultiCoreHandler extends RequestHandlerBase +{ + public MultiCoreHandler() + { + super(); + // Unlike most request handlers, MultiCore initialization + // should happen in the constructor... + } + + + @Override + final public void init(NamedList args) { + throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, + "MultiCoreHandler should not be configured in solrconf.xml\n"+ + "it is a special Handler configured directly by the RequestDispatcher" ); + } + + @Override + public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception + { + // Make sure the manager is enabled + MultiCore manager = MultiCore.getRegistry(); + if( !manager.isEnabled() ) { + throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, + "MultiCore support must be enabled at startup." ); + } + + // Pick the action + SolrParams params = req.getParams(); + MultiCoreAction action = MultiCoreAction.STATUS; + String a = params.get( MultiCoreParams.ACTION ); + if( a != null ) { + action = MultiCoreAction.get( a ); + if( action == null ) { + throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, + "Unknown 'action' value. Use: "+MultiCoreAction.values() ); + } + } + + // 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 + //--------------------------------------------------------- + if( action == MultiCoreAction.STATUS ) { + SolrCore defaultCore = manager.getDefaultCore(); + NamedList status = new SimpleOrderedMap(); + 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." ); + } + else { + switch( action ) { + case SETASDEFAULT: + manager.setDefaultCore( core ); + rsp.add( "default", core.getName() ); + break; + + case RELOAD: { + manager.reload( core ); + 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() ); + } + } + } + + private static NamedList getCoreStatus( SolrCore core, boolean isDefault ) throws IOException + { + NamedList info = new SimpleOrderedMap(); + info.add( "name", core.getName() ); + info.add( "instanceDir", core.getResourceLoader().getInstanceDir() ); + info.add( "dataDir", core.getDataDir() ); + info.add( "startTime", new Date( core.getStartTime() ) ); + info.add( "uptime", System.currentTimeMillis()-core.getStartTime() ); + info.add( "isDefault", isDefault ); + RefCounted searcher = core.getSearcher(); + info.add( "index", LukeRequestHandler.getIndexInfo( searcher.get().getReader(), false ) ); + searcher.decref(); + return info; + } + + + //////////////////////// SolrInfoMBeans methods ////////////////////// + + @Override + public String getDescription() { + return "Manage Multiple Solr Cores"; + } + + @Override + public String getVersion() { + return "$Revision$"; + } + + @Override + public String getSourceId() { + return "$Id$"; + } + + @Override + public String getSource() { + return "$URL$"; + } +} diff --git a/src/java/org/apache/solr/update/DirectUpdateHandler.java b/src/java/org/apache/solr/update/DirectUpdateHandler.java index bd35b0370e2..5e0ac5db1fb 100644 --- a/src/java/org/apache/solr/update/DirectUpdateHandler.java +++ b/src/java/org/apache/solr/update/DirectUpdateHandler.java @@ -134,8 +134,8 @@ public class DirectUpdateHandler extends UpdateHandler { try { Term term = new Term(idField.getName(), indexedId); num = ir.deleteDocuments(term); - if (SolrCore.log.isLoggable(Level.FINEST)) { - SolrCore.log.finest("deleted " + num + " docs matching id " + idFieldType.indexedToReadable(indexedId)); + if (core.log.isLoggable(Level.FINEST)) { + core.log.finest( "["+core.getName()+"] deleted " + num + " docs matching id " + idFieldType.indexedToReadable(indexedId)); } } finally { try { if (tdocs != null) tdocs.close(); } catch (Exception e) {} @@ -202,8 +202,8 @@ public class DirectUpdateHandler extends UpdateHandler { totDeleted = deleter.deleted; } - if (SolrCore.log.isLoggable(Level.FINE)) { - SolrCore.log.fine("docs deleted:" + totDeleted); + if (core.log.isLoggable(Level.FINE)) { + core.log.fine("["+core.getName()+"] docs deleted:" + totDeleted); } } diff --git a/src/java/org/apache/solr/update/DirectUpdateHandler2.java b/src/java/org/apache/solr/update/DirectUpdateHandler2.java index b0258fdaeb0..cd297a1fa84 100644 --- a/src/java/org/apache/solr/update/DirectUpdateHandler2.java +++ b/src/java/org/apache/solr/update/DirectUpdateHandler2.java @@ -176,7 +176,7 @@ public class DirectUpdateHandler2 extends UpdateHandler { // must only be called when iwCommit lock held private void deleteAll() throws IOException { - SolrCore.log.info("REMOVING ALL DOCUMENTS FROM INDEX"); + core.log.info("["+core.getName()+"] REMOVING ALL DOCUMENTS FROM INDEX"); closeWriter(); closeSearcher(); pset.clear(); // ignore docs marked for deletion since we are removing all @@ -376,8 +376,8 @@ public class DirectUpdateHandler2 extends UpdateHandler { } if (!delAll) { - if (SolrCore.log.isLoggable(Level.FINE)) { - SolrCore.log.fine("docs deleted by query:" + totDeleted); + if (core.log.isLoggable(Level.FINE)) { + core.log.fine("["+core.getName()+"] docs deleted by query:" + totDeleted); } numDocsDeleted.getAndAdd(totDeleted); } diff --git a/src/java/org/apache/solr/util/TestHarness.java b/src/java/org/apache/solr/util/TestHarness.java index 4d1aab3d3c7..0f7bb1a62d4 100644 --- a/src/java/org/apache/solr/util/TestHarness.java +++ b/src/java/org/apache/solr/util/TestHarness.java @@ -124,7 +124,7 @@ public class TestHarness { SolrConfig solrConfig, IndexSchema indexSchema) { try { - core = new SolrCore( dataDirectory, solrConfig, indexSchema); + core = new SolrCore( "test-"+System.currentTimeMillis(), dataDirectory, solrConfig, indexSchema); builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); updater = new XmlUpdateRequestHandler(); diff --git a/src/webapp/resources/admin/_info.jsp b/src/webapp/resources/admin/_info.jsp index 676ca45cebc..3b60f8eccbe 100644 --- a/src/webapp/resources/admin/_info.jsp +++ b/src/webapp/resources/admin/_info.jsp @@ -24,9 +24,17 @@ <%@ page import="org.apache.solr.util.XML"%> <%@ page import="org.apache.lucene.LucenePackage"%> + <% - Object ocore = request.getAttribute("org.apache.solr.SolrCore"); - SolrCore core = ocore instanceof SolrCore? (SolrCore) ocore : SolrCore.getSolrCore(); + // + SolrCore core = (SolrCore) request.getAttribute("org.apache.solr.SolrCore"); + if (core == null) { + String coreParam = request.getParameter("core"); + core = coreParam != null? org.apache.solr.core.MultiCore.getRegistry().getCore(coreParam) : null; + } + if (core == null) + core = SolrCore.getSolrCore(); + SolrConfig solrConfig = core.getSolrConfig(); int port = request.getServerPort(); IndexSchema schema = core.getSchema(); diff --git a/src/webapp/resources/admin/action.jsp b/src/webapp/resources/admin/action.jsp index 978c5303a2e..056e26b5f3f 100644 --- a/src/webapp/resources/admin/action.jsp +++ b/src/webapp/resources/admin/action.jsp @@ -111,6 +111,6 @@

- Return to Admin Page + Return to Admin Page diff --git a/src/webapp/resources/admin/analysis.jsp b/src/webapp/resources/admin/analysis.jsp index a1536efbb70..77d2208febf 100644 --- a/src/webapp/resources/admin/analysis.jsp +++ b/src/webapp/resources/admin/analysis.jsp @@ -60,6 +60,7 @@

Field Analysis

+
diff --git a/src/webapp/resources/admin/distributiondump.jsp b/src/webapp/resources/admin/distributiondump.jsp index 71cb41680e0..4d205a323f8 100644 --- a/src/webapp/resources/admin/distributiondump.jsp +++ b/src/webapp/resources/admin/distributiondump.jsp @@ -153,6 +153,6 @@ <%= buffer %>


- Return to Admin Page + Return to Admin Page diff --git a/src/webapp/resources/admin/form.jsp b/src/webapp/resources/admin/form.jsp index ca56eeb72f2..e34e1c7d655 100644 --- a/src/webapp/resources/admin/form.jsp +++ b/src/webapp/resources/admin/form.jsp @@ -19,7 +19,7 @@
- + - - - - - - - - - - - - - - Solr Admin: Logging - - - - SOLR - - -

Solr Admin ()

- - - -
- - - - - -
-

Solr Logging

- - - - - - - - - -
-

Log Level:

-
- -
- Set Level - - [ALL] - [CONFIG] - [FINE] - [FINER] - [FINEST] - [INFO] - [OFF] - [SEVERE] - [WARNING] -
- -
-
+ + + + + + + + + + + + + + + + Solr Admin: Logging + + + + SOLR + + +

Solr Admin ()

+
+ +
+
+ + .?core= + Return to Admin Page + +
+ + +
+ + + + + +
+

Solr Logging

+ + + + + + + + + +
+

Log Level:

+
+ +
+ Set Level + + [ + action.jsp?log=ALL&core= + ALL + ] + [ + action.jsp?log=CONFIG&core= + CONFIG + ] + [ + action.jsp?log=FINE&core= + FINE + ] + [ + action.jsp?log=FINER&core= + FINER + ] + [ + action.jsp?log=FINEST&core= + FINEST + ] + [ + action.jsp?log=INFO&core= + INFO + ] + [ + action.jsp?log=OFF&core= + OFF + ] + [ + action.jsp?log=SEVERE&core= + SEVERE + ] + [ + action.jsp?log=WARNING&core= + WARNING + ] +
+ +
+
diff --git a/src/webapp/resources/admin/ping.jsp b/src/webapp/resources/admin/ping.jsp index 6987f0d671f..746c9bcec68 100644 --- a/src/webapp/resources/admin/ping.jsp +++ b/src/webapp/resources/admin/ping.jsp @@ -24,26 +24,22 @@ <%@ page import="org.apache.solr.request.ServletSolrParams"%> <%@ page import="org.apache.solr.request.SolrQueryRequest"%> +<% + SolrCore core = (SolrCore) request.getAttribute("org.apache.solr.SolrCore"); + if (core == null) { + String coreParam = request.getParameter("core"); + core = coreParam != null? org.apache.solr.core.MultiCore.getRegistry().getCore(coreParam) : null; + } + if (core == null) + core = SolrCore.getSolrCore(); +%> + <%=core.getName()%> <% -// -// Deprecated -- use PingRequestHandler -// - - Object ocore = request.getAttribute("org.apache.solr.SolrCore"); - SolrCore core = ocore instanceof SolrCore? (SolrCore) ocore : SolrCore.getSolrCore(); - - SolrQueryRequest req = null; - - if (null == request.getQueryString()) { - req = core.getPingQueryRequest(); - } else { - req = new LocalSolrQueryRequest(core, new ServletSolrParams(request)); - } - + SolrQueryRequest req = core.getPingQueryRequest(); SolrQueryResponse resp = new SolrQueryResponse(); try { core.execute(req,resp); diff --git a/src/webapp/resources/admin/ping.xsl b/src/webapp/resources/admin/ping.xsl index 364577bc69c..ec5672acf5e 100644 --- a/src/webapp/resources/admin/ping.xsl +++ b/src/webapp/resources/admin/ping.xsl @@ -1,69 +1,72 @@ - - - - - - - - - - - - - - - - Solr Admin: Ping - - - - SOLR - - -

Solr Admin ()

- - - -
- - - - - - - - - -
-

Ping

-
- -
-
-
+ + + + + + + + + + + + + + + + Solr Admin: Ping + + + + SOLR + + +

Solr Admin ()

+
+ +
+
+ + .?core= + Return to Admin Page (ping) + +
+ + +
+ + + + + + + + + +
+

Ping

+
+ +
+
+
diff --git a/src/webapp/resources/admin/raw-schema.jsp b/src/webapp/resources/admin/raw-schema.jsp index 1319820c473..87839fd1f22 100644 --- a/src/webapp/resources/admin/raw-schema.jsp +++ b/src/webapp/resources/admin/raw-schema.jsp @@ -20,8 +20,14 @@ <%@ page import="java.io.Reader"%> <%@ page contentType="text/plain;charset=UTF-8" language="java" %> <% - Object ocore = request.getAttribute("org.apache.solr.SolrCore"); - SolrCore core = ocore instanceof SolrCore? (SolrCore) ocore : SolrCore.getSolrCore(); + SolrCore core = (SolrCore) request.getAttribute("org.apache.solr.SolrCore"); + if (core == null) { + String coreParam = request.getParameter("core"); + core = coreParam != null? org.apache.solr.core.MultiCore.getRegistry().getCore(coreParam) : null; + } + if (core == null) + core = SolrCore.getSolrCore(); + IndexSchema schema = core.getSchema(); Reader input = new InputStreamReader(schema.getInputStream()); char[] buf = new char[4096]; diff --git a/src/webapp/resources/admin/registry.jsp b/src/webapp/resources/admin/registry.jsp index e79949459fa..b9ea5b0a49f 100644 --- a/src/webapp/resources/admin/registry.jsp +++ b/src/webapp/resources/admin/registry.jsp @@ -25,6 +25,7 @@ <%@include file="_info.jsp" %> + <%= core.getName()%> <%= collectionName %> <%= hostname %> <%= new Date().toString() %> diff --git a/src/webapp/resources/admin/registry.xsl b/src/webapp/resources/admin/registry.xsl index 53ff775cc3b..f375e2568a4 100644 --- a/src/webapp/resources/admin/registry.xsl +++ b/src/webapp/resources/admin/registry.xsl @@ -48,7 +48,10 @@


- Return to Admin Page + + .?core= + Return to Admin Page + diff --git a/src/webapp/resources/admin/stats.jsp b/src/webapp/resources/admin/stats.jsp index 3902ec2bb40..89e0cafd95a 100644 --- a/src/webapp/resources/admin/stats.jsp +++ b/src/webapp/resources/admin/stats.jsp @@ -25,6 +25,7 @@ + <%=core.getName()%> <%= collectionName %> <%= hostname %> <%= new Date().toString() %> diff --git a/src/webapp/resources/admin/stats.xsl b/src/webapp/resources/admin/stats.xsl index 80ccc913e41..40bbdc99d78 100644 --- a/src/webapp/resources/admin/stats.xsl +++ b/src/webapp/resources/admin/stats.xsl @@ -48,7 +48,10 @@


- Return to Admin Page + + .?core= + Return to Admin Page + diff --git a/src/webapp/resources/admin/threaddump.jsp b/src/webapp/resources/admin/threaddump.jsp index 1cb962dc0de..17ce67a2956 100644 --- a/src/webapp/resources/admin/threaddump.jsp +++ b/src/webapp/resources/admin/threaddump.jsp @@ -15,18 +15,28 @@ See the License for the specific language governing permissions and limitations under the License. --%> -<%@ page import="java.lang.management.ManagementFactory, +<%@ page import="org.apache.solr.core.SolrCore, + java.lang.management.ManagementFactory, java.lang.management.ThreadMXBean, java.lang.management.ThreadInfo, java.io.IOException, org.apache.solr.util.XML"%> - +<% + SolrCore core = (SolrCore) request.getAttribute("org.apache.solr.SolrCore"); + if (core == null) { + String coreParam = request.getParameter("core"); + core = coreParam != null? org.apache.solr.core.MultiCore.getRegistry().getCore(coreParam) : null; + } + if (core == null) + core = SolrCore.getSolrCore(); +%> <%! static ThreadMXBean tmbean = ManagementFactory.getThreadMXBean(); %> + <%=core.getName()%> <%=System.getProperty("java.vm.version")%> diff --git a/src/webapp/resources/admin/threaddump.xsl b/src/webapp/resources/admin/threaddump.xsl index 999b05d009b..a51787acc67 100644 --- a/src/webapp/resources/admin/threaddump.xsl +++ b/src/webapp/resources/admin/threaddump.xsl @@ -1,101 +1,104 @@ - - - - - - - - - - - - - - - - SOLR Info - - - - SOLR - -

Solr Admin ()

-

Thread Dump

- - - -
- - - - - - - - - - - - - Thread Count: - current=, - peak=, - daemon= - - - - -
Full Thread Dump:
- - - - - '' - Id=, - - on lock=, - total cpu time= - user time= - - - - -
- - - - - -
-
- - -
- -
+ + + + + + + + + + + + + + + + SOLR Info + + + + SOLR + +

Solr Admin ()

+

Thread Dump

+
+ + +
+ + .?core= + Return to Admin Page + +
+ + +
+ + + + + + + + + + + + + Thread Count: + current=, + peak=, + daemon= + + + + +
Full Thread Dump:
+ + + + + '' + Id=, + + on lock=, + total cpu time= + user time= + + + + +
+ + + + + +
+
+ + +
+ +
diff --git a/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java b/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java index c4bd78df466..5da52405ef7 100644 --- a/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java +++ b/src/webapp/src/org/apache/solr/servlet/DirectSolrConnection.java @@ -107,7 +107,7 @@ public class DirectSolrConnection // If the Data directory is specified, initialize SolrCore directly IndexSchema schema = new IndexSchema(config, instanceDir+"/conf/schema.xml"); - core = new SolrCore( dataDir, config, schema ); + core = new SolrCore( "core", dataDir, config, schema ); parser = new SolrRequestParsers( true, Long.MAX_VALUE ); } catch (Exception ee) { diff --git a/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java b/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java index 733f9f720f1..2346613e5af 100644 --- a/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java +++ b/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java @@ -17,6 +17,7 @@ package org.apache.solr.servlet; +import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -35,8 +36,10 @@ import javax.servlet.http.HttpServletResponse; 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; +import org.apache.solr.core.SolrResourceLoader; import org.apache.solr.request.QueryResponseWriter; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryResponse; @@ -49,7 +52,8 @@ public class SolrDispatchFilter implements Filter { final Logger log = Logger.getLogger(SolrDispatchFilter.class.getName()); - protected SolrCore core; + 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 @@ -64,10 +68,32 @@ public class SolrDispatchFilter implements Filter // web.xml configuration this.pathPrefix = config.getInitParameter( "path-prefix" ); - log.info("user.dir=" + System.getProperty("user.dir")); - core = SolrCore.getSolrCore(); + // Find a valid solr core + SolrCore core = null; + multicore = MultiCore.getRegistry(); + String instanceDir = SolrResourceLoader.locateInstanceDir(); + File multiconfig = new File( instanceDir, "multicore.xml" ); + log.info( "looking for multicore.xml: "+multiconfig.getAbsolutePath() ); + if( multiconfig.exists() ) { + multicore.load( instanceDir, multiconfig ); + } + if( multicore.isEnabled() ) { + core = multicore.getDefaultCore(); + if( core == null ) { + throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, + "Multicore configuration does not include a default" ); + } + singlecore = null; + } + else { + singlecore = new SolrCore( null, null, new SolrConfig(), null ); + core = singlecore; + } - // Read the configuration + log.info("user.dir=" + System.getProperty("user.dir")); + + // Read global configuration + // Only the first registerd core configures the following attributes Config solrConfig = core.getSolrConfig(); long uploadLimitKB = solrConfig.getInt( @@ -120,7 +146,10 @@ public class SolrDispatchFilter implements Filter } public void destroy() { - core.close(); + multicore.shutdown(); + if( singlecore != null ) { + singlecore.close(); + } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException @@ -149,6 +178,32 @@ public class SolrDispatchFilter implements Filter path = path.substring( 0, idx ); } + // By default use the single core. If multicore is enabled, look for one. + SolrCore core = singlecore; + if( core == null ) { + // try to get the corename as a request parameter first + String corename = request.getParameter("core"); + if( corename == null && path.startsWith( "/@" ) ) { // multicore + idx = path.indexOf( '/', 2 ); + if( idx < 1 ) { + throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, + "MultiCore path must contain a '/'. For example: /@corename/handlerpath" ); + } + corename = path.substring( 2, idx ); + path = path.substring( idx ); + } + if (corename != null) { + core = multicore.getCore( corename ); + if( core == null ) { + throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, + "Can not find core: '"+corename+"'" ); + } + } + else { + core = multicore.getDefaultCore(); + } + } + SolrRequestHandler handler = null; if( path.length() > 1 ) { // don't match "" or "/" as valid path handler = core.getRequestHandler( path ); @@ -166,6 +221,12 @@ public class SolrDispatchFilter implements Filter } } } + + // Perhaps this is a muli-core admin page? + if( handler == null && path.equals( multicore.getAdminPath() ) ) { + handler = multicore.getMultiCoreHandler(); + } + if( handler != null ) { if( solrReq == null ) { solrReq = parsers.parse( core, path, req ); @@ -184,6 +245,11 @@ public class SolrDispatchFilter implements Filter responseWriter.write(out, solrReq, solrRsp); return; } + // otherwise, let's ensure the core is in the SolrCore request attribute so + // the servlet can retrieve it + else { + req.setAttribute("org.apache.solr.SolrCore", core); + } } catch( Throwable ex ) { sendError( (HttpServletResponse)response, ex ); @@ -203,7 +269,7 @@ public class SolrDispatchFilter implements Filter protected void execute( HttpServletRequest req, SolrRequestHandler handler, SolrQueryRequest sreq, SolrQueryResponse rsp) { // a custom filter could add more stuff to the request before passing it on. // for example: sreq.getContext().put( "HttpServletRequest", req ); - core.execute( handler, sreq, rsp ); + sreq.getCore().execute( handler, sreq, rsp ); } protected void sendError(HttpServletResponse res, Throwable ex) throws IOException