SOLR-215 -- extracting multicore config stuff from SOLR-350. This does three key things (that will make SOLR-350 easier to maintain)

1. extract SolrCore from SolrRequestParser -- this lets it be shared across cores
2. go back to the 1.2 interface for XmlUpdateRequestHandler
  public void doLegacyUpdate(Reader input, Writer output)
3. add a constructor to Config that lets you set the instanceDir explicitly (otherwise it forced static and needs to be specified as a property)


git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@578507 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2007-09-22 21:44:38 +00:00
parent d78f61db76
commit 6d8ae540e2
11 changed files with 145 additions and 135 deletions

View File

@ -59,7 +59,7 @@ public class EmbeddedSolrServer extends BaseSolrServer
public EmbeddedSolrServer( SolrCore core )
{
this.core = core;
this.parser = new SolrRequestParsers( core );
this.parser = new SolrRequestParsers( true, Long.MAX_VALUE );
// by default use the XML one
_processor = new XMLResponseParser();
@ -100,7 +100,7 @@ public class EmbeddedSolrServer extends BaseSolrServer
}
try {
SolrQueryRequest req = parser.buildRequestFrom( params, request.getContentStreams() );
SolrQueryRequest req = parser.buildRequestFrom( core, params, request.getContentStreams() );
req.getContext().put( "path", path );
SolrQueryResponse rsp = new SolrQueryResponse();
core.execute( handler, req, rsp );

View File

@ -50,16 +50,37 @@ public class Config {
static final XPathFactory xpathFactory = XPathFactory.newInstance();
private Document doc;
private String prefix;
private String name;
private final String instanceDir; // solr home directory
private final Document doc;
private final String prefix;
private final String name;
public Config(String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException {
@Deprecated
public Config(String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException
{
this( Config.locateInstanceDir(), name, is, prefix );
}
public Config(String instanceDir, String name) throws ParserConfigurationException, IOException, SAXException
{
this( instanceDir, name, null, null );
}
public Config(String instanceDir, String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException
{
if( instanceDir == null ) {
instanceDir = Config.locateInstanceDir();
}
this.instanceDir = normalizeDir(instanceDir);
log.info("Solr home set to '" + instanceDir + "'");
classLoader = null;
this.name = name;
this.prefix = prefix;
if (prefix!=null && !prefix.endsWith("/")) prefix += '/';
InputStream lis = is;
try{
try {
if (lis == null)
lis = openResource(name);
@ -194,7 +215,7 @@ public class Config {
// The directory where solr will look for config files by default.
// defaults to "./solr/conf/"
public String getConfigDir() {
return getInstanceDir() + "conf/";
return instanceDir + "conf/";
}
public InputStream openResource(String resource) {
@ -311,7 +332,6 @@ public class Config {
}
}
private String instanceDir; // solr home directory
private static String normalizeDir(String path) {
if (path==null) return null;
if ( !(path.endsWith("/") || path.endsWith("\\")) ) {
@ -320,55 +340,44 @@ public class Config {
return path;
}
public void setInstanceDir(String dir) {
instanceDir = normalizeDir(dir);
classLoader = null;
log.info("Solr home set to '" + instanceDir + "'");
}
public String getInstanceDir() {
if ( !isInstanceDirInitialized() ) {
String home = null;
// Try JNDI
try {
Context c = new InitialContext();
home = (String)c.lookup("java:comp/env/solr/home");
log.info("Using JNDI solr.home: "+home );
} catch (NoInitialContextException e) {
log.info("JNDI not configured for Solr (NoInitialContextEx)");
} catch (NamingException e) {
log.info("No /solr/home in JNDI");
} catch( RuntimeException ex ) {
log.warning("Odd RuntimeException while testing for JNDI: "
+ ex.getMessage());
}
// Now try system property
if( home == null ) {
String prop = project + ".solr.home";
home = normalizeDir(System.getProperty(prop));
if( home != null ) {
log.info("using system property solr.home: " + home );
}
}
// if all else fails, try
if( home == null ) {
home = project + '/';
log.info("Solr home defaulted to '" + instanceDir + "' (could not find system property or JNDI)");
}
setInstanceDir(home);
}
return instanceDir;
}
public boolean isInstanceDirInitialized() {
return instanceDir != null;
public static String locateInstanceDir() {
String home = null;
// Try JNDI
try {
Context c = new InitialContext();
home = (String)c.lookup("java:comp/env/solr/home");
log.info("Using JNDI solr.home: "+home );
} catch (NoInitialContextException e) {
log.info("JNDI not configured for Solr (NoInitialContextEx)");
} catch (NamingException e) {
log.info("No /solr/home in JNDI");
} catch( RuntimeException ex ) {
log.warning("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
}
// Now try system property
if( home == null ) {
String prop = project + ".solr.home";
home = normalizeDir(System.getProperty(prop));
if( home != null ) {
log.info("using system property solr.home: " + 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)");
}
return normalizeDir( home );
}
/** Singleton classloader loading resources specified in any configs */
private static ClassLoader classLoader = null;
private ClassLoader classLoader = null;
/**
* Returns the singleton classloader to be use when loading resources
@ -380,12 +389,12 @@ public class Config {
* found in the "lib/" directory in the "Solr Home" directory.
* <p>
*/
ClassLoader getClassLoader() {
private ClassLoader getClassLoader() {
if (null == classLoader) {
// NB5.5/win32/1.5_10: need to go thru local var or classLoader is not set!
ClassLoader loader = Thread.currentThread().getContextClassLoader();
File f = new File(getInstanceDir() + "lib/");
File f = new File(instanceDir + "lib/");
if (f.canRead() && f.isDirectory()) {
File[] jarFiles = f.listFiles();
URL[] jars = new URL[jarFiles.length];
@ -404,4 +413,10 @@ public class Config {
return classLoader;
}
/**
* @return the XML filename
*/
public String getName() {
return name;
}
}

View File

@ -74,35 +74,30 @@ public class SolrConfig extends Config {
* Singleton keeping track of configuration errors
*/
public static final Collection<Throwable> severeErrors = new HashSet<Throwable>();
/**
* Creates a configation information from the specified file.
* Add any exception that might occur to the severeErrors singleton.
* @param file file name to load
* @see Config#openResource
*/
public static SolrConfig createInstance(String file) {
try {
return new SolrConfig(file);
} catch (Exception ee) {
severeErrors.add( ee );
throw new RuntimeException("Error in " + file, ee);
}
}
/** Creates a default instance from the solrconfig.xml. */
public SolrConfig()
throws ParserConfigurationException, IOException, SAXException {
this(DEFAULT_CONF_FILE);
this( null, DEFAULT_CONF_FILE, null );
}
/** Creates a configuration instance from a file. */
public SolrConfig(String file)
throws ParserConfigurationException, IOException, SAXException {
this(file, null);
this( null, file, null);
}
/** Creates a configuration instance from an input stream. */
@Deprecated
public SolrConfig(String file, InputStream is)
throws ParserConfigurationException, IOException, SAXException {
super(file, is, "/config/");
throws ParserConfigurationException, IOException, SAXException
{
this( 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/");
this.configFile = file;
defaultIndexConfig = new SolrIndexConfig(this, null, null);
mainIndexConfig = new SolrIndexConfig(this, "mainIndex", defaultIndexConfig);

View File

@ -72,7 +72,8 @@ public final class SolrCore {
public static final String version="1.0";
public static Logger log = Logger.getLogger(SolrCore.class.getName());
private final SolrConfig solrConfig;
private final IndexSchema schema;
private final String dataDir;
private final String index_path;
@ -81,6 +82,7 @@ public final class SolrCore {
private final RequestHandlers reqHandlers;
private final SolrHighlighter highlighter;
private final Map<String,UpdateRequestProcessorFactory> updateProcessors;
private final Map<String,SolrInfoMBean> infoRegistry = new java.util.HashMap<String,SolrInfoMBean>();
public long getStartTime() { return startTime; }
@ -94,8 +96,9 @@ public final class SolrCore {
if (boolean_query_max_clause_count == Integer.MIN_VALUE) {
boolean_query_max_clause_count = solrConfig.booleanQueryMaxClauseCount;
BooleanQuery.setMaxClauseCount(boolean_query_max_clause_count);
} else if (boolean_query_max_clause_count != solrConfig.booleanQueryMaxClauseCount )
} else if (boolean_query_max_clause_count != solrConfig.booleanQueryMaxClauseCount ) {
log.fine("BooleanQuery.maxClauseCount= " +boolean_query_max_clause_count+ ", ignoring " +solrConfig.booleanQueryMaxClauseCount);
}
}
}
@ -111,9 +114,6 @@ public final class SolrCore {
return schema.getSchemaFile();
}
/** The configuration used by this core (to load resources, find classes, etc). */
private final SolrConfig solrConfig;
private Map<String,SolrInfoMBean> infoRegistry = new java.util.HashMap<String,SolrInfoMBean>();
/**
* @since solr 1.3

View File

@ -371,9 +371,9 @@ public class XmlUpdateRequestHandler extends RequestHandlerBase
* @since solr 1.2
*/
@Deprecated
public void doLegacyUpdate(SolrCore core, Reader input, Writer output) {
public void doLegacyUpdate(Reader input, Writer output) {
try {
//SolrCore core = SolrCore.getSolrCore();
SolrCore core = SolrCore.getSolrCore();
// Old style requests do not choose a custom handler
UpdateRequestProcessorFactory processorFactory = core.getUpdateProcessorFactory( null );

View File

@ -156,7 +156,9 @@ public class TestHarness {
StringReader req = new StringReader(xml);
StringWriter writer = new StringWriter(32000);
updater.doLegacyUpdate(core, req, writer);
// This relies on the fact that SolrCore.getSolrCore() uses the
// last instantiated SolrCore.
updater.doLegacyUpdate(req, writer);
return writer.toString();
}

View File

@ -48,7 +48,7 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
public void setUp() throws Exception {
super.setUp();
parser = new SolrRequestParsers(h.getCore() );
parser = new SolrRequestParsers( true, Long.MAX_VALUE );
}
public void testStreamBody() throws Exception
@ -57,19 +57,21 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
String body2 = "qwertasdfgzxcvb";
String body3 = "1234567890";
SolrCore core = SolrCore.getSolrCore();
Map<String,String[]> args = new HashMap<String, String[]>();
args.put( CommonParams.STREAM_BODY, new String[] {body1} );
// Make sure it got a single stream in and out ok
List<ContentStream> streams = new ArrayList<ContentStream>();
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
parser.buildRequestFrom( core, new MultiMapSolrParams( args ), streams );
assertEquals( 1, streams.size() );
assertEquals( body1, IOUtils.toString( streams.get(0).getStream() ) );
// Now add three and make sure they come out ok
streams = new ArrayList<ContentStream>();
args.put( CommonParams.STREAM_BODY, new String[] {body1,body2,body3} );
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
parser.buildRequestFrom( core, new MultiMapSolrParams( args ), streams );
assertEquals( 3, streams.size() );
ArrayList<String> input = new ArrayList<String>();
ArrayList<String> output = new ArrayList<String>();
@ -88,7 +90,7 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
String ctype = "text/xxx";
streams = new ArrayList<ContentStream>();
args.put( CommonParams.STREAM_CONTENTTYPE, new String[] {ctype} );
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
parser.buildRequestFrom( core, new MultiMapSolrParams( args ), streams );
for( ContentStream s : streams ) {
assertEquals( ctype, s.getContentType() );
}
@ -108,13 +110,15 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
fail( "this test only works if you have a network connection." );
return;
}
SolrCore core = SolrCore.getSolrCore();
Map<String,String[]> args = new HashMap<String, String[]>();
args.put( CommonParams.STREAM_URL, new String[] {url} );
// Make sure it got a single stream in and out ok
List<ContentStream> streams = new ArrayList<ContentStream>();
parser.buildRequestFrom( new MultiMapSolrParams( args ), streams );
parser.buildRequestFrom( core, new MultiMapSolrParams( args ), streams );
assertEquals( 1, streams.size() );
assertEquals( txt, IOUtils.toString( streams.get(0).getStream() ) );
}

View File

@ -29,7 +29,6 @@ import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.core.Config;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.QueryResponseWriter;
@ -59,7 +58,7 @@ public class DirectSolrConnection
public DirectSolrConnection()
{
core = SolrCore.getSolrCore();
parser = new SolrRequestParsers( core );
parser = new SolrRequestParsers( true, Long.MAX_VALUE );
}
/**
@ -68,7 +67,7 @@ public class DirectSolrConnection
public DirectSolrConnection( SolrCore c )
{
core = c;
parser = new SolrRequestParsers( core );
parser = new SolrRequestParsers( true, Long.MAX_VALUE );
}
/**
@ -100,27 +99,20 @@ public class DirectSolrConnection
}
}
// TODO! Set the instance directory
// if( instanceDir != null ) {
// if( Config.isInstanceDirInitialized() ) {
// String dir = Config.getInstanceDir();
// if( !dir.equals( instanceDir ) ) {
// throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "already initalized: "+dir );
// }
// }
// Config.setInstanceDir( instanceDir );
// }
SolrConfig config = SolrConfig.createInstance("solrconfig.xml");
// If the Data directory is specified, initialize SolrCore directly
if( dataDir != null ) {
// Initalize SolrConfig
SolrConfig config = null;
try {
config = new SolrConfig(instanceDir, SolrConfig.DEFAULT_CONF_FILE, null);
instanceDir = config.getInstanceDir();
// If the Data directory is specified, initialize SolrCore directly
IndexSchema schema = new IndexSchema(config, instanceDir+"/conf/schema.xml");
core = new SolrCore( dataDir, config, schema );
parser = new SolrRequestParsers( true, Long.MAX_VALUE );
}
catch (Exception ee) {
throw new RuntimeException(ee);
}
else {
core = SolrCore.getSolrCore();
}
parser = new SolrRequestParsers( core );
}
@ -165,7 +157,7 @@ public class DirectSolrConnection
streams.add( new ContentStreamBase.StringStream( body ) );
}
SolrQueryRequest req = parser.buildRequestFrom( params, streams );
SolrQueryRequest req = parser.buildRequestFrom( core, params, streams );
SolrQueryResponse rsp = new SolrQueryResponse();
core.execute( handler, req, rsp );
if( rsp.getException() != null ) {

View File

@ -34,6 +34,7 @@ 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.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.QueryResponseWriter;
@ -57,18 +58,31 @@ public class SolrDispatchFilter implements Filter
public void init(FilterConfig config) throws ServletException
{
log.info("SolrDispatchFilter.init()");
boolean abortOnConfigurationError = true;
try {
// web.xml configuration
this.pathPrefix = config.getInitParameter( "path-prefix" );
log.info("user.dir=" + System.getProperty("user.dir"));
core = SolrCore.getSolrCore();
parsers = new SolrRequestParsers( core );
// Read the configuration
Config solrConfig = core.getSolrConfig();
long uploadLimitKB = solrConfig.getInt(
"requestDispatcher/requestParsers/@multipartUploadLimitInKB", 2000 ); // 2MB default
boolean enableRemoteStreams = solrConfig.getBool(
"requestDispatcher/requestParsers/@enableRemoteStreaming", false );
parsers = new SolrRequestParsers( enableRemoteStreams, uploadLimitKB );
// Let this filter take care of /select?xxx format
this.handleSelect =
core.getSolrConfig().getBool( "requestDispatcher/@handleSelect", false );
this.handleSelect = solrConfig.getBool( "requestDispatcher/@handleSelect", false );
// should it keep going if we hit an error?
abortOnConfigurationError = solrConfig.getBool("abortOnConfigurationError",true);
}
catch( Throwable t ) {
// catch this so our filter still works
@ -78,7 +92,6 @@ public class SolrDispatchFilter implements Filter
}
// Optionally abort if we found a sever error
boolean abortOnConfigurationError = core.getSolrConfig().getBool("abortOnConfigurationError",true);
if( abortOnConfigurationError && SolrConfig.severeErrors.size() > 0 ) {
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter( sw );
@ -142,7 +155,7 @@ public class SolrDispatchFilter implements Filter
}
if( handler == null && handleSelect ) {
if( "/select".equals( path ) || "/select/".equals( path ) ) {
solrReq = parsers.parse( path, req );
solrReq = parsers.parse( core, path, req );
String qt = solrReq.getParams().get( CommonParams.QT );
if( qt != null && qt.startsWith( "/" ) ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type. Do not use /select to access: "+qt);
@ -155,7 +168,7 @@ public class SolrDispatchFilter implements Filter
}
if( handler != null ) {
if( solrReq == null ) {
solrReq = parsers.parse( path, req );
solrReq = parsers.parse( core, path, req );
}
SolrQueryResponse solrRsp = new SolrQueryResponse();
this.execute( req, handler, solrReq, solrRsp );

View File

@ -42,8 +42,6 @@ import org.apache.solr.common.params.MultiMapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.core.Config;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.ServletSolrParams;
import org.apache.solr.request.SolrQueryRequest;
@ -61,22 +59,13 @@ public class SolrRequestParsers
public static final String STANDARD = "standard";
private HashMap<String, SolrRequestParser> parsers;
private SolrCore core;
private boolean enableRemoteStreams = false;
private StandardRequestParser standard;
public SolrRequestParsers( SolrCore core )
public SolrRequestParsers( boolean enableRemoteStreams, long uploadLimitKB )
{
this.core = core;
Config config = core.getSolrConfig();
// Read the configuration
long uploadLimitKB = config.getInt(
"requestDispatcher/requestParsers/@multipartUploadLimitInKB", 2000 ); // 2MB default
this.enableRemoteStreams = config.getBool(
"requestDispatcher/requestParsers/@enableRemoteStreaming", false );
this.enableRemoteStreams = enableRemoteStreams;
MultipartRequestParser multi = new MultipartRequestParser( uploadLimitKB );
RawRequestParser raw = new RawRequestParser();
standard = new StandardRequestParser( multi, raw );
@ -91,7 +80,7 @@ public class SolrRequestParsers
parsers.put( "", standard );
}
public SolrQueryRequest parse( String path, HttpServletRequest req ) throws Exception
public SolrQueryRequest parse( SolrCore core, String path, HttpServletRequest req ) throws Exception
{
SolrRequestParser parser = standard;
@ -100,7 +89,7 @@ public class SolrRequestParsers
// Pick the parser from the request...
ArrayList<ContentStream> streams = new ArrayList<ContentStream>(1);
SolrParams params = parser.parseParamsAndFillStreams( req, streams );
SolrQueryRequest sreq = buildRequestFrom( params, streams );
SolrQueryRequest sreq = buildRequestFrom( core, params, streams );
// Handlers and loggin will want to know the path. If it contains a ':'
// the handler could use it for RESTfull URLs
@ -108,7 +97,7 @@ public class SolrRequestParsers
return sreq;
}
public SolrQueryRequest buildRequestFrom( SolrParams params, Collection<ContentStream> streams ) throws Exception
public SolrQueryRequest buildRequestFrom( SolrCore core, SolrParams params, Collection<ContentStream> streams ) throws Exception
{
// The content type will be applied to all streaming content
String contentType = params.get( CommonParams.STREAM_CONTENTTYPE );

View File

@ -25,7 +25,6 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.XmlUpdateRequestHandler;
import org.apache.solr.request.QueryResponseWriter;
import org.apache.solr.request.XMLResponseWriter;
@ -40,6 +39,7 @@ public class SolrUpdateServlet extends HttpServlet {
XmlUpdateRequestHandler legacyUpdateHandler;
XMLResponseWriter xmlResponseWriter;
@Override
public void init() throws ServletException
{
legacyUpdateHandler = new XmlUpdateRequestHandler();
@ -48,12 +48,12 @@ public class SolrUpdateServlet extends HttpServlet {
log.info("SolrUpdateServlet.init() done");
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BufferedReader requestReader = request.getReader();
response.setContentType(QueryResponseWriter.CONTENT_TYPE_XML_UTF8);
SolrCore core = SolrCore.getSolrCore();
PrintWriter writer = response.getWriter();
legacyUpdateHandler.doLegacyUpdate(core,requestReader, writer);
legacyUpdateHandler.doLegacyUpdate(requestReader, writer);
}
}