SOLR-350 -- make MultiCore subclassable so to allow custom persistance methods (for example, SQL)

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@635334 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2008-03-09 19:29:04 +00:00
parent 705cade858
commit 0d633bdcea
9 changed files with 302 additions and 184 deletions

View File

@ -54,22 +54,31 @@ public class EmbeddedSolrServer extends SolrServer
protected ModifiableSolrParams _invariantParams; protected ModifiableSolrParams _invariantParams;
protected ResponseParser _processor; protected ResponseParser _processor;
protected final SolrCore core; protected final MultiCore multicore; // either multicore
protected final SolrCore core; // or single core
protected final SolrRequestParsers parser; protected final SolrRequestParsers parser;
protected final String coreName; // use MultiCore registry protected final String coreName; // use MultiCore registry
public EmbeddedSolrServer( SolrCore core ) public EmbeddedSolrServer( SolrCore core )
{ {
if ( core == null ) {
throw new NullPointerException("SolrCore instance required");
}
this.core = core; this.core = core;
this.multicore = null;
this.coreName = null; this.coreName = null;
this.parser = init(); this.parser = init();
} }
public EmbeddedSolrServer( String coreName ) public EmbeddedSolrServer( MultiCore multicore, String coreName )
{ {
if ( multicore == null ) {
throw new NullPointerException("MultiCore instance required");
}
this.core = null; this.core = null;
this.multicore = multicore;
this.coreName = coreName; this.coreName = coreName;
SolrCore c = MultiCore.getRegistry().getCore( coreName ); SolrCore c = multicore.getCore( coreName );
if( c == null ) { if( c == null ) {
throw new RuntimeException( "Unknown core: "+coreName ); throw new RuntimeException( "Unknown core: "+coreName );
} }
@ -96,7 +105,6 @@ public class EmbeddedSolrServer extends SolrServer
} }
// Check for multicore action // Check for multicore action
MultiCore multicore = MultiCore.getRegistry();
SolrCore core = this.core; SolrCore core = this.core;
if( core == null ) { if( core == null ) {
core = multicore.getCore( coreName ); core = multicore.getCore( coreName );
@ -126,7 +134,7 @@ public class EmbeddedSolrServer extends SolrServer
} }
// Perhaps the path is to manage the cores // Perhaps the path is to manage the cores
if( handler == null && if( handler == null &&
coreName != null && multicore != null &&
path.equals( multicore.getAdminPath() ) && path.equals( multicore.getAdminPath() ) &&
multicore.isEnabled() ) { multicore.isEnabled() ) {
handler = multicore.getMultiCoreHandler(); handler = multicore.getMultiCoreHandler();

View File

@ -25,7 +25,7 @@ import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.request.UpdateRequest.ACTION; import org.apache.solr.client.solrj.request.UpdateRequest.ACTION;
import org.apache.solr.client.solrj.response.MultiCoreResponse; import org.apache.solr.client.solrj.response.MultiCoreResponse;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.MultiCore;
/** /**
@ -34,6 +34,9 @@ import org.apache.solr.core.SolrCore;
*/ */
public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase
{ {
@SuppressWarnings("deprecation")
protected static final MultiCore multicore = org.apache.solr.core.SolrMultiCore.getInstance();
@Override public String getSolrHome() { return "../../../example/multicore/"; } @Override public String getSolrHome() { return "../../../example/multicore/"; }
@Override public String getSchemaFile() { return getSolrHome()+"core0/conf/schema.xml"; } @Override public String getSchemaFile() { return getSolrHome()+"core0/conf/schema.xml"; }

View File

@ -21,7 +21,6 @@ import java.io.File;
import org.apache.solr.client.solrj.MultiCoreExampleTestBase; import org.apache.solr.client.solrj.MultiCoreExampleTestBase;
import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.core.MultiCore;
/** /**
* This runs SolrServer test using * This runs SolrServer test using
@ -37,24 +36,24 @@ public class MultiCoreEmbeddedTest extends MultiCoreExampleTestBase {
File home = new File( getSolrHome() ); File home = new File( getSolrHome() );
File f = new File( home, "multicore.xml" ); File f = new File( home, "multicore.xml" );
MultiCore.getRegistry().load( getSolrHome(), f ); multicore.load( getSolrHome(), f );
} }
@Override @Override
protected SolrServer getSolrCore0() protected SolrServer getSolrCore0()
{ {
return new EmbeddedSolrServer( "core0" ); return new EmbeddedSolrServer( multicore, "core0" );
} }
@Override @Override
protected SolrServer getSolrCore1() protected SolrServer getSolrCore1()
{ {
return new EmbeddedSolrServer( "core1" ); return new EmbeddedSolrServer( multicore, "core1" );
} }
@Override @Override
protected SolrServer getSolrAdmin() protected SolrServer getSolrAdmin()
{ {
return new EmbeddedSolrServer( "core0" ); return new EmbeddedSolrServer( multicore, "core0" );
} }
} }

View File

@ -49,30 +49,33 @@ import org.xml.sax.SAXException;
*/ */
public class MultiCore public class MultiCore
{ {
private static Logger log = Logger.getLogger(MultiCore.class.getName()); protected static Logger log = Logger.getLogger(MultiCore.class.getName());
private static final MultiCore instance = new MultiCore();
// Synchronized map of all cores protected final Map<String, CoreDescriptor> cores = new LinkedHashMap<String, CoreDescriptor>();
private final Map<String, CoreDescriptor> cores = new LinkedHashMap<String, CoreDescriptor>(); protected boolean enabled = false;
protected boolean persistent = false;
protected String adminPath = null;
protected MultiCoreHandler multiCoreHandler = null;
protected File configFile = null;
protected String libDir = null;
protected ClassLoader libLoader = null;
protected SolrResourceLoader loader = null;
protected java.lang.ref.WeakReference<SolrCore> adminCore = null;
private boolean enabled = false; public MultiCore() {
private boolean persistent = false; }
private String adminPath = null;
private MultiCoreHandler multiCoreHandler = null;
private File configFile = null;
private String libDir = null;
private ClassLoader libLoader = null;
private SolrResourceLoader loader = null;
// no one else can make the registry
private MultiCore() { }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Initialization / Cleanup // Initialization / Cleanup
//------------------------------------------------------------------- //-------------------------------------------------------------------
/** /**
* Load a config file listing the available solr cores * Load a config file listing the available solr cores.
* @param dir the home directory of all resources.
* @param configFile the configuration file
* @throws javax.xml.parsers.ParserConfigurationException
* @throws java.io.IOException
* @throws org.xml.sax.SAXException
*/ */
public void load(String dir, File configFile ) throws ParserConfigurationException, IOException, SAXException { public void load(String dir, File configFile ) throws ParserConfigurationException, IOException, SAXException {
this.configFile = configFile; this.configFile = configFile;
@ -94,7 +97,7 @@ public class MultiCore
} }
if( adminPath != null ) { if( adminPath != null ) {
multiCoreHandler = new MultiCoreHandler(); multiCoreHandler = this.createMultiCoreHandler();
} }
NodeList nodes = (NodeList)cfg.evaluate("multicore/core", XPathConstants.NODESET); NodeList nodes = (NodeList)cfg.evaluate("multicore/core", XPathConstants.NODESET);
@ -135,7 +138,9 @@ public class MultiCore
enabled = true; enabled = true;
} }
/** Stops all cores. */ /**
* Stops all cores.
*/
public void shutdown() { public void shutdown() {
synchronized(cores) { synchronized(cores) {
for(Map.Entry<String,CoreDescriptor> e : cores.entrySet()) { for(Map.Entry<String,CoreDescriptor> e : cores.entrySet()) {
@ -154,15 +159,11 @@ public class MultiCore
shutdown(); shutdown();
} }
//------------------------------------------------------------------- /**
// * Registers a SolrCore descriptor in the registry.
//------------------------------------------------------------------- * @param descr the Solr core descriptor
* @return a previous descriptor having the same name if it existed, null otherwise
/** Get the singleton */ */
public static MultiCore getRegistry() {
return instance;
}
public CoreDescriptor register( CoreDescriptor descr ) { public CoreDescriptor register( CoreDescriptor descr ) {
if( descr == null ) { if( descr == null ) {
throw new RuntimeException( "Can not register a null core." ); throw new RuntimeException( "Can not register a null core." );
@ -186,6 +187,12 @@ public class MultiCore
} }
} }
/**
* Swaps two SolrCore descriptors.
* @param c0
* @param c1
*/
public void swap(CoreDescriptor c0, CoreDescriptor c1) { public void swap(CoreDescriptor c0, CoreDescriptor c1) {
if( c0 == null || c1 == null ) { if( c0 == null || c1 == null ) {
throw new RuntimeException( "Can not swap a null core." ); throw new RuntimeException( "Can not swap a null core." );
@ -235,10 +242,11 @@ public class MultiCore
} }
/** /**
* Recreates a SolrCore.
* While the new core is loading, requests will continue to be dispatched to * While the new core is loading, requests will continue to be dispatched to
* and processed by the old core * and processed by the old core
* *
* @param core * @param core the SolrCore to reload
* @throws ParserConfigurationException * @throws ParserConfigurationException
* @throws IOException * @throws IOException
* @throws SAXException * @throws SAXException
@ -314,6 +322,49 @@ public class MultiCore
this.adminPath = adminPath; this.adminPath = adminPath;
} }
/**
* Sets the preferred core used to handle MultiCore admin tasks.
* Note that getAdminCore is not symmetrical to this method since
* it will allways return an opened SolrCore.
* This however can be useful implementing a "metacore" (a core of cores).
*/
public void setAdminCore(SolrCore core) {
adminCore = new java.lang.ref.WeakReference<SolrCore>(core);
}
/**
* Gets a core to handle MultiCore admin tasks (@see SolrDispatchFilter).
* This makes the best attempt to reuse the same opened SolrCore accross calls.
*/
public SolrCore getAdminCore() {
SolrCore core = adminCore != null ? adminCore.get() : null;
if (core == null || core.isClosed()) {
for (CoreDescriptor descr : this.cores.values()) {
core = descr.getCore();
if (core == null || core.isClosed()) {
core = null;
} else {
break;
}
}
setAdminCore(core);
}
return core;
}
/**
* Creates a MultiCoreHandler for this MultiCore.
* @return a MultiCoreHandler
*/
public MultiCoreHandler createMultiCoreHandler() {
return new MultiCoreHandler() {
@Override
public MultiCore getMultiCore() {
return MultiCore.this;
}
};
}
public MultiCoreHandler getMultiCoreHandler() { public MultiCoreHandler getMultiCoreHandler() {
return multiCoreHandler; return multiCoreHandler;
} }
@ -439,4 +490,5 @@ public class MultiCore
throw xforward; throw xforward;
} }
} }
} }

View File

@ -32,7 +32,6 @@ import javax.xml.parsers.ParserConfigurationException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.Matcher; import java.util.regex.Matcher;

View File

@ -467,6 +467,10 @@ public final class SolrCore {
} }
} }
public boolean isClosed() {
return _searcher == null;
}
@Override @Override
protected void finalize() { close(); } protected void finalize() { close(); }
@ -926,7 +930,7 @@ public final class SolrCore {
synchronized (searcherLock) { synchronized (searcherLock) {
if (_searcher != null) { if (_searcher != null) {
_searcher.decref(); // dec refcount for this._searcher _searcher.decref(); // dec refcount for this._searcher
_searcher=null; _searcher=null; // isClosed() does check this
infoRegistry.remove("currentSearcher"); infoRegistry.remove("currentSearcher");
} }
} }

View File

@ -0,0 +1,47 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.core;
/**
* A MultiCore singleton.
* Marked as deprecated to avoid usage proliferation of core code that would
* assume MultiCore being a singleton. In solr 2.0, the MultiCore factory
* should be popluated with a standard tool like spring. Until then, this is
* a simple static factory that should not be used widely.
*
* @version $Id$
* @since solr 1.3
*/
@Deprecated
public final class SolrMultiCore extends MultiCore
{
private static MultiCore instance = null;
// no one else can make the registry
private SolrMultiCore() {}
/** Returns a default MultiCore singleton.
* @return
*/
public static synchronized MultiCore getInstance() {
if (instance == null) {
instance = new SolrMultiCore();
}
return instance;
}
}

View File

@ -39,7 +39,7 @@ import org.apache.solr.util.RefCounted;
* @version $Id$ * @version $Id$
* @since solr 1.3 * @since solr 1.3
*/ */
public class MultiCoreHandler extends RequestHandlerBase public abstract class MultiCoreHandler extends RequestHandlerBase
{ {
public MultiCoreHandler() public MultiCoreHandler()
{ {
@ -56,11 +56,18 @@ public class MultiCoreHandler extends RequestHandlerBase
"it is a special Handler configured directly by the RequestDispatcher" ); "it is a special Handler configured directly by the RequestDispatcher" );
} }
/**
* The instance of multicore this handler handles.
* This should be the MultiCore instance that created this handler.
* @return a MultiCore instance
*/
public abstract MultiCore getMultiCore();
@Override @Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception
{ {
// Make sure the manager is enabled // Make sure the manager is enabled
MultiCore manager = MultiCore.getRegistry(); MultiCore manager = getMultiCore();
if( !manager.isEnabled() ) { if( !manager.isEnabled() ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
"MultiCore support must be enabled at startup." ); "MultiCore support must be enabled at startup." );

View File

@ -21,7 +21,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Collection;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.logging.Level; import java.util.logging.Level;
@ -74,23 +73,12 @@ public class SolrDispatchFilter implements Filter
this.pathPrefix = config.getInitParameter( "path-prefix" ); this.pathPrefix = config.getInitParameter( "path-prefix" );
this.solrConfigFilename = config.getInitParameter("solrconfig-filename"); this.solrConfigFilename = config.getInitParameter("solrconfig-filename");
multicore = MultiCore.getRegistry(); // multicore instantiation
if( multicore.isEnabled() ) { this.multicore = initMultiCore(config);
log.info( "Using existing multicore configuration" );
}
else {
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 != null && multicore.isEnabled() ) {
abortOnConfigurationError = false; abortOnConfigurationError = false;
if( multicore.isEnabled() ) {
singlecore = null; singlecore = null;
// if any core aborts on startup, then abort // if any core aborts on startup, then abort
for( SolrCore c : multicore.getCores() ) { for( SolrCore c : multicore.getCores() ) {
if( c.getSolrConfig().getBool( "abortOnConfigurationError",false) ) { if( c.getSolrConfig().getBool( "abortOnConfigurationError",false) ) {
@ -100,11 +88,10 @@ public class SolrDispatchFilter implements Filter
} }
} }
else { else {
if (this.solrConfigFilename==null) { SolrConfig cfg = this.solrConfigFilename == null? new SolrConfig() : new SolrConfig(this.solrConfigFilename);
singlecore = new SolrCore( null, null, new SolrConfig(), null ); singlecore = new SolrCore( null, null, cfg, null );
} else { abortOnConfigurationError = cfg.getBool(
singlecore = new SolrCore( null, null, new SolrConfig(this.solrConfigFilename), null); "abortOnConfigurationError", abortOnConfigurationError);
}
} }
log.info("user.dir=" + System.getProperty("user.dir")); log.info("user.dir=" + System.getProperty("user.dir"));
} }
@ -123,10 +110,9 @@ public class SolrDispatchFilter implements Filter
out.println( "Check your log files for more detailed information on what may be wrong.\n" ); out.println( "Check your log files for more detailed information on what may be wrong.\n" );
out.println( "If you want solr to continue after configuration errors, change: \n"); out.println( "If you want solr to continue after configuration errors, change: \n");
out.println( " <abortOnConfigurationError>false</abortOnConfigurationError>\n" ); out.println( " <abortOnConfigurationError>false</abortOnConfigurationError>\n" );
if( multicore.isEnabled() ) { if (multicore != null && multicore.isEnabled()) {
out.println( "in multicore.xml\n" ); out.println( "in multicore.xml\n" );
} } else {
else {
out.println( "in solrconfig.xml\n" ); out.println( "in solrconfig.xml\n" );
} }
@ -148,24 +134,53 @@ public class SolrDispatchFilter implements Filter
log.info("SolrDispatchFilter.init() done"); log.info("SolrDispatchFilter.init() done");
} }
/**
* Initializes the multicore instance.
* @param config the filter configuration
* @return the multicore instance or null
* @throws java.lang.Exception
*/
protected MultiCore initMultiCore(FilterConfig config) throws Exception {
@SuppressWarnings("deprecation") // since SolrDispatchFilter can be derived & initMultiCore can be overriden
MultiCore mcore = org.apache.solr.core.SolrMultiCore.getInstance();
if (mcore.isEnabled()) {
log.info("Using existing multicore configuration");
} else {
// multicore load
String instanceDir = SolrResourceLoader.locateInstanceDir();
File fconf = new File(instanceDir, "multicore.xml");
log.info("looking for multicore.xml: " + fconf.getAbsolutePath());
if (fconf.exists()) {
mcore.load(instanceDir, fconf);
}
}
return mcore;
}
public void destroy() { public void destroy() {
if (multicore != null) {
multicore.shutdown(); multicore.shutdown();
multicore = null;
}
if( singlecore != null ) { if( singlecore != null ) {
singlecore.close(); singlecore.close();
singlecore = null;
} }
} }
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
{
if( abortErrorMessage != null ) { if( abortErrorMessage != null ) {
((HttpServletResponse)response).sendError( 500, abortErrorMessage ); ((HttpServletResponse)response).sendError( 500, abortErrorMessage );
return; return;
} }
if( request instanceof HttpServletRequest) { if( request instanceof HttpServletRequest) {
SolrQueryRequest solrReq = null;
HttpServletRequest req = (HttpServletRequest)request; HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response; HttpServletResponse resp = (HttpServletResponse)response;
SolrRequestHandler handler = null;
SolrQueryRequest solrReq = null;
try { try {
String path = req.getServletPath(); String path = req.getServletPath();
if( req.getPathInfo() != null ) { if( req.getPathInfo() != null ) {
@ -183,133 +198,118 @@ public class SolrDispatchFilter implements Filter
} }
// By default use the single core. If multicore is enabled, look for one. // By default use the single core. If multicore is enabled, look for one.
SolrRequestHandler handler = null; final SolrCore core;
SolrCore core = singlecore; if (multicore != null && multicore.isEnabled()) {
if( core == null ) { // if this is the multi-core admin page, it will handle it
// Perhaps this is a multi-core admin page?
if( path.equals( "/" ) ) {
chain.doFilter(request, response);
return;
}
if( path.equals( multicore.getAdminPath() ) ) { if( path.equals( multicore.getAdminPath() ) ) {
handler = multicore.getMultiCoreHandler(); handler = multicore.getMultiCoreHandler();
// pick a core to use for output generation
// pick a core to use for output core = multicore.getAdminCore();
Collection<SolrCore> cores = multicore.getCores();
if( cores != null && cores.size() > 0 ) {
core = cores.iterator().next();
}
if( core == null ) { if( core == null ) {
throw new RuntimeException( "Can not find a valid core for the multicore admin handler" ); throw new RuntimeException( "Can not find a valid core for the multicore admin handler" );
} }
} } else {
else { //otherwise, we should find a core from the path
idx = path.indexOf( "/", 1 ); idx = path.indexOf( "/", 1 );
if( idx <= 1 ) { if( idx > 1 ) {
idx = path.length(); // try to get the corename as a request parameter first
} String corename = path.substring( 1, idx );
path = path.substring( idx );
// try to get the corename as a request parameter first core = multicore.getCore( corename );
String corename = path.substring( 1, idx ); } else {
path = path.substring( idx ); core = null;
core = multicore.getCore( corename );
if( path.length() == 0 ) {
path = "/";
}
if( core == null ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown core: "+corename );
} }
} }
} }
SolrRequestParsers parser = parsers.get( core );
if( parser == null ) {
parser = new SolrRequestParsers( core.getSolrConfig() );
parsers.put( core, parser );
}
// Only try to parse the handler *if* a valid core exists
// when multi-core is enabled, the path can lead to a null core.
if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
handler = core.getRequestHandler( path );
}
if( handler == null && parser.isHandleSelect() ) {
if( "/select".equals( path ) || "/select/".equals( path ) ) {
solrReq = parser.parse( core, path, req );
String qt = solrReq.getParams().get( CommonParams.QT );
if( qt != null && qt.startsWith( "/" ) ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type. Do not use /select to access: "+qt);
}
handler = core.getRequestHandler( qt );
if( handler == null ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
}
}
}
if( handler != null ) {
if( solrReq == null ) {
solrReq = parser.parse( core, path, req );
}
final SolrConfig conf = core.getSolrConfig();
final Method reqMethod = Method.getMethod(req.getMethod());
if (Method.POST != reqMethod) {
HttpCacheHeaderUtil.setCacheControlHeader(conf, resp);
}
// unless we have been explicitly told not to, do cache validation
if (!conf.getHttpCachingConfig().isNever304()) {
// if we've confirmed cache validation, return immediately
if (HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req,resp)) {
return;
}
}
SolrQueryResponse solrRsp = new SolrQueryResponse();
/* even for HEAD requests, we need to execute the handler to
* ensure we don't get an error (and to make sure the correct
* QueryResponseWriter is selectedand we get the correct
* Content-Type)
*/
this.execute( req, handler, solrReq, solrRsp );
if( solrRsp.getException() != null ) {
sendError( (HttpServletResponse)response, solrRsp.getException() );
return;
}
// Now write it out
QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
if (Method.HEAD == Method.getMethod(req.getMethod())) {
// nothing to write out, waited this long just to get ContentType
return;
}
PrintWriter out = response.getWriter();
responseWriter.write(out, solrReq, solrRsp);
return;
}
// otherwise, let's ensure the core is in the SolrCore request attribute so
// the servlet/jsp can retrieve it
else { else {
req.setAttribute("org.apache.solr.SolrCore", core); core = singlecore;
}
// Let each core have its own admin page...
if( singlecore == null && path.startsWith( "/admin" ) ) { // With a valid core...
req.getRequestDispatcher( path ).forward( request, response ); if( core != null ) {
return; final SolrConfig config = core.getSolrConfig();
// get or create/cache the parser for the core
SolrRequestParsers parser = null;
parser = parsers.get(core);
if( parser == null ) {
parser = new SolrRequestParsers(config);
parsers.put( core, parser );
}
// Determine the handler from the url path if not set
// (we might already have selected the multicore handler)
if( handler == null && path.length() > 1 ) { // don't match "" or "/" as valid path
handler = core.getRequestHandler( path );
// no handler yet but allowed to handle select; let's check
if( handler == null && parser.isHandleSelect() ) {
if( "/select".equals( path ) || "/select/".equals( path ) ) {
solrReq = parser.parse( core, path, req );
String qt = solrReq.getParams().get( CommonParams.QT );
if( qt != null && qt.startsWith( "/" ) ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type. Do not use /select to access: "+qt);
}
handler = core.getRequestHandler( qt );
if( handler == null ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
}
}
}
}
// With a valid handler and a valid core...
if( handler != null ) {
// if not a /select, create the request
if( solrReq == null ) {
solrReq = parser.parse( core, path, req );
}
final Method reqMethod = Method.getMethod(req.getMethod());
if (Method.POST != reqMethod) {
HttpCacheHeaderUtil.setCacheControlHeader(config, resp);
}
// unless we have been explicitly told not to, do cache validation
// if we fail cache validation, execute the query
if (config.getHttpCachingConfig().isNever304() ||
!HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, resp)) {
SolrQueryResponse solrRsp = new SolrQueryResponse();
/* even for HEAD requests, we need to execute the handler to
* ensure we don't get an error (and to make sure the correct
* QueryResponseWriter is selectedand we get the correct
* Content-Type)
*/
this.execute( req, handler, solrReq, solrRsp );
if( solrRsp.getException() != null ) {
sendError( (HttpServletResponse)response, solrRsp.getException() );
}
else {
// Now write it out
QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
if (Method.HEAD != Method.getMethod(req.getMethod())) {
PrintWriter out = response.getWriter();
responseWriter.write(out, solrReq, solrRsp);
}
//else http HEAD request, nothing to write out, waited this long just to get ContentType
}
}
return; // we are done with a valid handler
}
// otherwise (we have a core), let's ensure the core is in the SolrCore request attribute so
// a servlet/jsp can retrieve it
else {
req.setAttribute("org.apache.solr.SolrCore", core);
// Modify the request so each core gets its own /admin
if( singlecore == null && path.startsWith( "/admin" ) ) {
req.getRequestDispatcher( path ).forward( request, response );
return;
}
} }
} }
} log.info("no handler or core retrieved for " + path + ", follow through...");
catch( Throwable ex ) { } catch (Throwable ex) {
sendError( (HttpServletResponse)response, ex ); sendError( (HttpServletResponse)response, ex );
return; return;
} } finally {
finally {
if( solrReq != null ) { if( solrReq != null ) {
solrReq.close(); solrReq.close();
} }
@ -326,8 +326,7 @@ public class SolrDispatchFilter implements Filter
sreq.getCore().execute( handler, sreq, rsp ); sreq.getCore().execute( handler, sreq, rsp );
} }
protected void sendError(HttpServletResponse res, Throwable ex) throws IOException protected void sendError(HttpServletResponse res, Throwable ex) throws IOException {
{
int code=500; int code=500;
String trace = ""; String trace = "";
if( ex instanceof SolrException ) { if( ex instanceof SolrException ) {