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
This commit is contained in:
Ryan McKinley 2007-12-07 03:49:52 +00:00
parent 69f9e931e9
commit f14885cf0b
50 changed files with 1755 additions and 387 deletions

View File

@ -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<ContentStream> getContentStreams() throws IOException;

View File

@ -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<Object> 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 );

View File

@ -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();
}

View File

@ -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<ContentStream> 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 );
}
}

View File

@ -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;
}
}

View File

@ -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( "<delete>" );
if( deleteById != null ) {
if( deleteI ) {
for( String id : deleteById ) {
writer.append( "<id>" );
XML.escapeCharData( id, writer );
writer.append( "</id>" );
}
}
if( deleteQuery != null ) {
if( deleteQ ) {
for( String q : deleteQuery ) {
writer.append( "<query>" );
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;
}

View File

@ -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<Object> res) {
super(res);
}
@SuppressWarnings("unchecked")
public NamedList<NamedList<Object>> getCoreStatus()
{
return (NamedList<NamedList<Object>>) getResponse().get( "status" );
}
public NamedList<Object> getCoreStatus( String core )
{
return getCoreStatus().get( core );
}
public Date getStartTime( String core )
{
NamedList<Object> v = getCoreStatus( core );
if( v == null ) {
return null;
}
return (Date) v.get( "startTime" );
}
public Long getUptime( String core )
{
NamedList<Object> v = getCoreStatus( core );
if( v == null ) {
return null;
}
return (Long) v.get( "uptime" );
}
}

View File

@ -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 );
}
}

View File

@ -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

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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 );
}
}
}

View File

@ -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.

View File

@ -0,0 +1,41 @@
<?xml version="1.0" ?>
<!--
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.
-->
<schema name="example core0" version="1.1">
<types>
<fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
</types>
<fields>
<!-- general -->
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="type" type="string" indexed="true" stored="true" multiValued="false" />
<field name="name" type="string" indexed="true" stored="true" multiValued="false" />
<field name="core0" type="string" indexed="true" stored="true" multiValued="false" />
</fields>
<!-- field to use to determine and enforce document uniqueness. -->
<uniqueKey>id</uniqueKey>
<!-- field for the QueryParser to use when an explicit fieldname is absent -->
<defaultSearchField>name</defaultSearchField>
<!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
<solrQueryParser defaultOperator="OR"/>
</schema>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
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.
-->
<!--
This is a stripped down config file used for a simple example...
It is *not* a good example to work from.
-->
<config>
<updateHandler class="solr.DirectUpdateHandler2" />
<requestDispatcher handleSelect="true" >
<requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" />
</requestDispatcher>
<requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
<requestHandler name="/update" class="solr.XmlUpdateRequestHandler" />
<requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" />
<!-- config for the admin interface -->
<admin>
<defaultQuery>solr</defaultQuery>
<gettableFiles>solrconfig.xml schema.xml admin-extra.html</gettableFiles>
<pingQuery>
qt=standard&amp;q=solrpingquery
</pingQuery>
</admin>
</config>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" ?>
<!--
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.
-->
<schema name="example core1" version="1.1">
<types>
<fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
</types>
<fields>
<!-- general -->
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="type" type="string" indexed="true" stored="true" multiValued="false" />
<field name="name" type="string" indexed="true" stored="true" multiValued="false" />
<field name="core1" type="string" indexed="true" stored="true" multiValued="false" />
</fields>
<!-- field to use to determine and enforce document uniqueness. -->
<uniqueKey>id</uniqueKey>
<!-- field for the QueryParser to use when an explicit fieldname is absent -->
<defaultSearchField>name</defaultSearchField>
<!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
<solrQueryParser defaultOperator="OR"/>
</schema>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
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.
-->
<!--
This is a stripped down config file used for a simple example...
It is *not* a good example to work from.
-->
<config>
<updateHandler class="solr.DirectUpdateHandler2" />
<requestDispatcher handleSelect="true" >
<requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" />
</requestDispatcher>
<requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
<requestHandler name="/update" class="solr.XmlUpdateRequestHandler" />
<requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" />
<!-- config for the admin interface -->
<admin>
<defaultQuery>solr</defaultQuery>
<gettableFiles>solrconfig.xml schema.xml admin-extra.html</gettableFiles>
<pingQuery>
qt=standard&amp;q=solrpingquery
</pingQuery>
</admin>
</config>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
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.
-->
<!--
All paths are relative to the instaliation 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
-->
<multicore adminPath="/admin/multicore" persistent="true" >
<core name="core0" instanceDir="core0" default="true"/>
<core name="core1" instanceDir="core1" />
</multicore>

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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<String, SolrCore> cores =
Collections.synchronizedMap( new HashMap<String, SolrCore>() );
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<nodes.getLength(); i++) {
Node node = nodes.item(i);
try {
String name = DOMUtil.getAttr(node,"name", "Core needs a name" );
String instanceDir = DOMUtil.getAttr(node,"instanceDir", "Missing required 'instanceDir'" );
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, null, 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() );
}
this.setDefaultCore( 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" );
}
enabled = true;
}
/** Stops all cores. */
public void shutdown() {
synchronized(cores) {
for( SolrCore core : cores.values() ) {
core.close();
}
cores.clear();
}
}
@Override
protected void finalize() {
shutdown();
}
//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
/** Get the singleton */
public static MultiCore getRegistry() {
return instance;
}
public SolrCore register( SolrCore core ) {
if( core == null ) {
throw new RuntimeException( "Can not register a null core." );
}
String name = core.getName();
if( name == null || name.length() == 0 ) {
throw new RuntimeException( "Invalid core name." );
}
SolrCore old = cores.put(name, core);
if( old == null ) {
log.info( "registering core: "+name );
} else {
log.info( "replacing core: "+name );
}
return old;
}
/**
* While the new core is loading, requests will continue to be dispatched to
* and processed by the old core
*
* @param core
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public void reload(SolrCore core) throws ParserConfigurationException, IOException, SAXException
{
boolean wasDefault = (core==defaultCore);
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 );
if( wasDefault ) {
this.setDefaultCore( loaded );
}
// TODO? -- add some kind of hook to close the core after all references are
// gone... is finalize() enough?
}
public void setDefaultCore( SolrCore core )
{
defaultCore = core;
cores.put( null, core );
cores.put( "", core );
}
public SolrCore getDefaultCore() {
return defaultCore;
}
/**
* @return a Collection of registered SolrCores
*/
public Collection<SolrCore> getCores() {
ArrayList<SolrCore> c = new ArrayList<SolrCore>(cores.size());
for( Map.Entry<String, SolrCore> 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;
}
}

View File

@ -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 ) {

View File

@ -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);

View File

@ -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<String,UpdateRequestProcessorFactory> 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<SolrEventListener> parseListener(String path) {
List<SolrEventListener> lst = new ArrayList<SolrEventListener>();
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<nodes.getLength(); i++) {
@ -144,7 +149,7 @@ public final class SolrCore {
SolrEventListener listener = createEventListener(className);
listener.init(DOMUtil.childNodesToNamedList(node));
lst.add(listener);
log.info("added SolrEventListener: " + listener);
log.info( "["+name+"] Added SolrEventListener: " + listener);
}
}
return lst;
@ -178,7 +183,7 @@ public final class SolrCore {
// if it didn't exist already...
Directory dir = FSDirectory.getDirectory(dirFile, !indexExists);
if (IndexReader.isLocked(dir)) {
log.warning("WARNING: Solr index directory '" + getIndexDir() + "' is locked. Unlocking...");
log.warning("["+name+"] WARNING: Solr index directory '" + getIndexDir() + "' is locked. Unlocking...");
IndexReader.unlock(dir);
}
}
@ -186,7 +191,7 @@ public final class SolrCore {
// Create the index if it doesn't exist. Note that indexExists was tested *before*
// lock removal, since that will result in the creation of the directory.
if(!indexExists) {
log.warning("Solr index directory '" + dirFile + "' doesn't exist."
log.warning("["+name+"] Solr index directory '" + dirFile + "' doesn't exist."
+ " Creating new index...");
SolrIndexWriter writer = new SolrIndexWriter("SolrCore.initIndex",getIndexDir(), true, schema, solrConfig.mainIndexConfig);
@ -251,9 +256,8 @@ public final class SolrCore {
if( instance == null ) {
try {
// sets 'instance' to the latest solr core
instance = new SolrCore(null, new SolrConfig(), null);
}
catch(Exception xany) {
instance = new SolrCore("default", null, new SolrConfig(), null);
} catch(Exception xany) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
"error creating core", xany );
}
@ -262,6 +266,10 @@ public final class SolrCore {
return instance;
}
public SolrCore(String dataDir, IndexSchema schema) throws ParserConfigurationException, IOException, SAXException {
this( "core", dataDir, new SolrConfig(), schema );
}
/**
* Creates a new core and register it in the list of cores.
* If a core with the same name already exists, it will be stopped and replaced by this one.
@ -269,18 +277,18 @@ public final class SolrCore {
*@param config a solr config instance
*@param schema a solr schema instance
*/
public SolrCore(String dataDir, SolrConfig config, IndexSchema schema) {
public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema) {
synchronized (SolrCore.class) {
// this is for backward compatibility (and also the reason
// the sync block is needed)
instance = this; // set singleton
this.name = name;
SolrResourceLoader loader = config.getResourceLoader();
if (dataDir ==null) {
dataDir = config.get("dataDir",loader.getInstanceDir()+"data");
}
log.info("Opening new SolrCore at " + loader.getInstanceDir() + ", dataDir="+dataDir);
log.info("["+name+"] Opening new SolrCore at " + loader.getInstanceDir() + ", dataDir="+dataDir);
if (schema==null) {
schema = new IndexSchema(config, "schema.xml");
@ -290,7 +298,7 @@ public final class SolrCore {
this.dataDir = dataDir;
this.index_path = dataDir + "/" + "index";
this.solrConfig = config;
this.startTime = System.currentTimeMillis();
this.maxWarmingSearchers = config.getInt("query/maxWarmingSearchers",Integer.MAX_VALUE);
booleanQueryMaxClauseCount();
@ -377,7 +385,7 @@ public final class SolrCore {
}
public void close() {
log.info("CLOSING SolrCore!");
log.info("["+name+"] CLOSING SolrCore!");
try {
closeSearcher();
} catch (Exception e) {
@ -570,16 +578,16 @@ public final class SolrCore {
onDeckSearchers++;
if (onDeckSearchers < 1) {
// should never happen... just a sanity check
log.severe("ERROR!!! onDeckSearchers is " + onDeckSearchers);
log.severe("["+name+"] ERROR!!! onDeckSearchers is " + onDeckSearchers);
onDeckSearchers=1; // reset
} else if (onDeckSearchers > 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);

View File

@ -73,20 +73,19 @@ public class SolrResourceLoader implements ResourceLoader
* found in the "lib/" directory in the "Solr Home" directory.
* <p>
*/
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 + "'");
if( loader == null ) {
// NB5.5/win32/1.5_10: need to go thru local var or classLoader is not set!
loader = Thread.currentThread().getContextClassLoader();
this.classLoader = createClassLoader(new File(this.instanceDir + "lib/"), parent);
}
File f = new File(instanceDir + "lib/");
static ClassLoader createClassLoader(File f, ClassLoader loader) {
if( loader == null ) {
loader = Thread.currentThread().getContextClassLoader();
}
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 );
}

View File

@ -378,7 +378,7 @@ public class LukeRequestHandler extends RequestHandlerBase
return finfo;
}
private static SimpleOrderedMap<Object> getIndexInfo( IndexReader reader, boolean countTerms ) throws IOException
public static SimpleOrderedMap<Object> getIndexInfo( IndexReader reader, boolean countTerms ) throws IOException
{
Directory dir = reader.directory();
SimpleOrderedMap<Object> indexInfo = new SimpleOrderedMap<Object>();

View File

@ -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<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." );
}
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<Object> getCoreStatus( SolrCore core, boolean isDefault ) throws IOException
{
NamedList<Object> info = new SimpleOrderedMap<Object>();
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<SolrIndexSearcher> 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$";
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -111,6 +111,6 @@
</tr>
</table>
<br><br>
<a href=".">Return to Admin Page</a>
<a href=".?core=<%=core.getName()%>">Return to Admin Page</a>
</body>
</html>

View File

@ -60,6 +60,7 @@
<h2>Field Analysis</h2>
<form method="GET" action="analysis.jsp">
<input type='hidden' name='core' value='<%=core.getName()%>'>
<table>
<tr>
<td>

View File

@ -153,6 +153,6 @@
<%= buffer %>
</table>
<br><br>
<a href=".">Return to Admin Page</a>
<a href=".?<%=core.getName()%>">Return to Admin Page</a>
</body>
</html>

View File

@ -19,7 +19,7 @@
<br clear="all">
<form name="queryForm" method="GET" action="../select">
<input name='core' type='hidden' value='<%=core.getName()%>'>
<!-- these are good defaults to have if people bookmark the resulting
URLs, but they should not show up in the form since they are very
output type specific.

View File

@ -29,7 +29,7 @@ var host_name="<%= hostname %>"
</head>
<body>
<a href="."><img border="0" align="right" height="61" width="142" src="solr-head.gif" alt="Solr"></a>
<a href="?core=<%=core.getName()%>"><img border="0" align="right" height="61" width="142" src="solr-head.gif" alt="Solr"></a>
<h1>Solr Admin (<%= collectionName %>)
<%= enabledStatus==null ? "" : (isEnabled ? " - Enabled" : " - Disabled") %> </h1>

View File

@ -34,42 +34,53 @@
<h3>Solr</h3>
</td>
<td>
[<a href="get-file.jsp?file=<%=core.getSchemaFile()%>">Schema</a>]
[<a href="get-file.jsp?file=<%=core.getConfigFile()%>">Config</a>]
[<a href="analysis.jsp?highlight=on">Analysis</a>]
[<a href="get-file.jsp?core=<%=core.getName()%>&file=<%=core.getSchemaFile()%>">Schema</a>]
[<a href="get-file.jsp?core=<%=core.getName()%>&file=<%=core.getConfigFile()%>">Config</a>]
[<a href="analysis.jsp?core=<%=core.getName()%>&highlight=on">Analysis</a>]
<br>
[<a href="stats.jsp">Statistics</a>]
[<a href="registry.jsp">Info</a>]
[<a href="distributiondump.jsp">Distribution</a>]
[<a href="ping">Ping</a>]
[<a href="logging.jsp">Logging</a>]
[<a href="stats.jsp?core=<%=core.getName()%>">Statistics</a>]
[<a href="registry.jsp?core=<%=core.getName()%>">Info</a>]
[<a href="distributiondump.jsp?core=<%=core.getName()%>">Distribution</a>]
[<a href="ping?core=<%=core.getName()%>">Ping</a>]
[<a href="logging.jsp?core=<%=core.getName()%>">Logging</a>]
</td>
</tr>
<%-- List the cores (that arent this one) so we can switch --%>
<% java.util.Collection<SolrCore> cores = org.apache.solr.core.MultiCore.getRegistry().getCores();
if (cores.size() > 1) {%><tr><td><strong>Cores:</strong><br></td><td><%
java.util.Iterator<SolrCore> icore = cores.iterator();
while (icore.hasNext()) {
SolrCore acore = icore.next();
if (acore == core) continue;
%>[<a href=".?core=<%=acore.getName()%>"><%=acore.getName()%></a>]<%
}%></td></tr><%
}%>
<tr>
<td>
<strong>App server:</strong><br>
</td>
<td>
[<a href="get-properties.jsp">Java Properties</a>]
[<a href="threaddump.jsp">Thread Dump</a>]
[<a href="get-properties.jsp?core=<%=core.getName()%>">Java Properties</a>]
[<a href="threaddump.jsp?core=<%=core.getName()%>">Thread Dump</a>]
<%
if (enabledFile!=null)
if (isEnabled) {
%>
[<a href="action.jsp?action=Disable">Disable</a>]
[<a href="action.jsp?core=<%=core.getName()%>&action=Disable">Disable</a>]
<%
} else {
%>
[<a href="action.jsp?action=Enable">Enable</a>]
[<a href="action.jsp?core=<%=core.getName()%>&action=Enable">Enable</a>]
<%
}
%>
</td>
</tr>
<jsp:include page="get-file.jsp?file=admin-extra.html&optional=y" flush="true"/>
<jsp:include page="get-file.jsp?core=<%=core.getName()%>&file=admin-extra.html&optional=y" flush="true"/>
</table><P>
@ -80,7 +91,7 @@
<h3>Make a Query</h3>
</td>
<td>
[<a href="form.jsp">Full Interface</a>]
[<a href="form.jsp?core=<%=core.getName()%>">Full Interface</a>]
</td>
</tr>
@ -91,6 +102,7 @@
<td colspan=2>
<form name=queryForm method="GET" action="../select/">
<textarea class="std" rows="4" cols="40" name="q"><%= defaultSearch %></textarea>
<input name="core" type="hidden" value="<%=core.getName()%>">
<input name="version" type="hidden" value="2.2">
<input name="start" type="hidden" value="0">
<input name="rows" type="hidden" value="10">

View File

@ -28,6 +28,14 @@
<?xml-stylesheet type="text/xsl" href="logging.xsl"?>
<%
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();
Logger log = SolrCore.log;
Logger parent = log.getParent();
while(parent != null) {
@ -38,6 +46,7 @@
%>
<solr>
<core><%=core.getName()%></core>
<logging>
<% if (lvl != null) {%>
<logLevel><%= lvl.toString() %></logLevel>

View File

@ -46,7 +46,10 @@
<xsl:apply-templates/>
<div>
</div>
<a href=".">Return to Admin Page</a>
<xsl:element name='a'>
<xsl:attribute name='href'>.?core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>Return to Admin Page</xsl:text>
</xsl:element>
</div>
</body>
</html>
@ -72,15 +75,42 @@
Set Level
</td>
<td>
[<a href="action.jsp?log=ALL">ALL</a>]
[<a href="action.jsp?log=CONFIG">CONFIG</a>]
[<a href="action.jsp?log=FINE">FINE</a>]
[<a href="action.jsp?log=FINER">FINER</a>]
[<a href="action.jsp?log=FINEST">FINEST</a>]
[<a href="action.jsp?log=INFO">INFO</a>]
[<a href="action.jsp?log=OFF">OFF</a>]
[<a href="action.jsp?log=SEVERE">SEVERE</a>]
[<a href="action.jsp?log=WARNING">WARNING</a>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=ALL&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>ALL</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=CONFIG&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>CONFIG</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=FINE&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>FINE</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=FINER&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>FINER</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=FINEST&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>FINEST</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=INFO&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>INFO</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=OFF&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>OFF</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=SEVERE&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>SEVERE</xsl:text>
</xsl:element>]
[<xsl:element name='a'>
<xsl:attribute name='href'>action.jsp?log=WARNING&amp;core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>WARNING</xsl:text>
</xsl:element>]
</td>
</tr>
</table>

View File

@ -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();
%>
<?xml-stylesheet type="text/xsl" href="ping.xsl"?>
<solr>
<core><%=core.getName()%></core>
<ping>
<%
//
// 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);

View File

@ -46,7 +46,10 @@
<xsl:apply-templates/>
<div>
</div>
<a href=".">Return to Admin Page</a>
<xsl:element name='a'>
<xsl:attribute name='href'>.?core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>Return to Admin Page (ping)</xsl:text>
</xsl:element>
</div>
</body>
</html>

View File

@ -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];

View File

@ -25,6 +25,7 @@
<%@include file="_info.jsp" %>
<solr>
<core><%= core.getName()%></core>
<schema><%= collectionName %></schema>
<host><%= hostname %></host>
<now><%= new Date().toString() %></now>

View File

@ -48,7 +48,10 @@
<br clear="all" />
<xsl:apply-templates/>
<br /><br />
<a href="">Return to Admin Page</a>
<xsl:element name='a'>
<xsl:attribute name='href'>.?core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>Return to Admin Page</xsl:text>
</xsl:element>
</body>
</html>
</xsl:template>

View File

@ -25,6 +25,7 @@
<solr>
<core><%=core.getName()%></core>
<schema><%= collectionName %></schema>
<host><%= hostname %></host>
<now><%= new Date().toString() %></now>

View File

@ -48,7 +48,10 @@
<br clear="all" />
<xsl:apply-templates/>
<br /><br />
<a href=".">Return to Admin Page</a>
<xsl:element name='a'>
<xsl:attribute name='href'>.?core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>Return to Admin Page</xsl:text>
</xsl:element>
</body>
</html>
</xsl:template>

View File

@ -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"%>
<?xml-stylesheet type="text/xsl" href="threaddump.xsl"?>
<%
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();
%>
<solr>
<core><%=core.getName()%></core>
<system>
<jvm>
<version><%=System.getProperty("java.vm.version")%></version>

View File

@ -46,7 +46,10 @@
<table>
<xsl:apply-templates/>
</table>
<a href=".">Return to Admin Page</a>
<xsl:element name='a'>
<xsl:attribute name='href'>.?core=<xsl:value-of select="//solr/core"/></xsl:attribute>
<xsl:text>Return to Admin Page</xsl:text>
</xsl:element>
</div>
</body>
</html>

View File

@ -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) {

View File

@ -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