You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ro...@apache.org on 2014/03/24 11:54:52 UTC

svn commit: r1580814 [1/2] - in /lucene/dev/trunk/solr: ./ core/src/java/org/apache/solr/cloud/ core/src/java/org/apache/solr/core/ core/src/java/org/apache/solr/handler/admin/ core/src/java/org/apache/solr/servlet/ core/src/test-files/solr/collection1...

Author: romseygeek
Date: Mon Mar 24 10:54:51 2014
New Revision: 1580814

URL: http://svn.apache.org/r1580814
Log:
SOLR-4478: Allow cores to use configurations specified outside their instance directory

Added:
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudConfigSetService.java   (with props)
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSet.java   (with props)
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSetService.java   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-withgethandler.xml   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/schema.xml   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/solrconfig.xml   (with props)
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigSets.java   (with props)
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-1/
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-1/conf/
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-1/conf/schema-minimal.xml   (with props)
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-1/conf/solrconfig-minimal.xml   (with props)
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-2/
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-2/conf/
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-2/conf/schema.xml   (with props)
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/configsets/configset-2/conf/solrconfig.xml   (with props)
Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolr.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ZkContainer.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/CoreContainerCoreInitFailuresTest.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/params/CoreAdminParams.java
    lucene/dev/trunk/solr/solrj/src/test-files/solrj/solr/shared/solr.xml
    lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/AbstractEmbeddedSolrServerTestCase.java
    lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestCoreAdmin.java
    lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Mon Mar 24 10:54:51 2014
@@ -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
 ----------------------
 

Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudConfigSetService.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudConfigSetService.java?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudConfigSetService.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudConfigSetService.java Mon Mar 24 10:54:51 2014
@@ -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();
+  }
+}

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/ZkController.java Mon Mar 24 10:54:51 2014
@@ -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);
     }
     
   }

Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSet.java?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSet.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSet.java Mon Mar 24 10:54:51 2014
@@ -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;
+  }
+}

Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSetService.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSetService.java?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSetService.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSetService.java Mon Mar 24 10:54:51 2014
@@ -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);
+    }
+  }
+
+}

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolr.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolr.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolr.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolr.java Mon Mar 24 10:54:51 2014
@@ -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,

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java Mon Mar 24 10:54:51 2014
@@ -122,6 +122,7 @@ public class ConfigSolrXml extends Confi
     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']"));

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java Mon Mar 24 10:54:51 2014
@@ -168,6 +168,7 @@ public class ConfigSolrXmlOld extends Co
         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

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java Mon Mar 24 10:54:51 2014
@@ -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,9 +74,8 @@ 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,20 +201,15 @@ public class CoreContainer {
       loader.reloadLuceneSPI();
     }
 
+
     shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
-    
+
     updateShardHandler = new UpdateShardHandler(cfg);
 
     solrCores.allocateLazyCores(cfg.getTransientCacheSize(), loader);
 
     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);
-    }
-
-    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);
+  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]);
     }
-
-    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));
   }
 
   /**
@@ -602,32 +548,26 @@ public class CoreContainer {
     if (isShutDown) {
       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);
@@ -988,10 +896,6 @@ public class CoreContainer {
   public ZkController getZkController() {
     return zkSys.getZkController();
   }
-  
-  public boolean isShareSchema() {
-    return shareSchema;
-  }
 
   /** The default ShardHandlerFactory used to communicate with other solr instances */
   public ShardHandlerFactory getShardHandlerFactory() {
@@ -1015,6 +919,10 @@ public class CoreContainer {
   String getCoreToOrigName(SolrCore core) {
     return solrCores.getCoreToOrigName(core);
   }
+
+  public SolrResourceLoader getResourceLoader() {
+    return loader;
+  }
 }
 
 class CloserThread extends Thread {

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java Mon Mar 24 10:54:51 2014
@@ -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);
+  }
 }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java Mon Mar 24 10:54:51 2014
@@ -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;
 
 
 /**
@@ -128,6 +138,16 @@ public class SolrConfig extends Config {
   throws ParserConfigurationException, IOException, SAXException {
     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.
@@ -146,7 +166,7 @@ public class SolrConfig extends Config {
     // Old indexDefaults and mainIndex sections are deprecated and fails fast for luceneMatchVersion=>LUCENE_40.
     // For older solrconfig.xml's we allow the old sections, but never mixed with the new <indexConfig>
     boolean hasDeprecatedIndexConfig = (getNode("indexDefaults", false) != null) || (getNode("mainIndex", false) != null);
-    boolean hasNewIndexConfig = getNode("indexConfig", false) != null; 
+    boolean hasNewIndexConfig = getNode("indexConfig", false) != null;
     if(hasDeprecatedIndexConfig){
       if(luceneMatchVersion.onOrAfter(Version.LUCENE_40)) {
         throw new SolrException(ErrorCode.FORBIDDEN, "<indexDefaults> and <mainIndex> configuration sections are discontinued. Use <indexConfig> instead.");
@@ -167,12 +187,12 @@ public class SolrConfig extends Config {
     nrtMode = getBool(indexConfigPrefix+"/nrtMode", true);
     // Parse indexConfig section, using mainIndex as backup in case old config is used
     indexConfig = new SolrIndexConfig(this, "indexConfig", mainIndexConfig);
-   
+
     booleanQueryMaxClauseCount = getInt("query/maxBooleanClauses", BooleanQuery.getMaxClauseCount());
     log.info("Using Lucene MatchVersion: " + luceneMatchVersion);
 
     // Warn about deprecated / discontinued parameters
-    // boolToFilterOptimizer has had no effect since 3.1 
+    // boolToFilterOptimizer has had no effect since 3.1
     if(get("query/boolTofilterOptimizer", null) != null)
       log.warn("solrconfig.xml: <boolTofilterOptimizer> is currently not implemented and has no effect.");
     if(get("query/HashDocSet", null) != null)
@@ -182,13 +202,13 @@ public class SolrConfig extends Config {
 //    filtOptEnabled = getBool("query/boolTofilterOptimizer/@enabled", false);
 //    filtOptCacheSize = getInt("query/boolTofilterOptimizer/@cacheSize",32);
 //    filtOptThreshold = getFloat("query/boolTofilterOptimizer/@threshold",.05f);
-    
+
     useFilterForSortedQuery = getBool("query/useFilterForSortedQuery", false);
     queryResultWindowSize = Math.max(1, getInt("query/queryResultWindowSize", 1));
     queryResultMaxDocsCached = getInt("query/queryResultMaxDocsCached", Integer.MAX_VALUE);
     enableLazyFieldLoading = getBool("query/enableLazyFieldLoading", false);
 
-    
+
     filterCacheConfig = CacheConfig.getConfig(this, "query/filterCache");
     queryResultCacheConfig = CacheConfig.getConfig(this, "query/queryResultCache");
     documentCacheConfig = CacheConfig.getConfig(this, "query/documentCache");
@@ -215,14 +235,14 @@ public class SolrConfig extends Config {
     hashDocSetMaxSize= getInt("//HashDocSet/@maxSize",3000);
 
     httpCachingConfig = new HttpCachingConfig(this);
-    
+
     Node jmx = getNode("jmx", false);
     if (jmx != null) {
-      jmxConfig = new JmxConfiguration(true, 
-                                       get("jmx/@agentId", null), 
+      jmxConfig = new JmxConfiguration(true,
+                                       get("jmx/@agentId", null),
                                        get("jmx/@serviceUrl", null),
                                        get("jmx/@rootName", null));
-                                           
+
     } else {
       jmxConfig = new JmxConfiguration(false, null, null, null);
     }
@@ -249,24 +269,24 @@ public class SolrConfig extends Config {
                     REQUIRE_NAME, REQUIRE_CLASS);
 
      // this is hackish, since it picks up all SolrEventListeners,
-     // regardless of when/how/why they are used (or even if they are 
-     // declared outside of the appropriate context) but there's no nice 
+     // regardless of when/how/why they are used (or even if they are
+     // declared outside of the appropriate context) but there's no nice
      // way around that in the PluginInfo framework
-     loadPluginInfo(SolrEventListener.class, "//listener", 
+     loadPluginInfo(SolrEventListener.class, "//listener",
                     REQUIRE_CLASS, MULTI_OK);
 
-     loadPluginInfo(DirectoryFactory.class,"directoryFactory", 
+     loadPluginInfo(DirectoryFactory.class,"directoryFactory",
                     REQUIRE_CLASS);
-     loadPluginInfo(IndexDeletionPolicy.class,indexConfigPrefix+"/deletionPolicy", 
+     loadPluginInfo(IndexDeletionPolicy.class,indexConfigPrefix+"/deletionPolicy",
                     REQUIRE_CLASS);
-     loadPluginInfo(CodecFactory.class,"codecFactory", 
+     loadPluginInfo(CodecFactory.class,"codecFactory",
                     REQUIRE_CLASS);
-     loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory", 
+     loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory",
                     REQUIRE_CLASS);
-     loadPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain", 
+     loadPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain",
                     MULTI_OK);
      loadPluginInfo(UpdateLog.class,"updateHandler/updateLog");
-     loadPluginInfo(IndexSchemaFactory.class,"schemaFactory", 
+     loadPluginInfo(IndexSchemaFactory.class,"schemaFactory",
                     REQUIRE_CLASS);
      loadPluginInfo(RestManager.class, "restManager");
      updateHandlerInfo = loadUpdatehandlerInfo();

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java Mon Mar 24 10:54:51 2014
@@ -17,42 +17,6 @@
 
 package org.apache.solr.core;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Writer;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.nio.file.NoSuchFileException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-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;
@@ -67,8 +31,8 @@ import org.apache.solr.cloud.CloudDescri
 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.CommonParams.EchoParamStyle;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.ExecutorUtil;
 import org.apache.solr.common.util.NamedList;
@@ -101,8 +65,8 @@ import org.apache.solr.response.SchemaXm
 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.ManagedResourceStorage.StorageIO;
 import org.apache.solr.rest.RestManager;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
@@ -114,8 +78,8 @@ import org.apache.solr.search.SolrIndexS
 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.SolrCoreState.IndexWriterCloser;
 import org.apache.solr.update.SolrIndexWriter;
 import org.apache.solr.update.UpdateHandler;
 import org.apache.solr.update.VersionInfo;
@@ -134,6 +98,41 @@ 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;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.nio.file.NoSuchFileException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  *
@@ -411,19 +410,10 @@ public final class SolrCore implements S
   public QueryResponseWriter registerResponseWriter( String name, QueryResponseWriter responseWriter ){
     return responseWriters.put(name, responseWriter);
   }
-  
-  public SolrCore reload(SolrCore prev) throws IOException,
-      ParserConfigurationException, SAXException {
-    return reload(prev.getResourceLoader(), prev);
-  }
-  
-  public SolrCore reload(SolrResourceLoader resourceLoader, SolrCore prev) throws IOException,
+
+  public SolrCore reload(ConfigSet coreConfig, SolrCore prev) throws IOException,
       ParserConfigurationException, SAXException {
     
-    SolrConfig config = new SolrConfig(resourceLoader, getSolrConfig().getName(), null);
-    
-    IndexSchema schema = IndexSchemaFactory.buildIndexSchema(getLatestSchema().getResourceName(), config);
-    
     solrCoreState.increfSolrCoreState();
     
     if (!getNewIndexDir().equals(getIndexDir())) {
@@ -431,8 +421,8 @@ public final class SolrCore implements S
       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 S
     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

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ZkContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ZkContainer.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ZkContainer.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ZkContainer.java Mon Mar 24 10:54:51 2014
@@ -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);
       }
     }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java Mon Mar 24 10:54:51 2014
@@ -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 Re
       .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)

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java Mon Mar 24 10:54:51 2014
@@ -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;

Added: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-withgethandler.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-withgethandler.xml?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-withgethandler.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-withgethandler.xml Mon Mar 24 10:54:51 2014
@@ -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>
+

Added: lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/schema-minimal.xml Mon Mar 24 10:54:51 2014
@@ -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>

Added: lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-1/conf/solrconfig-minimal.xml Mon Mar 24 10:54:51 2014
@@ -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>
+

Added: lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/schema.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/schema.xml?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/schema.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/schema.xml Mon Mar 24 10:54:51 2014
@@ -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>

Added: lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/solrconfig.xml?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/solrconfig.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/configsets/configset-2/conf/solrconfig.xml Mon Mar 24 10:54:51 2014
@@ -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>
+

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/CoreContainerCoreInitFailuresTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/CoreContainerCoreInitFailuresTest.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/CoreContainerCoreInitFailuresTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/CoreContainerCoreInitFailuresTest.java Mon Mar 24 10:54:51 2014
@@ -287,9 +287,10 @@ public class CoreContainerCoreInitFailur
       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 CoreContainerCoreInitFailur
     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
@@ -351,7 +352,7 @@ public class CoreContainerCoreInitFailur
       tmp.close();
     }
   }
-  
+
   private static final String EMPTY_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
       "<solr persistent=\"false\">\n" +
       "  <cores adminPath=\"/admin/cores\">\n" +

Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigSets.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigSets.java?rev=1580814&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigSets.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigSets.java Mon Mar 24 10:54:51 2014
@@ -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();
+  }
+
+}

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestCoreContainer.java Mon Mar 24 10:54:51 2014
@@ -87,8 +87,6 @@ public class TestCoreContainer extends S
     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);
       

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestLazyCores.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestLazyCores.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestLazyCores.java Mon Mar 24 10:54:51 2014
@@ -27,11 +27,9 @@ import org.apache.solr.handler.admin.Cor
 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 SolrT
 
   // 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.

Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java Mon Mar 24 10:54:51 2014
@@ -53,6 +53,7 @@ public class CoreAdminRequest extends So
     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 So
     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 So
     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 So
       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);
       }

Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java Mon Mar 24 10:54:51 2014
@@ -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.ThreadFactor
 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,22 +142,33 @@ public class ZkStateReader {
     if (log.isInfoEnabled()) {
       log.info("Load collection config from:" + path);
     }
-    byte[] data = zkClient.getData(path, null, null, true);
 
-    if(data != null) {
-      ZkNodeProps props = ZkNodeProps.load(data);
-      configName = props.getStr(CONFIGNAME_PROP);
-    }
+    try {
+      byte[] data = zkClient.getData(path, null, null, true);
 
-    if (configName != null) {
-      if (!zkClient.exists(CONFIGS_ZKNODE + "/" + configName, true)) {
-        log.error("Specified config does not exist in ZooKeeper:" + configName);
-        throw new ZooKeeperException(ErrorCode.SERVER_ERROR,
-            "Specified config does not exist in ZooKeeper:" + configName);
-      } else if (log.isInfoEnabled()) {
-        log.info("path={} {}={} specified config exists in ZooKeeper",
-            new Object[] {path, CONFIGNAME_PROP, configName});
+      if(data != null) {
+        ZkNodeProps props = ZkNodeProps.load(data);
+        configName = props.getStr(CONFIGNAME_PROP);
       }
+
+      if (configName != null) {
+        if (!zkClient.exists(CONFIGS_ZKNODE + "/" + configName, true)) {
+          log.error("Specified config does not exist in ZooKeeper:" + configName);
+          throw new ZooKeeperException(ErrorCode.SERVER_ERROR,
+              "Specified config does not exist in ZooKeeper:" + configName);
+        } else if (log.isInfoEnabled()) {
+          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;

Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/params/CoreAdminParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/params/CoreAdminParams.java?rev=1580814&r1=1580813&r2=1580814&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/params/CoreAdminParams.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/params/CoreAdminParams.java Mon Mar 24 10:54:51 2014
@@ -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 **/
@@ -50,6 +51,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";