Keep User's Change when Update solr.xml


Problem
In our product, user is able to create additional core: Solr will update solr.xml to add extra core information. But at some time, we need update solr.xml to add our extra cores. 
This is a common requirement: we need upgrade solr config files in future release, but at same time keep customer's change.

For solrconfig.xml or solrschema.xml, we can use xi:include to put our change in one xml(for example solrconfig-upgrade.xml), user should only change solrconfig.xml either manually or via GUI.
Please refer to http://wiki.apache.org/solr/SolrConfigXml#XInclude

But this doesn't work for solr.xml, as if we define xi:include in solr.xml:
<solr persistent="true" sharedLib="lib" shareSchema="true">
 <cores adminPath="/admin/cores" defaultCoreName="collection1" 
host="${host:}" hostPort="${jetty.port:}" hostContext="${hostContext:}" zkClientTimeout="${zkClientTimeout:15000}">
<core name="collection1" instanceDir="collection1"/>
  <!-- this doesn't work -->
   <xi:include href="solr_extracores.xml"/>
 </cores>
</solr>

later if user creates another solr core, solr will update solr.xml: it will delete <xi:include> and overwrite cores section to include all cores.
Solution
We can define extra cores in a property file: cvanalytics_solr_extra.propertie like below:
# support corename_name, corename_instanceDir, corename_schemaName, corename_configName
extra_cores=extracore1, extracore2
extracore1_name=extracore1
extracore1_instanceDir=extracore1
extracore1_schemaName=extracore1_schema.xml
extracore1_configName=extracore1_config.xml
....
We will iterate all core names in extra_cores, if it's already loaded: CoreContainer.getCoreFromAnyList(core_name) returns not null, we ignore, Otherwise, we create a SolrCore and register it.
Implementation Code
org.apache.solr.core.CoreContainer.Initializer
private void initExtraCores(CoreContainer cores) throws RuntimeException {
  try {
 Properties cvProps = cores.getCVProperties();
 String solrxml_extra = cvProps.getProperty("solrxml_extra");
 if (!StringUtils.isBlank(solrxml_extra)) {
   File solrxml_extraFile = new File(cores.getSolrHome(), solrxml_extra);
   Properties solrxml_extraProps = readProperties(solrxml_extraFile);
   
   String extra_cores = solrxml_extraProps.getProperty("extra_cores");
   if (!StringUtils.isBlank(extra_cores)) {
  String[] extra_coresArr = extra_cores.split(",");
  for (String extra_core : extra_coresArr) {
    extra_core = extra_core.trim();
    if (cores.getCoreFromAnyList(extra_core) == null) {
   String coreName = solrxml_extraProps.getProperty(extra_core
    + "_name");
   if (StringUtils.isBlank(coreName)) {
     coreName = extra_core;
   }
   String instanceDir = solrxml_extraProps.getProperty(extra_core
    + "_instanceDir");
   if (StringUtils.isBlank(instanceDir)) {
     throw new RuntimeException("No instanceDir defined for "
      + coreName + "in " + solrxml_extraFile);
   }
   CoreDescriptor cd = new CoreDescriptor(cores, coreName,
    instanceDir);
   String schemaName = solrxml_extraProps.getProperty(extra_core
    + "_schemaName");
   if (!StringUtils.isBlank(schemaName)) {
     cd.setSchemaName(schemaName);
   }
   String configName = solrxml_extraProps.getProperty(extra_core
    + "_configName");
   if (!StringUtils.isBlank(configName)) {
     cd.setConfigName(configName);
   }
   SolrCore core = cores.create(cd);
   cores.register(core, false);
    }
  }
   }
 }
  } catch (Exception e) {
 throw new RuntimeException(e);
  }
}
public CoreContainer initialize() {
  CoreContainer cores = null;
  String solrHome = SolrResourceLoader.locateSolrHome();
  cores = new CoreContainer(solrHome);
  
  if (fconf.exists()) {
 cores.load(solrHome, fconf);
  } else {
 log.info("no solr.xml file found - using default");
 try {
   cores.load(solrHome, new InputSource(new ByteArrayInputStream(DEF_SOLR_XML.getBytes("UTF-8"))));
 } catch (Exception e) {
   throw new SolrException(ErrorCode.SERVER_ERROR,
    "CoreContainer.Initialize failed when trying to load default solr.xml file", e);
 }
 cores.configFile = fconf;
  }
  // call initExtraCores
  initExtraCores(cores);
  return cores;
}

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)