SOLR-4478: Allow cores to use configurations specified outside their instance directory

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1580814 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Alan Woodward 2014-03-24 10:54:51 +00:00
parent 00d2b4d960
commit 0e8d8fefae
35 changed files with 1141 additions and 372 deletions

View File

@ -110,10 +110,6 @@ System Requirements
* LUCENE-4747, LUCENE-5514: Move to Java 7 as minimum Java version.
(Robert Muir, Uwe Schindler)
* SOLR-5858: Add a hl.qparser parameter to allow you to define a queryparser
for hl.q highlight queries. If no queryparser is defined, Solr will use
the overall query's defType. (Alan Woodward)
New Features
----------------------
@ -156,6 +152,13 @@ New Features
* SOLR-5749: A new Overseer status collection API exposes overseer queue sizes, timing
statistics, success and error counts and last N failures per operation. (shalin)
* SOLR-5858: Add a hl.qparser parameter to allow you to define a queryparser
for hl.q highlight queries. If no queryparser is defined, Solr will use
the overall query's defType. (Alan Woodward)
* SOLR-4478: Allow cores to use configuration from a configsets directory
outside their instance directory. (Alan Woodward, Erick Erickson)
Bug Fixes
----------------------

View File

@ -0,0 +1,46 @@
/*
* 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.cloud;
import org.apache.solr.core.ConfigSetService;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.core.SolrResourceLoader;
public class CloudConfigSetService extends ConfigSetService {
private final ZkController zkController;
public CloudConfigSetService(SolrResourceLoader loader, ZkController zkController) {
super(loader);
this.zkController = zkController;
}
@Override
public SolrResourceLoader createCoreResourceLoader(CoreDescriptor cd) {
// TODO: Shouldn't the collection node be created by the Collections API?
zkController.createCollectionZkNode(cd.getCloudDescriptor());
String configName = zkController.getZkStateReader().readConfigName(cd.getCollectionName());
return new ZkSolrResourceLoader(cd.getInstanceDir(), configName, parentLoader.getClassLoader(),
cd.getSubstitutableProperties(), zkController);
}
@Override
public String configName(CoreDescriptor cd) {
return "collection " + cd.getCloudDescriptor().getCollectionName();
}
}

View File

@ -1131,7 +1131,7 @@ public final class ZkController {
zkClient.printLayoutToStdOut();
}
public void createCollectionZkNode(CloudDescriptor cd) throws KeeperException, InterruptedException {
public void createCollectionZkNode(CloudDescriptor cd) {
String collection = cd.getCollectionName();
log.info("Check for collection zkNode:" + collection);
@ -1204,9 +1204,14 @@ public final class ZkController {
} catch (KeeperException e) {
// its okay if another beats us creating the node
if (e.code() != KeeperException.Code.NODEEXISTS) {
throw e;
if (e.code() == KeeperException.Code.NODEEXISTS) {
return;
}
throw new SolrException(ErrorCode.SERVER_ERROR, "Error creating collection node in Zookeeper", e);
}
catch (InterruptedException e) {
Thread.interrupted();
throw new SolrException(ErrorCode.SERVER_ERROR, "Error creating collection node in Zookeeper", e);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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 org.apache.solr.schema.IndexSchema;
/**
* Stores a core's configuration in the form of a SolrConfig and IndexSchema
*/
public class ConfigSet {
private final String name;
private final SolrConfig solrconfig;
private final IndexSchema indexSchema;
public ConfigSet(String name, SolrConfig solrConfig, IndexSchema indexSchema) {
this.name = name;
this.solrconfig = solrConfig;
this.indexSchema = indexSchema;
}
public String getName() {
return name;
}
public SolrConfig getSolrConfig() {
return solrconfig;
}
public IndexSchema getIndexSchema() {
return indexSchema;
}
}

View File

@ -0,0 +1,197 @@
/*
* 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 com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.solr.common.SolrException;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
/**
* Service class used by the CoreContainer to load ConfigSets for use in SolrCore
* creation.
*/
public abstract class ConfigSetService {
protected final SolrResourceLoader parentLoader;
/**
* Create a new ConfigSetService
* @param loader the CoreContainer's resource loader
*/
public ConfigSetService(SolrResourceLoader loader) {
this.parentLoader = loader;
}
/**
* Load the ConfigSet for a core
* @param dcore the core's CoreDescriptor
* @return a ConfigSet
*/
public final ConfigSet getConfig(CoreDescriptor dcore) {
SolrResourceLoader coreLoader = createCoreResourceLoader(dcore);
try {
SolrConfig solrConfig = createSolrConfig(dcore, coreLoader);
IndexSchema schema = createIndexSchema(dcore, solrConfig);
return new ConfigSet(configName(dcore), solrConfig, schema);
}
catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Could not load core configuration for core " + dcore.getName(), e);
}
}
/**
* Create a SolrConfig object for a core
* @param cd the core's CoreDescriptor
* @param loader the core's resource loader
* @return a SolrConfig object
*/
protected SolrConfig createSolrConfig(CoreDescriptor cd, SolrResourceLoader loader) {
return SolrConfig.readFromResourceLoader(loader, cd.getConfigName());
}
/**
* Create an IndexSchema object for a core
* @param cd the core's CoreDescriptor
* @param solrConfig the core's SolrConfig
* @return an IndexSchema
*/
protected IndexSchema createIndexSchema(CoreDescriptor cd, SolrConfig solrConfig) {
return IndexSchemaFactory.buildIndexSchema(cd.getSchemaName(), solrConfig);
}
/**
* Create a SolrResourceLoader for a core
* @param cd the core's CoreDescriptor
* @return a SolrResourceLoader
*/
protected abstract SolrResourceLoader createCoreResourceLoader(CoreDescriptor cd);
/**
* Return a name for the ConfigSet for a core
* @param cd the core's CoreDescriptor
* @return a name for the core's ConfigSet
*/
public abstract String configName(CoreDescriptor cd);
/**
* The default ConfigSetService.
*
* Loads a ConfigSet defined by the core's configSet property,
* looking for a directory named for the configSet property value underneath
* a base directory. If no configSet property is set, loads the ConfigSet
* instead from the core's instance directory.
*/
public static class Default extends ConfigSetService {
private final String configSetBase;
/**
* Create a new ConfigSetService.Default
* @param loader the CoreContainer's resource loader
* @param configSetBase the base directory under which to look for config set directories
*/
public Default(SolrResourceLoader loader, String configSetBase) {
super(loader);
this.configSetBase = configSetBase;
}
@Override
public SolrResourceLoader createCoreResourceLoader(CoreDescriptor cd) {
String instanceDir = locateInstanceDir(cd);
return new SolrResourceLoader(instanceDir, parentLoader.getClassLoader(), cd.getSubstitutableProperties());
}
@Override
public String configName(CoreDescriptor cd) {
return (cd.getConfigSet() == null ? "instancedir " : "configset ") + locateInstanceDir(cd);
}
protected String locateInstanceDir(CoreDescriptor cd) {
String configSet = cd.getConfigSet();
if (configSet == null)
return cd.getInstanceDir();
File configSetDirectory = new File(configSetBase, configSet);
if (!configSetDirectory.exists() || !configSetDirectory.isDirectory())
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Could not load configuration from directory " + configSetDirectory.getAbsolutePath());
return configSetDirectory.getAbsolutePath();
}
}
/**
* A ConfigSetService that shares schema objects between cores
*/
public static class SchemaCaching extends Default {
private static final Logger logger = LoggerFactory.getLogger(SchemaCaching.class);
private final Cache<String, IndexSchema> schemaCache = CacheBuilder.newBuilder().build();
public SchemaCaching(SolrResourceLoader loader, String configSetBase) {
super(loader, configSetBase);
}
public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormat.forPattern("yyyyMMddHHmmss");
public static String cacheName(File schemaFile) {
return String.format(Locale.ROOT, "%s:%s",
schemaFile.getAbsolutePath(), cacheKeyFormatter.print(schemaFile.lastModified()));
}
@Override
public IndexSchema createIndexSchema(final CoreDescriptor cd, final SolrConfig solrConfig) {
final String resourceNameToBeUsed = IndexSchemaFactory.getResourceNameToBeUsed(cd.getSchemaName(), solrConfig);
File schemaFile = new File(resourceNameToBeUsed);
if (!schemaFile.isAbsolute()) {
schemaFile = new File(solrConfig.getResourceLoader().getConfigDir(), schemaFile.getPath());
}
if (schemaFile.exists()) {
try {
return schemaCache.get(cacheName(schemaFile), new Callable<IndexSchema>() {
@Override
public IndexSchema call() throws Exception {
logger.info("Creating new index schema for core {}", cd.getName());
return IndexSchemaFactory.buildIndexSchema(cd.getSchemaName(), solrConfig);
}
});
} catch (ExecutionException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Error creating index schema for core " + cd.getName(), e);
}
}
return IndexSchemaFactory.buildIndexSchema(cd.getSchemaName(), solrConfig);
}
}
}

View File

@ -21,6 +21,8 @@ import com.google.common.base.Charsets;
import com.google.common.io.ByteStreams;
import org.apache.commons.io.IOUtils;
import org.apache.solr.cloud.CloudConfigSetService;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.common.SolrException;
import org.apache.solr.logging.LogWatcherConfig;
import org.apache.solr.util.DOMUtil;
@ -221,6 +223,10 @@ public abstract class ConfigSolr {
return get(CfgProp.SOLR_MANAGEMENTPATH, null);
}
public String getConfigSetBaseDirectory() {
return get(CfgProp.SOLR_CONFIGSETBASEDIR, "configsets");
}
public LogWatcherConfig getLogWatcherConfig() {
return new LogWatcherConfig(
getBool(CfgProp.SOLR_LOGGING_ENABLED, true),
@ -234,6 +240,14 @@ public abstract class ConfigSolr {
return getInt(CfgProp.SOLR_TRANSIENTCACHESIZE, Integer.MAX_VALUE);
}
public ConfigSetService createCoreConfigService(SolrResourceLoader loader, ZkController zkController) {
if (getZkHost() != null)
return new CloudConfigSetService(loader, zkController);
if (hasSchemaCache())
return new ConfigSetService.SchemaCaching(loader, getConfigSetBaseDirectory());
return new ConfigSetService.Default(loader, getConfigSetBaseDirectory());
}
// Ugly for now, but we'll at least be able to centralize all of the differences between 4x and 5x.
protected static enum CfgProp {
SOLR_ADMINHANDLER,
@ -261,6 +275,7 @@ public abstract class ConfigSolr {
SOLR_ZKCLIENTTIMEOUT,
SOLR_ZKHOST,
SOLR_LEADERCONFLICTRESOLVEWAIT,
SOLR_CONFIGSETBASEDIR,
//TODO: Remove all of these elements for 5.0
SOLR_PERSISTENT,

View File

@ -122,6 +122,7 @@ public class ConfigSolrXml extends ConfigSolr {
propMap.put(CfgProp.SOLR_TRANSIENTCACHESIZE, doSub("solr/int[@name='transientCacheSize']"));
propMap.put(CfgProp.SOLR_ZKCLIENTTIMEOUT, doSub("solr/solrcloud/int[@name='zkClientTimeout']"));
propMap.put(CfgProp.SOLR_ZKHOST, doSub("solr/solrcloud/str[@name='zkHost']"));
propMap.put(CfgProp.SOLR_CONFIGSETBASEDIR, doSub("solr/str[@name='configSetBaseDir']"));
propMap.put(CfgProp.SOLR_LOGGING_CLASS, doSub("solr/logging/str[@name='class']"));
propMap.put(CfgProp.SOLR_LOGGING_ENABLED, doSub("solr/logging/str[@name='enabled']"));

View File

@ -168,6 +168,7 @@ public class ConfigSolrXmlOld extends ConfigSolr {
config.getVal("solr/cores/@transientCacheSize", false));
propMap.put(CfgProp.SOLR_ZKCLIENTTIMEOUT,
config.getVal("solr/cores/@zkClientTimeout", false));
propMap.put(CfgProp.SOLR_CONFIGSETBASEDIR, config.getVal("solr/cores/@configSetBaseDir", false));
// These have no counterpart in 5.0, asking, for any of these in Solr 5.0
// will result in an error being

View File

@ -20,30 +20,23 @@ package org.apache.solr.core;
import com.google.common.collect.Maps;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.handler.admin.InfoHandler;
import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.logging.LogWatcher;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.update.UpdateShardHandler;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.FileUtils;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@ -53,7 +46,6 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
@ -82,8 +74,7 @@ public class CoreContainer {
protected Properties containerProperties;
protected Map<String ,IndexSchema> indexSchemaCache;
protected boolean shareSchema;
private ConfigSetService coreConfigService;
protected ZkContainer zkSys = new ZkContainer();
protected ShardHandlerFactory shardHandlerFactory;
@ -210,6 +201,7 @@ public class CoreContainer {
loader.reloadLuceneSPI();
}
shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
updateShardHandler = new UpdateShardHandler(cfg);
@ -218,12 +210,6 @@ public class CoreContainer {
logging = LogWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
shareSchema = cfg.hasSchemaCache();
if (shareSchema) {
indexSchemaCache = new ConcurrentHashMap<>();
}
hostName = cfg.getHost();
log.info("Host Name: " + hostName);
@ -233,6 +219,8 @@ public class CoreContainer {
infoHandler = createHandler(cfg.getInfoHandlerClass(), InfoHandler.class);
coreAdminHandler = createHandler(cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
coreConfigService = cfg.createCoreConfigService(loader, zkSys.getZkController());
containerProperties = cfg.getSolrProperties("solr");
// setup executor to load cores in parallel
@ -540,55 +528,13 @@ public class CoreContainer {
return registerCore(core.getCoreDescriptor().isTransient(), name, core, returnPrev);
}
// Helper method to separate out creating a core from local configuration files. See create()
private SolrCore createFromLocal(String instanceDir, CoreDescriptor dcore) {
SolrResourceLoader solrLoader = null;
SolrConfig config = null;
solrLoader = new SolrResourceLoader(instanceDir, loader.getClassLoader(), dcore.getSubstitutableProperties());
try {
config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
} catch (Exception e) {
log.error("Failed to load file {}", new File(instanceDir, dcore.getConfigName()).getAbsolutePath());
throw new SolrException(ErrorCode.SERVER_ERROR,
"Could not load config file " + new File(instanceDir, dcore.getConfigName()).getAbsolutePath(),
e);
public SolrCore create(String name, String instanceDir, String... properties) {
Properties props = new Properties();
assert properties.length % 2 == 0;
for (int i = 0; i < properties.length; i += 2) {
props.setProperty(properties[i], properties[i+1]);
}
IndexSchema schema = null;
if (indexSchemaCache != null) {
final String resourceNameToBeUsed = IndexSchemaFactory.getResourceNameToBeUsed(dcore.getSchemaName(), config);
File schemaFile = new File(resourceNameToBeUsed);
if (!schemaFile.isAbsolute()) {
schemaFile = new File(solrLoader.getConfigDir(), schemaFile.getPath());
}
if (schemaFile.exists()) {
String key = schemaFile.getAbsolutePath()
+ ":"
+ new SimpleDateFormat("yyyyMMddHHmmss", Locale.ROOT).format(new Date(
schemaFile.lastModified()));
schema = indexSchemaCache.get(key);
if (schema == null) {
log.info("creating new schema object for core: " + dcore.getName());
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
indexSchemaCache.put(key, schema);
} else {
log.info("re-using schema object for core: " + dcore.getName());
}
}
}
if (schema == null) {
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
}
SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
if (core.getUpdateHandler().getUpdateLog() != null) {
// always kick off recovery if we are in standalone mode.
core.getUpdateHandler().getUpdateLog().recoverFromLog();
}
return core;
return create(new CoreDescriptor(this, name, instanceDir, props));
}
/**
@ -603,31 +549,25 @@ public class CoreContainer {
throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Solr has shutdown.");
}
final String name = dcore.getName();
try {
// Make the instanceDir relative to the cores instanceDir if not absolute
File idir = new File(dcore.getInstanceDir());
String instanceDir = idir.getPath();
log.info("Creating SolrCore '{}' using instanceDir: {}",
dcore.getName(), instanceDir);
// Initialize the solr config
SolrCore created = null;
if (zkSys.getZkController() != null) {
created = zkSys.createFromZk(instanceDir, dcore, loader);
} else {
created = createFromLocal(instanceDir, dcore);
ConfigSet coreConfig = coreConfigService.getConfig(dcore);
log.info("Creating SolrCore '{}' using configuration from {}", dcore.getName(), coreConfig.getName());
SolrCore core = new SolrCore(dcore, coreConfig);
solrCores.addCreated(core);
// always kick off recovery if we are in non-Cloud mode
if (!isZooKeeperAware() && core.getUpdateHandler().getUpdateLog() != null) {
core.getUpdateHandler().getUpdateLog().recoverFromLog();
}
solrCores.addCreated(created); // For persisting newly-created cores.
return created;
return core;
// :TODO: Java7...
// http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
} catch (Exception ex) {
throw recordAndThrow(name, "Unable to create core: " + name, ex);
}
catch (Exception e) {
throw recordAndThrow(dcore.getName(), "Unable to create core: " + dcore.getName(), e);
}
}
/**
@ -705,41 +645,9 @@ public class CoreContainer {
try {
solrCores.waitAddPendingCoreOps(name);
CoreDescriptor cd = core.getCoreDescriptor();
File instanceDir = new File(cd.getInstanceDir());
log.info("Reloading SolrCore '{}' using instanceDir: {}",
cd.getName(), instanceDir.getAbsolutePath());
SolrResourceLoader solrLoader;
if(zkSys.getZkController() == null) {
solrLoader = new SolrResourceLoader(instanceDir.getAbsolutePath(), loader.getClassLoader(),
cd.getSubstitutableProperties());
} else {
try {
String collection = cd.getCloudDescriptor().getCollectionName();
zkSys.getZkController().createCollectionZkNode(cd.getCloudDescriptor());
String zkConfigName = zkSys.getZkController().getZkStateReader().readConfigName(collection);
if (zkConfigName == null) {
log.error("Could not find config name for collection:" + collection);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
"Could not find config name for collection:" + collection);
}
solrLoader = new ZkSolrResourceLoader(instanceDir.getAbsolutePath(), zkConfigName, loader.getClassLoader(),
cd.getSubstitutableProperties(), zkSys.getZkController());
} catch (KeeperException e) {
log.error("", e);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
"", e);
} catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
log.error("", e);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
"", e);
}
}
SolrCore newCore = core.reload(solrLoader, core);
ConfigSet coreConfig = coreConfigService.getConfig(cd);
log.info("Reloading SolrCore '{}' using configuration from {}", cd.getName(), coreConfig.getName());
SolrCore newCore = core.reload(coreConfig, core);
// keep core to orig name link
solrCores.removeCoreToOrigName(newCore, core);
registerCore(false, name, newCore, false, false);
@ -989,10 +897,6 @@ public class CoreContainer {
return zkSys.getZkController();
}
public boolean isShareSchema() {
return shareSchema;
}
/** The default ShardHandlerFactory used to communicate with other solr instances */
public ShardHandlerFactory getShardHandlerFactory() {
return shardHandlerFactory;
@ -1015,6 +919,10 @@ public class CoreContainer {
String getCoreToOrigName(SolrCore core) {
return solrCores.getCoreToOrigName(core);
}
public SolrResourceLoader getResourceLoader() {
return loader;
}
}
class CloserThread extends Thread {

View File

@ -58,6 +58,7 @@ public class CoreDescriptor {
public static final String CORE_LOADONSTARTUP = "loadOnStartup";
public static final String CORE_TRANSIENT = "transient";
public static final String CORE_NODE_NAME = "coreNodeName";
public static final String CORE_CONFIGSET = "configSet";
public static final String SOLR_CORE_PROP_PREFIX = "solr.core.";
public static final String DEFAULT_EXTERNAL_PROPERTIES_FILE = "conf" + File.separator + "solrcore.properties";
@ -100,6 +101,7 @@ public class CoreDescriptor {
CORE_PROPERTIES,
CORE_LOADONSTARTUP,
CORE_TRANSIENT,
CORE_CONFIGSET,
// cloud props
CORE_SHARD,
CORE_COLLECTION,
@ -390,4 +392,8 @@ public class CoreDescriptor {
.append("]")
.toString();
}
public String getConfigSet() {
return coreProperties.getProperty(CORE_CONFIGSET);
}
}

View File

@ -17,31 +17,30 @@
package org.apache.solr.core;
import static org.apache.solr.core.SolrConfig.PluginOpts.*;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.util.Version;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.FileUtils;
import org.apache.solr.util.RegexFileFilter;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.rest.RestManager;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.search.CacheConfig;
import org.apache.solr.search.FastLRUCache;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.ValueSourceParser;
import org.apache.solr.servlet.SolrRequestParsers;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.update.SolrIndexConfig;
import org.apache.solr.update.UpdateLog;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.spelling.QueryConverter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.util.Version;
import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.FileUtils;
import org.apache.solr.util.RegexFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
@ -51,13 +50,24 @@ import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.solr.core.SolrConfig.PluginOpts.MULTI_OK;
import static org.apache.solr.core.SolrConfig.PluginOpts.NOOP;
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS;
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME;
/**
@ -129,6 +139,16 @@ public class SolrConfig extends Config {
this(new SolrResourceLoader(instanceDir), name, is);
}
public static SolrConfig readFromResourceLoader(SolrResourceLoader loader, String name) {
try {
return new SolrConfig(loader, name, null);
}
catch (Exception e) {
String resource = loader.getInstanceDir() + name;
throw new SolrException(ErrorCode.SERVER_ERROR, "Error loading solr config from " + resource, e);
}
}
/** Creates a configuration instance from a resource loader, a configuration name and a stream.
* If the stream is null, the resource loader will open the configuration stream.
* If the stream is not null, no attempt to load the resource will occur (the name is not used).

View File

@ -17,6 +17,88 @@
package org.apache.solr.core;
import org.apache.commons.io.IOUtils;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.solr.cloud.CloudDescriptor;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.CommonParams.EchoParamStyle;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.DirectoryFactory.DirContext;
import org.apache.solr.handler.SnapPuller;
import org.apache.solr.handler.admin.ShowFileRequestHandler;
import org.apache.solr.handler.component.AnalyticsComponent;
import org.apache.solr.handler.component.DebugComponent;
import org.apache.solr.handler.component.ExpandComponent;
import org.apache.solr.handler.component.FacetComponent;
import org.apache.solr.handler.component.HighlightComponent;
import org.apache.solr.handler.component.MoreLikeThisComponent;
import org.apache.solr.handler.component.QueryComponent;
import org.apache.solr.handler.component.RealTimeGetComponent;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.handler.component.StatsComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.BinaryResponseWriter;
import org.apache.solr.response.CSVResponseWriter;
import org.apache.solr.response.JSONResponseWriter;
import org.apache.solr.response.PHPResponseWriter;
import org.apache.solr.response.PHPSerializedResponseWriter;
import org.apache.solr.response.PythonResponseWriter;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.RawResponseWriter;
import org.apache.solr.response.RubyResponseWriter;
import org.apache.solr.response.SchemaXmlResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.response.XMLResponseWriter;
import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.rest.ManagedResourceStorage;
import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
import org.apache.solr.rest.RestManager;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.schema.SimilarityFactory;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.SolrFieldCacheMBean;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.ValueSourceParser;
import org.apache.solr.update.DefaultSolrCoreState;
import org.apache.solr.update.DirectUpdateHandler2;
import org.apache.solr.update.SolrCoreState;
import org.apache.solr.update.SolrCoreState.IndexWriterCloser;
import org.apache.solr.update.SolrIndexWriter;
import org.apache.solr.update.UpdateHandler;
import org.apache.solr.update.VersionInfo;
import org.apache.solr.update.processor.DistributedUpdateProcessorFactory;
import org.apache.solr.update.processor.LogUpdateProcessorFactory;
import org.apache.solr.update.processor.RunUpdateProcessorFactory;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.PropertiesInputStream;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -51,89 +133,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.IOUtils;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.solr.cloud.CloudDescriptor;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.params.CommonParams.EchoParamStyle;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.DirectoryFactory.DirContext;
import org.apache.solr.handler.SnapPuller;
import org.apache.solr.handler.admin.ShowFileRequestHandler;
import org.apache.solr.handler.component.AnalyticsComponent;
import org.apache.solr.handler.component.DebugComponent;
import org.apache.solr.handler.component.ExpandComponent;
import org.apache.solr.handler.component.FacetComponent;
import org.apache.solr.handler.component.HighlightComponent;
import org.apache.solr.handler.component.MoreLikeThisComponent;
import org.apache.solr.handler.component.QueryComponent;
import org.apache.solr.handler.component.RealTimeGetComponent;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.handler.component.StatsComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.BinaryResponseWriter;
import org.apache.solr.response.CSVResponseWriter;
import org.apache.solr.response.JSONResponseWriter;
import org.apache.solr.response.PHPResponseWriter;
import org.apache.solr.response.PHPSerializedResponseWriter;
import org.apache.solr.response.PythonResponseWriter;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.RawResponseWriter;
import org.apache.solr.response.RubyResponseWriter;
import org.apache.solr.response.SchemaXmlResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.response.XMLResponseWriter;
import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
import org.apache.solr.rest.ManagedResourceStorage;
import org.apache.solr.rest.RestManager;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.schema.SimilarityFactory;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.SolrFieldCacheMBean;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.ValueSourceParser;
import org.apache.solr.update.DefaultSolrCoreState;
import org.apache.solr.update.DirectUpdateHandler2;
import org.apache.solr.update.SolrCoreState.IndexWriterCloser;
import org.apache.solr.update.SolrCoreState;
import org.apache.solr.update.SolrIndexWriter;
import org.apache.solr.update.UpdateHandler;
import org.apache.solr.update.VersionInfo;
import org.apache.solr.update.processor.DistributedUpdateProcessorFactory;
import org.apache.solr.update.processor.LogUpdateProcessorFactory;
import org.apache.solr.update.processor.RunUpdateProcessorFactory;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.PropertiesInputStream;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
*
@ -412,17 +411,8 @@ public final class SolrCore implements SolrInfoMBean {
return responseWriters.put(name, responseWriter);
}
public SolrCore reload(SolrCore prev) throws IOException,
public SolrCore reload(ConfigSet coreConfig, SolrCore prev) throws IOException,
ParserConfigurationException, SAXException {
return reload(prev.getResourceLoader(), prev);
}
public SolrCore reload(SolrResourceLoader resourceLoader, SolrCore prev) throws IOException,
ParserConfigurationException, SAXException {
SolrConfig config = new SolrConfig(resourceLoader, getSolrConfig().getName(), null);
IndexSchema schema = IndexSchemaFactory.buildIndexSchema(getLatestSchema().getResourceName(), config);
solrCoreState.increfSolrCoreState();
@ -431,8 +421,8 @@ public final class SolrCore implements SolrInfoMBean {
prev = null;
}
SolrCore core = new SolrCore(getName(), getDataDir(), config,
schema, coreDescriptor, updateHandler, this.solrDelPolicy, prev);
SolrCore core = new SolrCore(getName(), getDataDir(), coreConfig.getSolrConfig(),
coreConfig.getIndexSchema(), coreDescriptor, updateHandler, this.solrDelPolicy, prev);
core.solrDelPolicy = this.solrDelPolicy;
core.getUpdateHandler().getSolrCoreState().newIndexWriter(core, false);
@ -645,6 +635,10 @@ public final class SolrCore implements SolrInfoMBean {
this(name, dataDir, config, schema, cd, null, null, null);
}
public SolrCore(CoreDescriptor cd, ConfigSet coreConfig) {
this(cd.getName(), null, coreConfig.getSolrConfig(), coreConfig.getIndexSchema(), cd, null, null, null);
}
/**
* Creates a new core that is to be loaded lazily. i.e. lazyLoad="true" in solr.xml

View File

@ -20,21 +20,15 @@ package org.apache.solr.core;
import org.apache.solr.cloud.CurrentCoreDescriptorProvider;
import org.apache.solr.cloud.SolrZkServer;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.cloud.ZooKeeperException;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.SystemIdResolver;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@ -198,42 +192,6 @@ public class ZkContainer {
this.zkController = zkController;
}
// Helper method to separate out creating a core from ZK as opposed to the
// "usual" way. See create()
SolrCore createFromZk(String instanceDir, CoreDescriptor dcore, SolrResourceLoader loader) {
try {
SolrResourceLoader solrLoader = null;
SolrConfig config = null;
String zkConfigName = null;
IndexSchema schema;
String collection = dcore.getCloudDescriptor().getCollectionName();
zkController.createCollectionZkNode(dcore.getCloudDescriptor());
zkConfigName = zkController.getZkStateReader().readConfigName(collection);
if (zkConfigName == null) {
log.error("Could not find config name for collection:" + collection);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
"Could not find config name for collection:" + collection);
}
solrLoader = new ZkSolrResourceLoader(instanceDir, zkConfigName,
loader.getClassLoader(), dcore.getSubstitutableProperties(), zkController);
config = getSolrConfigFromZk(zkConfigName, dcore.getConfigName(),
solrLoader);
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(),
config);
return new SolrCore(dcore.getName(), null, config, schema, dcore);
} catch (KeeperException e) {
log.error("", e);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
} catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
log.error("", e);
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
}
}
public void registerInZk(final SolrCore core, boolean background) {
Thread thread = new Thread() {
@Override
@ -268,26 +226,6 @@ public class ZkContainer {
}
}
public SolrConfig getSolrConfigFromZk(String zkConfigName, String solrConfigFileName,
SolrResourceLoader resourceLoader) {
SolrConfig cfg = null;
try {
byte[] config = zkController.getConfigFileData(zkConfigName,
solrConfigFileName);
InputSource is = new InputSource(new ByteArrayInputStream(config));
is.setSystemId(SystemIdResolver
.createSystemIdFromResourceName(solrConfigFileName));
cfg = solrConfigFileName == null ? new SolrConfig(resourceLoader,
SolrConfig.DEFAULT_CONF_FILE, is) : new SolrConfig(resourceLoader,
solrConfigFileName, is);
} catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"getSolrConfigFromZK failed for " + zkConfigName + " "
+ solrConfigFileName, e);
}
return cfg;
}
public ZkController getZkController() {
return zkController;
}
@ -300,6 +238,7 @@ public class ZkContainer {
} catch (KeeperException e) {
CoreContainer.log.error("", e);
} catch (InterruptedException e) {
Thread.interrupted();
CoreContainer.log.error("", e);
}
}

View File

@ -86,7 +86,6 @@ import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static org.apache.solr.common.cloud.DocCollection.DOC_ROUTER;
@ -488,6 +487,7 @@ public class CoreAdminHandler extends RequestHandlerBase {
.put(CoreAdminParams.SCHEMA, CoreDescriptor.CORE_SCHEMA)
.put(CoreAdminParams.DATA_DIR, CoreDescriptor.CORE_DATADIR)
.put(CoreAdminParams.ULOG_DIR, CoreDescriptor.CORE_ULOGDIR)
.put(CoreAdminParams.CONFIGSET, CoreDescriptor.CORE_CONFIGSET)
.put(CoreAdminParams.LOAD_ON_STARTUP, CoreDescriptor.CORE_LOADONSTARTUP)
.put(CoreAdminParams.TRANSIENT, CoreDescriptor.CORE_TRANSIENT)
.put(CoreAdminParams.SHARD, CoreDescriptor.CORE_SHARD)

View File

@ -81,7 +81,6 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

View File

@ -0,0 +1,58 @@
<?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.
-->
<!--
Small solrconfig with a /get handler defined, for use in TestConfigSets#testConfigSetOnReload
-->
<config>
<dataDir>${solr.data.dir:}</dataDir>
<directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<updateHandler class="solr.DirectUpdateHandler2">
<commitWithin>
<softCommit>${solr.commitwithin.softcommit:true}</softCommit>
</commitWithin>
</updateHandler>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
<requestHandler name="/get" class="solr.RealTimeGetHandler">
<lst name="defaults">
<str name="omitHeader">true</str>
</lst>
</requestHandler>
</config>

View File

@ -0,0 +1,25 @@
<?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.
-->
<schema name="minimal" version="1.1">
<types>
<fieldType name="string" class="solr.StrField"/>
</types>
<fields>
<dynamicField name="*" type="string" indexed="true" stored="true" />
</fields>
</schema>

View File

@ -0,0 +1,59 @@
<?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.
-->
<!-- This is a "kitchen sink" config file that tests can use.
When writting a new test, feel free to add *new* items (plugins,
config options, etc...) as long as they don't break any existing
tests. if you need to test something esoteric please add a new
"solrconfig-your-esoteric-purpose.xml" config file.
Note in particular that this test is used by MinimalSchemaTest so
Anything added to this file needs to work correctly even if there
is now uniqueKey or defaultSearch Field.
-->
<config>
<dataDir>${solr.data.dir:}</dataDir>
<directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<updateHandler class="solr.DirectUpdateHandler2">
<commitWithin>
<softCommit>${solr.commitwithin.softcommit:true}</softCommit>
</commitWithin>
</updateHandler>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
</config>

View File

@ -0,0 +1,25 @@
<?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.
-->
<schema name="minimal" version="1.1">
<types>
<fieldType name="string" class="solr.StrField"/>
</types>
<fields>
<dynamicField name="*" type="string" indexed="true" stored="true" />
</fields>
</schema>

View File

@ -0,0 +1,52 @@
<?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.
-->
<!--
Small solrconfig with no /get handler defined, for use in TestConfigSets#testConfigSetOnReload
-->
<config>
<dataDir>${solr.data.dir:}</dataDir>
<directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<updateHandler class="solr.DirectUpdateHandler2">
<commitWithin>
<softCommit>${solr.commitwithin.softcommit:true}</softCommit>
</commitWithin>
</updateHandler>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
</config>

View File

@ -287,9 +287,10 @@ public class CoreContainerCoreInitFailuresTest extends SolrTestCaseJ4 {
cc.reload("col_bad");
fail("corrupt solrconfig.xml failed to trigger exception from reload");
} catch (SolrException e) {
Throwable rootException = getWrappedException(e);
assertTrue("We're supposed to have a wrapped SAXParserException here, but we don't",
e.getCause().getCause() instanceof SAXParseException);
SAXParseException se = (SAXParseException)e.getCause().getCause();
rootException instanceof SAXParseException);
SAXParseException se = (SAXParseException) rootException;
assertTrue("reload exception doesn't refer to slrconfig.xml " + se.getSystemId(),
0 < se.getSystemId().indexOf("solrconfig.xml"));
@ -310,12 +311,12 @@ public class CoreContainerCoreInitFailuresTest extends SolrTestCaseJ4 {
failures = cc.getCoreInitFailures();
assertNotNull("core failures is a null map", failures);
assertEquals("wrong number of core failures", 1, failures.size());
fail = failures.get("col_bad");
assertNotNull("null failure for test core", fail);
Throwable ex = getWrappedException(failures.get("col_bad"));
assertNotNull("null failure for test core", ex);
assertTrue("init failure isn't SAXParseException",
fail.getCause() instanceof SAXParseException);
assertTrue("init failure doesn't mention problem: " + fail.toString(),
0 < ((SAXParseException)fail.getCause()).getSystemId().indexOf("solrconfig.xml"));
ex instanceof SAXParseException);
SAXParseException saxEx = (SAXParseException) ex;
assertTrue("init failure doesn't mention problem: " + saxEx.toString(), saxEx.getSystemId().contains("solrconfig.xml"));
// ----
// fix col_bad's config (again) and RELOAD to fix failure

View File

@ -0,0 +1,130 @@
package org.apache.solr.core;
/*
* 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.
*/
import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
import org.apache.commons.io.FileUtils;
import org.apache.solr.SolrTestCaseJ4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import java.io.File;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.internal.matchers.StringContains.containsString;
public class TestConfigSets extends SolrTestCaseJ4 {
@Rule
public TestRule testRule = RuleChain.outerRule(new SystemPropertiesRestoreRule());
public static String solrxml = "<solr><str name=\"configSetBaseDir\">${configsets:configsets}</str></solr>";
public CoreContainer setupContainer(String testName, String configSetsBaseDir) {
File testDirectory = new File(TEMP_DIR, testName);
testDirectory.mkdirs();
System.setProperty("configsets", configSetsBaseDir);
SolrResourceLoader loader = new SolrResourceLoader(testDirectory.getAbsolutePath());
CoreContainer container = new CoreContainer(loader, ConfigSolr.fromString(loader, solrxml));
container.load();
return container;
}
@Test
public void testConfigSetServiceFindsConfigSets() {
CoreContainer container = null;
try {
container = setupContainer("findsConfigSets", getFile("solr/configsets").getAbsolutePath());
String testDirectory = container.getResourceLoader().getInstanceDir();
SolrCore core1 = container.create("core1", testDirectory + "/core1", "configSet", "configset-2");
assertThat(core1.getCoreDescriptor().getName(), is("core1"));
assertThat(core1.getDataDir(), is(testDirectory + "/core1/data/"));
core1.close();
}
finally {
if (container != null)
container.shutdown();
}
}
@Test
public void testNonExistentConfigSetThrowsException() {
CoreContainer container = null;
try {
container = setupContainer("badConfigSet", getFile("solr/configsets").getAbsolutePath());
String testDirectory = container.getResourceLoader().getInstanceDir();
container.create("core1", testDirectory + "/core1", "configSet", "nonexistent");
fail("Expected core creation to fail");
}
catch (Exception e) {
Throwable wrappedException = getWrappedException(e);
assertThat(wrappedException.getMessage(), containsString("nonexistent"));
}
finally {
if (container != null)
container.shutdown();
}
}
@Test
public void testConfigSetOnCoreReload() throws IOException {
File testDirectory = new File(TEMP_DIR, "core-reload");
testDirectory.mkdirs();
File configSetsDir = new File(testDirectory, "configsets");
FileUtils.copyDirectory(getFile("solr/configsets"), configSetsDir);
String csd = configSetsDir.getAbsolutePath();
System.setProperty("configsets", csd);
SolrResourceLoader loader = new SolrResourceLoader(testDirectory.getAbsolutePath());
CoreContainer container = new CoreContainer(loader, ConfigSolr.fromString(loader, solrxml));
container.load();
// We initially don't have a /get handler defined
SolrCore core = container.create("core1", testDirectory + "/core", "configSet", "configset-2");
container.register(core, false);
assertThat("No /get handler should be defined in the initial configuration",
core.getRequestHandler("/get"), is(nullValue()));
// Now copy in a config with a /get handler and reload
FileUtils.copyFile(getFile("solr/collection1/conf/solrconfig-withgethandler.xml"),
new File(new File(configSetsDir, "configset-2/conf"), "solrconfig.xml"));
container.reload("core1");
core = container.getCore("core1");
assertThat("A /get handler should be defined in the reloaded configuration",
core.getRequestHandler("/get"), is(notNullValue()));
core.close();
container.shutdown();
}
}

View File

@ -87,8 +87,6 @@ public class TestCoreContainer extends SolrTestCaseJ4 {
System.setProperty("shareSchema", "true");
final CoreContainer cores = init("_shareSchema");
try {
assertTrue(cores.isShareSchema());
CoreDescriptor descriptor1 = new CoreDescriptor(cores, "core1", "./collection1");
SolrCore core1 = cores.create(descriptor1);

View File

@ -27,11 +27,9 @@ import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.CommitUpdateCommand;
import org.apache.solr.update.UpdateHandler;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.TestHarness;
import org.junit.After;
import org.junit.BeforeClass;
@ -560,10 +558,13 @@ public class TestLazyCores extends SolrTestCaseJ4 {
// See fi the message you expect is in the list of failures
private void testMessage(Map<String, Exception> failures, String lookFor) {
List<String> messages = new ArrayList<>();
for (Exception e : failures.values()) {
if (e.getMessage().indexOf(lookFor) != -1) return;
String message = e.getCause().getMessage();
messages.add(message);
if (message.contains(lookFor)) return;
}
fail("Should have found message containing these tokens " + lookFor + " in the failure messages");
fail("Should have found message containing these tokens " + lookFor + " in the failure messages: " + messages);
}
// Just localizes writing a configuration rather than repeating it for good and bad files.

View File

@ -53,6 +53,7 @@ public class CoreAdminRequest extends SolrRequest
protected String schemaName = null;
protected String dataDir = null;
protected String ulogDir = null;
protected String configSet = null;
protected String collection;
private Integer numShards;
private String shardId;
@ -71,6 +72,9 @@ public class CoreAdminRequest extends SolrRequest
public void setConfigName(String config) { this.configName = config; }
public void setDataDir(String dataDir) { this.dataDir = dataDir; }
public void setUlogDir(String ulogDir) { this.ulogDir = ulogDir; }
public void setConfigSet(String configSet) {
this.configSet = configSet;
}
public void setCollection(String collection) { this.collection = collection; }
public void setNumShards(int numShards) {this.numShards = numShards;}
public void setShardId(String shardId) {this.shardId = shardId;}
@ -85,6 +89,9 @@ public class CoreAdminRequest extends SolrRequest
public String getConfigName() { return configName; }
public String getDataDir() { return dataDir; }
public String getUlogDir() { return ulogDir; }
public String getConfigSet() {
return configSet;
}
public String getCollection() { return collection; }
public String getShardId() { return shardId; }
public String getRoles() { return roles; }
@ -118,6 +125,9 @@ public class CoreAdminRequest extends SolrRequest
if (ulogDir != null) {
params.set( CoreAdminParams.ULOG_DIR, ulogDir);
}
if (configSet != null) {
params.set( CoreAdminParams.CONFIGSET, configSet);
}
if (collection != null) {
params.set( CoreAdminParams.COLLECTION, collection);
}

View File

@ -17,6 +17,21 @@ package org.apache.solr.common.cloud;
* limitations under the License.
*/
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.ByteUtils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.data.Stat;
import org.noggit.CharArr;
import org.noggit.JSONParser;
import org.noggit.JSONWriter;
import org.noggit.ObjectBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@ -34,21 +49,6 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.noggit.CharArr;
import org.noggit.JSONParser;
import org.noggit.JSONWriter;
import org.noggit.ObjectBuilder;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.ByteUtils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ZkStateReader {
private static Logger log = LoggerFactory.getLogger(ZkStateReader.class);
@ -134,8 +134,7 @@ public class ZkStateReader {
*
* @param collection to return config set name for
*/
public String readConfigName(String collection) throws KeeperException,
InterruptedException {
public String readConfigName(String collection) {
String configName = null;
@ -143,6 +142,8 @@ public class ZkStateReader {
if (log.isInfoEnabled()) {
log.info("Load collection config from:" + path);
}
try {
byte[] data = zkClient.getData(path, null, null, true);
if(data != null) {
@ -159,6 +160,15 @@ public class ZkStateReader {
log.info("path={} {}={} specified config exists in ZooKeeper",
new Object[] {path, CONFIGNAME_PROP, configName});
}
}
}
catch (KeeperException e) {
throw new SolrException(ErrorCode.SERVER_ERROR, "Error loading config name for collection " + collection, e);
}
catch (InterruptedException e) {
Thread.interrupted();
throw new SolrException(ErrorCode.SERVER_ERROR, "Error loading config name for collection " + collection, e);
}
return configName;

View File

@ -37,9 +37,10 @@ public abstract class CoreAdminParams
/** If you rename something, what is the new name **/
public final static String NAME = "name";
/** If you rename something, what is the new name **/
/** Core data directory **/
public final static String DATA_DIR = "dataDir";
/** Core updatelog directory **/
public final static String ULOG_DIR = "ulogDir";
/** Name of the other core in actions involving 2 cores **/
@ -51,6 +52,9 @@ public abstract class CoreAdminParams
/** If you specify a schema, what is its name **/
public final static String SCHEMA = "schema";
/** If you specify a configset, what is its name **/
public final static String CONFIGSET = "configSet";
/** If you specify a config, what is its name **/
public final static String CONFIG = "config";

View File

@ -0,0 +1,25 @@
<?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.
-->
<schema name="minimal" version="1.1">
<types>
<fieldType name="string" class="solr.StrField"/>
</types>
<fields>
<dynamicField name="*" type="string" indexed="true" stored="true" />
</fields>
</schema>

View File

@ -0,0 +1,59 @@
<?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.
-->
<!-- This is a "kitchen sink" config file that tests can use.
When writting a new test, feel free to add *new* items (plugins,
config options, etc...) as long as they don't break any existing
tests. if you need to test something esoteric please add a new
"solrconfig-your-esoteric-purpose.xml" config file.
Note in particular that this test is used by MinimalSchemaTest so
Anything added to this file needs to work correctly even if there
is now uniqueKey or defaultSearch Field.
-->
<config>
<dataDir>${solr.data.dir:}</dataDir>
<directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<updateHandler class="solr.DirectUpdateHandler2">
<commitWithin>
<softCommit>${solr.commitwithin.softcommit:true}</softCommit>
</commitWithin>
</updateHandler>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
</config>

View File

@ -0,0 +1,25 @@
<?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.
-->
<schema name="minimal" version="1.1">
<types>
<fieldType name="string" class="solr.StrField"/>
</types>
<fields>
<dynamicField name="*" type="string" indexed="true" stored="true" />
</fields>
</schema>

View File

@ -0,0 +1,52 @@
<?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.
-->
<!--
Small solrconfig with no /get handler defined, for use in TestConfigSets#testConfigSetOnReload
-->
<config>
<dataDir>${solr.data.dir:}</dataDir>
<directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<updateHandler class="solr.DirectUpdateHandler2">
<commitWithin>
<softCommit>${solr.commitwithin.softcommit:true}</softCommit>
</commitWithin>
</updateHandler>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
</config>

View File

@ -30,7 +30,7 @@
adminPath: RequestHandler path to manage cores.
If 'null' (or absent), cores will not be manageable via REST
-->
<cores adminPath="/admin/cores" defaultCoreName="core0" host="127.0.0.1" hostPort="${hostPort:8983}" hostContext="${hostContext:solr}" zkClientTimeout="8000" genericCoreNodeNames="${genericCoreNodeNames:true}">
<cores adminPath="/admin/cores" defaultCoreName="core0" host="127.0.0.1" hostPort="${hostPort:8983}" hostContext="${hostContext:solr}" zkClientTimeout="8000" genericCoreNodeNames="${genericCoreNodeNames:true}" configSetBaseDir="${configSetBase:configsets}">
<core name="collection1" instanceDir="." />
<core name="core0" instanceDir="${theInstanceDir:./}" dataDir="${dataDir1}" collection="${collection:acollection}">
<property name="version" value="3.5"/>

View File

@ -51,6 +51,7 @@ public abstract class AbstractEmbeddedSolrServerTestCase extends LuceneTestCase
super.setUp();
System.setProperty("solr.solr.home", SOLR_HOME.getAbsolutePath());
System.setProperty("configSetBase", SolrTestCaseJ4.getFile("solrj/solr/configsets").getAbsolutePath());
System.out.println("Solr home: " + SOLR_HOME.getAbsolutePath());
//The index is always stored within a temporary directory

View File

@ -18,23 +18,31 @@
package org.apache.solr.client.solrj.request;
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
import org.apache.commons.io.FileUtils;
import org.apache.solr.SolrIgnoredThreadsFilter;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.embedded.AbstractEmbeddedSolrServerTestCase;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.response.CoreAdminResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.Is.is;
@ThreadLeakFilters(defaultFilters = true, filters = {SolrIgnoredThreadsFilter.class})
public class TestCoreAdmin extends AbstractEmbeddedSolrServerTestCase {
protected static Logger log = LoggerFactory.getLogger(TestCoreAdmin.class);
@ -43,6 +51,9 @@ public class TestCoreAdmin extends AbstractEmbeddedSolrServerTestCase {
private static String tempDirProp;
@Rule
public TestRule testRule = RuleChain.outerRule(new SystemPropertiesRestoreRule());
@Override
protected File getSolrXml() throws Exception {
// This test writes on the directory where the solr.xml is located. Better
@ -58,14 +69,46 @@ public class TestCoreAdmin extends AbstractEmbeddedSolrServerTestCase {
return new EmbeddedSolrServer(cores, "core0");
}
@Test
public void testConfigSet() throws Exception {
SolrServer server = getSolrAdmin();
File testDir = createTestDirectory();
File newCoreInstanceDir = new File(testDir, "newcore");
CoreAdminRequest.Create req = new CoreAdminRequest.Create();
req.setCoreName("corewithconfigset");
req.setInstanceDir(newCoreInstanceDir.getAbsolutePath());
req.setConfigSet("configset-2");
CoreAdminResponse response = req.process(server);
assertThat((String) response.getResponse().get("core"), is("corewithconfigset"));
SolrCore core = null;
try {
core = cores.getCore("corewithconfigset");
assertThat(core, is(notNullValue()));
}
finally {
if (core != null)
core.close();
}
}
private File createTestDirectory() {
File tmp = new File(TEMP_DIR, "solrtest-" + getTestClass().getSimpleName() + "-" + System.currentTimeMillis());
assertTrue("Couldn't create temporary directory " + tmp.getAbsolutePath(), tmp.mkdirs());
return tmp;
}
@Test
public void testCustomUlogDir() throws Exception {
SolrServer server = getSolrAdmin();
File tmp = new File(TEMP_DIR, "solrtest-" + getTestClass().getSimpleName() + "-" + System.currentTimeMillis());
tmp.mkdirs();
File tmp = createTestDirectory();
log.info("Creating cores underneath {}", tmp);

View File

@ -301,6 +301,13 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
System.setProperty("solr.tests.maxIndexingThreads", String.valueOf(maxIndexingThreads));
}
public static Throwable getWrappedException(Throwable e) {
while (e != null && e.getCause() != e && e.getCause() != null) {
e = e.getCause();
}
return e;
}
@Override
public void setUp() throws Exception {
super.setUp();