You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by no...@apache.org on 2021/04/16 02:03:34 UTC
[solr] branch jira/solr15337 updated: untested
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch jira/solr15337
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/jira/solr15337 by this push:
new dea2494 untested
dea2494 is described below
commit dea2494200e9bc294c3cc559bbdce8771d5c17e8
Author: Noble Paul <no...@gmail.com>
AuthorDate: Fri Apr 16 11:58:23 2021 +1000
untested
---
.../java/org/apache/solr/core/ConfigOverlay.java | 1 +
.../src/java/org/apache/solr/core/SolrConfig.java | 155 ++++++++++++---------
.../org/apache/solr/schema/IndexSchemaFactory.java | 4 +-
.../java/org/apache/solr/search/CacheConfig.java | 2 +-
.../org/apache/solr/update/SolrIndexConfig.java | 79 +++++------
.../java/org/apache/solr/update/VersionInfo.java | 4 +-
.../java/org/apache/solr/util/DataConfigNode.java | 4 +-
.../src/test/org/apache/solr/core/TestConfig.java | 9 +-
.../java/org/apache/solr/common/ConfigNode.java | 53 +++++--
9 files changed, 175 insertions(+), 136 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java b/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
index 069de5d..e1a44d5 100644
--- a/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
+++ b/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
@@ -191,6 +191,7 @@ public class ConfigOverlay implements MapSerializable {
return isEditable(isXpath, hierarchy, StrUtils.splitSmart(path, isXpath ? '/' : '.'));
}
+ @SuppressWarnings("rawtypes")
private static Class isEditable(boolean isXpath, List<String> hierarchy, List<String> parts) {
Object obj = editable_prop_map;
for (int i = 0; i < parts.size(); i++) {
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index 65f5043..58a2515 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -38,7 +38,9 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -55,7 +57,6 @@ import org.apache.solr.common.MapSerializable;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.IOUtils;
-import org.apache.solr.common.util.StrUtils;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.pkg.PackageLoader;
@@ -82,7 +83,6 @@ import org.apache.solr.util.DataConfigNode;
import org.apache.solr.util.circuitbreaker.CircuitBreakerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import static org.apache.solr.common.params.CommonParams.NAME;
@@ -109,9 +109,13 @@ public class SolrConfig implements MapSerializable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String DEFAULT_CONF_FILE = "solrconfig.xml";
+ private final String resourceName;
- private XmlConfigFile xml;
+// private XmlConfigFile xml;
+ private int znodeVersion;
ConfigNode root;
+ private final SolrResourceLoader resourceLoader;
+ private Properties substituteProperties;
private RequestParams requestParams;
@@ -174,11 +178,41 @@ public class SolrConfig implements MapSerializable {
*/
private SolrConfig(SolrResourceLoader loader, String name, boolean isConfigsetTrusted, Properties substitutableProperties)
throws ParserConfigurationException, IOException, SAXException {
+ this.resourceLoader = loader;
+ this.resourceName = name;
+ this.substituteProperties = substitutableProperties;
+ getOverlay();//just in case it is not initialized
// insist we have non-null substituteProperties; it might get overlayed
- xml = new XmlConfigFile(loader, name, null, "/config/", substitutableProperties == null ? new Properties() : substitutableProperties );
- root = new DataConfigNode(new DOMConfigNode(xml.getDocument().getDocumentElement()));
+ if(loader.getCoreContainer().getZkController() != null ){
+ @SuppressWarnings("unchecked")
+ Map<String, IndexSchemaFactory.VersionedConfig> configCache = (Map<String, IndexSchemaFactory.VersionedConfig>) loader.getCoreContainer().getZkController().getSolrCloudManager().getObjectCache()
+ .computeIfAbsent(IndexSchemaFactory.ConfigResource.class.getName(), s -> new ConcurrentHashMap<>());
+ if(overlay.getZnodeVersion() == -1) {
+ //currently not optimized for this
+ IndexSchemaFactory.VersionedConfig cfg = configCache.get(name);
+ if(cfg != null){
+ InputStream in = loader.openResource(name);
+ if (in instanceof ZkSolrResourceLoader.ZkByteArrayInputStream) {
+ int zkVersion = ((ZkSolrResourceLoader.ZkByteArrayInputStream) in).getStat().getVersion();
+ if(cfg.version == zkVersion) {
+ root = cfg.data;
+ } else {
+ configCache.remove(name);
+ readXml(loader, name);
+ configCache.put(name, new IndexSchemaFactory.VersionedConfig(this.znodeVersion, root));
+ }
+ }
+ }
+
+ }
+ }
+ if(root == null) {
+ readXml(loader, name);
+ }
+
+// xml = new XmlConfigFile(loader, name, null, "/config/", substitutableProperties == null ? new Properties() : substitutableProperties );
+// root = new DataConfigNode(new DOMConfigNode(xml.getDocument().getDocumentElement()));
// super(loader, name, null, "/config/", substitutableProperties == null ? new Properties() : substitutableProperties);
- getOverlay();//just in case it is not initialized
getRequestParams();
initLibs(loader, isConfigsetTrusted);
String val = root.child(IndexSchema.LUCENE_MATCH_VERSION_PARAM,
@@ -191,14 +225,14 @@ public class SolrConfig implements MapSerializable {
// Old indexDefaults and mainIndex sections are deprecated and fails fast for luceneMatchVersion=>LUCENE_4_0_0.
// For older solrconfig.xml's we allow the old sections, but never mixed with the new <indexConfig>
- boolean hasDeprecatedIndexConfig = (root.child("indexDefaults") != null) || (root.child("mainIndex") != null);
+ boolean hasDeprecatedIndexConfig = __("indexDefaults").exists() || __("mainIndex").exists();
if (hasDeprecatedIndexConfig) {
throw new SolrException(ErrorCode.FORBIDDEN, "<indexDefaults> and <mainIndex> configuration sections are discontinued. Use <indexConfig> instead.");
} else {
indexConfigPrefix = "indexConfig";
}
assertWarnOrFail("The <nrtMode> config has been discontinued and NRT mode is always used by Solr." +
- " This config will be removed in future versions.", root.__("indexDefaults").child("nrtMode") == null,
+ " This config will be removed in future versions.", !__("indexDefaults").__("nrtMode").exists(),
true
);
assertWarnOrFail("Solr no longer supports forceful unlocking via the 'unlockOnStartup' option. "+
@@ -206,17 +240,14 @@ public class SolrConfig implements MapSerializable {
"it would be dangerous and should not be done. For other lockTypes and/or "+
"directoryFactory options it may also be dangerous and users must resolve "+
"problematic locks manually.",
- null == root.__(indexConfigPrefix).child( "unlockOnStartup"),
+ __(indexConfigPrefix).__( "unlockOnStartup").exists(),
true // 'fail' in trunk
);
// Parse indexConfig section, using mainIndex as backup in case old config is used
- indexConfig = new SolrIndexConfig(this, "indexConfig", null);
+ indexConfig = new SolrIndexConfig (__("indexConfig"), null);
- booleanQueryMaxClauseCount = root
- .__("query")
- .__( "maxBooleanClauses")
- ._int(IndexSearcher.getMaxClauseCount());
+ booleanQueryMaxClauseCount = __("query").__( "maxBooleanClauses")._int(IndexSearcher.getMaxClauseCount());
if (IndexSearcher.getMaxClauseCount() < booleanQueryMaxClauseCount) {
log.warn("solrconfig.xml: <maxBooleanClauses> of {} is greater than global limit of {} {}"
, booleanQueryMaxClauseCount, IndexSearcher.getMaxClauseCount()
@@ -225,9 +256,9 @@ public class SolrConfig implements MapSerializable {
// Warn about deprecated / discontinued parameters
// boolToFilterOptimizer has had no effect since 3.1
- if (__("query").child("boolTofilterOptimizer") != null)
+ if (__("query").__("boolTofilterOptimizer").exists())
log.warn("solrconfig.xml: <boolTofilterOptimizer> is currently not implemented and has no effect.");
- if (__("query").child("HashDocSet") != null)
+ if (__("query").__("HashDocSet").exists())
log.warn("solrconfig.xml: <HashDocSet> is deprecated and no longer used.");
// TODO: Old code - in case somebody wants to re-enable. Also see SolrIndexSearcher#search()
@@ -240,10 +271,10 @@ public class SolrConfig implements MapSerializable {
queryResultMaxDocsCached = __("query").__("queryResultMaxDocsCached")._int(Integer.MAX_VALUE);
enableLazyFieldLoading = __("query").__("enableLazyFieldLoading")._bool(false);
- filterCacheConfig = CacheConfig.getConfig(this, __("query").child("filterCache"), "query/filterCache");
- queryResultCacheConfig = CacheConfig.getConfig(this, __("query").child("queryResultCache"), "query/queryResultCache");
- documentCacheConfig = CacheConfig.getConfig(this, __("query").child("documentCache"), "query/documentCache");
- CacheConfig conf = CacheConfig.getConfig(this, __("query").child("fieldValueCache"), "query/fieldValueCache");
+ filterCacheConfig = CacheConfig.getConfig(this, __("query").__("filterCache"), "query/filterCache");
+ queryResultCacheConfig = CacheConfig.getConfig(this, __("query").__("queryResultCache"), "query/queryResultCache");
+ documentCacheConfig = CacheConfig.getConfig(this, __("query").__("documentCache"), "query/documentCache");
+ CacheConfig conf = CacheConfig.getConfig(this, __("query").__("fieldValueCache"), "query/fieldValueCache");
if (conf == null) {
Map<String, String> args = new HashMap<>();
args.put(NAME, "fieldValueCache");
@@ -254,13 +285,13 @@ public class SolrConfig implements MapSerializable {
}
fieldValueCacheConfig = conf;
useColdSearcher = __("query").__("useColdSearcher")._bool(false);
- dataDir = __("dataDir").textValue();
+ dataDir = __("dataDir").txt();
if (dataDir != null && dataDir.length() == 0) dataDir = null;
org.apache.solr.search.SolrIndexSearcher.initRegenerators(this);
- if (root.child("jmx") != null) {
+ if (__("jmx").exists()) {
log.warn("solrconfig.xml: <jmx> is no longer supported, use solr.xml:/metrics/reporter section instead");
}
@@ -311,6 +342,12 @@ public class SolrConfig implements MapSerializable {
log.debug("Loaded SolrConfig: {}", name);
}
+ private void readXml(SolrResourceLoader loader, String name) throws ParserConfigurationException, IOException, SAXException {
+ XmlConfigFile xml = new XmlConfigFile(loader, name, null, "/config/", null);
+ root = new DataConfigNode(new DOMConfigNode(xml.getDocument().getDocumentElement()));
+ this.znodeVersion = xml.getZnodeVersion();
+ }
+
private static final AtomicBoolean versionWarningAlreadyLogged = new AtomicBoolean(false);
public static final Version parseLuceneVersionString(final String matchVersion) {
@@ -438,12 +475,12 @@ public class SolrConfig implements MapSerializable {
return new UpdateHandlerInfo( __("updateHandler").attr("class"),
__("updateHandler").__("autoCommit").__("maxDocs")._int( -1),
__("updateHandler").__("autoCommit").__("maxTime")._int( -1),
- convertHeapOptionStyleConfigStringToBytes(__("updateHandler").__("autoCommit").__("maxSize").txt("")),
+ convertHeapOptionStyleConfigStringToBytes(__("updateHandler").__("autoCommit").__("maxSize").txt()),
__("updateHandler").__("indexWriter").__("closeWaitsForMerges")._bool(true),
__("updateHandler").__("autoCommit").__("openSearcher")._bool(true),
- __("updateHandler").__("autoSoftCommit").__("autoSoftCommit")._int(-1),
+ __("updateHandler").__("autoSoftCommit").__("maxDocs")._int(-1),
__("updateHandler").__("autoSoftCommit").__("maxTime")._int(-1),
- __("updateHandler").__("commitWithin").__("maxTime")._bool(true));
+ __("updateHandler").__("commitWithin").__("softCommit")._bool(true));
}
/**
@@ -454,7 +491,7 @@ public class SolrConfig implements MapSerializable {
* @return the size, in bytes. -1 if the given config string is empty
*/
protected static long convertHeapOptionStyleConfigStringToBytes(String configStr) {
- if (configStr.isEmpty()) {
+ if (configStr== null || configStr.isEmpty()) {
return -1;
}
long multiplier = 1;
@@ -572,7 +609,7 @@ public class SolrConfig implements MapSerializable {
"cacheControl", cacheControlHeader);
}
- public static enum LastModFrom {
+ public enum LastModFrom {
OPENTIME, DIRLASTMOD, BOGUS;
/**
@@ -593,18 +630,20 @@ public class SolrConfig implements MapSerializable {
private final String cacheControlHeader;
private final Long maxAge;
private final LastModFrom lastModFrom;
+ private ConfigNode configNode;
private HttpCachingConfig(SolrConfig conf) {
+ configNode = conf.root;
//"requestDispatcher/httpCaching/";
- never304 = conf.__("requestDispatcher").__("httpCaching").boolAttr("never304", false);
+ never304 = __("requestDispatcher").__("httpCaching").boolAttr("never304", false);
- etagSeed = conf.__("requestDispatcher").__("httpCaching").attr("etagSeed", "Solr");
+ etagSeed = __("requestDispatcher").__("httpCaching").attr("etagSeed", "Solr");
- lastModFrom = LastModFrom.parse(conf.__("requestDispatcher").__("httpCaching").attr("lastModFrom","openTime"));
+ lastModFrom = LastModFrom.parse(__("requestDispatcher").__("httpCaching").attr("lastModFrom","openTime"));
- cacheControlHeader = conf.__("requestDispatcher").__("httpCaching").__("cacheControl").textValue();
+ cacheControlHeader = __("requestDispatcher").__("httpCaching").__("cacheControl").txt();
Long tmp = null; // maxAge
if (null != cacheControlHeader) {
@@ -622,6 +661,9 @@ public class SolrConfig implements MapSerializable {
maxAge = tmp;
}
+ private ConfigNode __(String name){
+ return configNode.__(name);
+ }
public boolean isNever304() {
return never304;
@@ -838,29 +880,13 @@ public class SolrConfig implements MapSerializable {
return enableStreamBody;
}
- private Object _getVal(String path) {
+ /*private Object _getVal(String path) {
List<String> parts = StrUtils.split(path,'/');
Object val = overlay.getXPathProperty(parts);
if(val !=null) return val;
return root.child(parts);
}
-
-
- static int getInt(Object v, int def) {
- if (v instanceof Number) return ((Number) v).intValue();
- return v == null ? def : Integer.parseInt(v.toString());
- }
-
- static boolean getBool(Object v, boolean def) {
- if (v instanceof Boolean) return (Boolean) v;
- return v == null ? def : Boolean.parseBoolean(v.toString());
- }
-
- public int _getInt(String path, int def) {
- Object val = _getVal(path);
- return val == null ? def : Integer.parseInt(val.toString());
- }
public String get(String path) {
Object val = _getVal(path);
return val != null ? val.toString() :null;
@@ -870,12 +896,12 @@ public class SolrConfig implements MapSerializable {
Object val = _getVal(path);
return val != null ? val.toString() : xml.get(path, def);
- }
+ }*/
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Map<String, Object> toMap(Map<String, Object> result) {
- if (xml.getZnodeVersion() > -1) result.put(ZNODEVER, xml.getZnodeVersion());
+ if (znodeVersion > -1) result.put(ZNODEVER, znodeVersion);
if(luceneMatchVersion != null) result.put(IndexSchema.LUCENE_MATCH_VERSION_PARAM, luceneMatchVersion.toString());
result.put("updateHandler", getUpdateHandlerInfo());
Map m = new LinkedHashMap();
@@ -938,8 +964,8 @@ public class SolrConfig implements MapSerializable {
public Properties getSubstituteProperties() {
Map<String, Object> p = getOverlay().getUserProps();
- if (p == null || p.isEmpty()) return xml.getSubstituteProperties();
- Properties result = new Properties(xml.getSubstituteProperties());
+ if (p == null || p.isEmpty()) return substituteProperties;
+ Properties result = new Properties(substituteProperties);
result.putAll(p);
return result;
}
@@ -948,7 +974,7 @@ public class SolrConfig implements MapSerializable {
public ConfigOverlay getOverlay() {
if (overlay == null) {
- overlay = getConfigOverlay(xml.getResourceLoader());
+ overlay = getConfigOverlay(resourceLoader);
}
return overlay;
}
@@ -975,12 +1001,8 @@ public class SolrConfig implements MapSerializable {
if (o == null || PackageLoader.LATEST.equals(o)) return null;
return o.toString();
}
- ConfigNode getRoot() {
- return root;
- }
-
public RequestParams refreshRequestParams() {
- requestParams = RequestParams.getFreshRequestParams(xml.getResourceLoader(), requestParams);
+ requestParams = RequestParams.getFreshRequestParams(resourceLoader, requestParams);
if (log.isDebugEnabled()) {
log.debug("current version of requestparams : {}", requestParams.getZnodeVersion());
}
@@ -988,24 +1010,33 @@ public class SolrConfig implements MapSerializable {
}
public SolrResourceLoader getResourceLoader() {
- return xml.getResourceLoader();
+ return resourceLoader;
}
public int getZnodeVersion() {
- return xml.getZnodeVersion();
+ return znodeVersion;
}
public String getName() {
- return xml.getName();
+ return resourceName;
}
public String getResourceName() {
- return xml.getResourceName();
+ return resourceName;
}
+ /**fetches a child node by name. An "empty node" is returned if the child does not exist
+ * This never returns a null
+ *
+ *
+ */
public ConfigNode __(String name) {
return root.__(name);
}
+ ConfigNode __(String name, Predicate<ConfigNode> test) {
+ return root.__(name, test);
+ }
+
}
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchemaFactory.java b/solr/core/src/java/org/apache/solr/schema/IndexSchemaFactory.java
index c9d3187..0131943 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchemaFactory.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchemaFactory.java
@@ -141,8 +141,8 @@ public abstract class IndexSchemaFactory implements NamedListInitializedPlugin {
}
public static class VersionedConfig {
- final int version;
- final ConfigNode data;
+ public final int version;
+ public final ConfigNode data;
public VersionedConfig(int version, ConfigNode data) {
this.version = version;
diff --git a/solr/core/src/java/org/apache/solr/search/CacheConfig.java b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
index 1f83b56..465494b 100644
--- a/solr/core/src/java/org/apache/solr/search/CacheConfig.java
+++ b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
@@ -109,7 +109,7 @@ public class CacheConfig implements MapSerializable{
@SuppressWarnings({"unchecked"})
public static CacheConfig getConfig(SolrConfig solrConfig, ConfigNode node, String xpath) {
// Node node = solrConfig.getNode(xpath, false);
- if(node == null || !"true".equals(node.attributes().get( "enabled", "true"))) {
+ if(!node.exists() || !"true".equals(node.attributes().get( "enabled", "true"))) {
Map<String, String> m = solrConfig.getOverlay().getEditableSubProperties(xpath);
if(m==null) return null;
List<String> parts = StrUtils.splitSmart(xpath, '/');
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
index cf24e33..ebb8395 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
@@ -19,7 +19,6 @@ package org.apache.solr.update;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Collections;
-import java.util.List;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
@@ -37,7 +36,6 @@ import org.apache.solr.common.util.Utils;
import org.apache.solr.core.DirectoryFactory;
import org.apache.solr.common.MapSerializable;
import org.apache.solr.core.PluginInfo;
-import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.index.DefaultMergePolicyFactory;
@@ -48,7 +46,6 @@ import org.apache.solr.schema.IndexSchema;
import org.apache.solr.util.SolrPluginUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.w3c.dom.Node;
import static org.apache.solr.core.XmlConfigFile.assertWarnOrFail;
@@ -93,11 +90,12 @@ public class SolrIndexConfig implements MapSerializable {
public final PluginInfo mergedSegmentWarmerInfo;
public InfoStream infoStream = InfoStream.NO_OUTPUT;
+ private ConfigNode node;
/**
* Internal constructor for setting defaults based on Lucene Version
*/
- private SolrIndexConfig(SolrConfig solrConfig) {
+ private SolrIndexConfig() {
useCompoundFile = false;
maxBufferedDocs = -1;
ramBufferSizeMB = 100;
@@ -111,23 +109,18 @@ public class SolrIndexConfig implements MapSerializable {
// enable coarse-grained metrics by default
metricsInfo = new PluginInfo("metrics", Collections.emptyMap(), null, null);
}
-
+ private ConfigNode __(String s) { return node.__(s); }
/**
* Constructs a SolrIndexConfig which parses the Lucene related config params in solrconfig.xml
- * @param solrConfig the overall SolrConfig object
- * @param prefix the XPath prefix for which section to parse (mandatory)
* @param def a SolrIndexConfig instance to pick default values from (optional)
*/
- public SolrIndexConfig(SolrConfig solrConfig, String prefix, SolrIndexConfig def) {
- if (prefix == null) {
- prefix = "indexConfig";
- log.debug("Defaulting to prefix '{}' for index configuration", prefix);
- }
-
+ public SolrIndexConfig(ConfigNode cfg, SolrIndexConfig def) {
+ this.node = cfg;
if (def == null) {
- def = new SolrIndexConfig(solrConfig);
+ def = new SolrIndexConfig();
}
+
// sanity check: this will throw an error for us if there is more then one
// config section
// Object unused = solrConfig.getNode(prefix, false);
@@ -135,65 +128,56 @@ public class SolrIndexConfig implements MapSerializable {
// Assert that end-of-life parameters or syntax is not in our config.
// Warn for luceneMatchVersion's before LUCENE_3_6, fail fast above
assertWarnOrFail("The <mergeScheduler>myclass</mergeScheduler> syntax is no longer supported in solrconfig.xml. Please use syntax <mergeScheduler class=\"myclass\"/> instead.",
- !(solrConfig.__(prefix).__("mergeScheduler") != null && (solrConfig.__(prefix).attr("class", null) == null)),
+ __("mergeScheduler").exists() && __("mergeScheduler").attr("class", null) == null,
true);
assertWarnOrFail("Beginning with Solr 7.0, <mergePolicy>myclass</mergePolicy> is no longer supported, use <mergePolicyFactory> instead.",
- !((solrConfig.__(prefix).__("mergePolicy") != null) && (solrConfig.__(prefix).__("mergePolicy").attr("class", null) == null)),
+ __("mergePolicy").exists() && __("mergePolicy").attr("class") == null,
true);
assertWarnOrFail("The <luceneAutoCommit>true|false</luceneAutoCommit> parameter is no longer valid in solrconfig.xml.",
- solrConfig.get(prefix + "/luceneAutoCommit", null) == null,
+ __("luceneAutoCommit").textValue() != null,
true);
- useCompoundFile = solrConfig.__(prefix).__("useCompoundFile")._bool(def.useCompoundFile);
- maxBufferedDocs = solrConfig.__(prefix).__("maxBufferedDocs")._int(def.maxBufferedDocs);
- ramBufferSizeMB = solrConfig.__(prefix).__("ramBufferSizeMB").doubleVal(def.ramBufferSizeMB);
- maxCommitMergeWaitMillis = solrConfig.__(prefix).__("maxCommitMergeWaitTime")._int(def.maxCommitMergeWaitMillis);
+ useCompoundFile = __("useCompoundFile")._bool(def.useCompoundFile);
+ maxBufferedDocs = __("maxBufferedDocs")._int(def.maxBufferedDocs);
+ ramBufferSizeMB = __("ramBufferSizeMB").doubleVal(def.ramBufferSizeMB);
+ maxCommitMergeWaitMillis = __("maxCommitMergeWaitTime")._int(def.maxCommitMergeWaitMillis);
// how do we validate the value??
- ramPerThreadHardLimitMB = solrConfig.__(prefix).__("ramPerThreadHardLimitMB")._int(def.ramPerThreadHardLimitMB);
+ ramPerThreadHardLimitMB = __("ramPerThreadHardLimitMB")._int(def.ramPerThreadHardLimitMB);
- writeLockTimeout= solrConfig.__(prefix).__("writeLockTimeout")._int(def.writeLockTimeout);
- lockType=solrConfig.get(prefix+"/lockType", def.lockType);
+ writeLockTimeout= __("writeLockTimeout")._int(def.writeLockTimeout);
+ lockType = __("lockType").txt(def.lockType);
- List<PluginInfo> infos = solrConfig.readPluginInfos(prefix + "/metrics", false, false);
- if (infos.isEmpty()) {
- metricsInfo = def.metricsInfo;
- } else {
- metricsInfo = infos.get(0);
- }
- mergeSchedulerInfo = getPluginInfo(prefix + "/mergeScheduler", solrConfig, def.mergeSchedulerInfo);
- mergePolicyFactoryInfo = getPluginInfo(prefix + "/mergePolicyFactory", solrConfig, def.mergePolicyFactoryInfo);
+ metricsInfo = getPluginInfo(__("metrics"), def.metricsInfo);
+ mergeSchedulerInfo = getPluginInfo(__("mergeScheduler"), def.mergeSchedulerInfo);
+ mergePolicyFactoryInfo = getPluginInfo(__("mergePolicyFactory"), def.mergePolicyFactoryInfo);
assertWarnOrFail("Beginning with Solr 7.0, <mergePolicy> is no longer supported, use <mergePolicyFactory> instead.",
- getPluginInfo(prefix + "/mergePolicy", solrConfig, null) == null,
+ __("mergePolicy").exists(),
true);
assertWarnOrFail("Beginning with Solr 7.0, <maxMergeDocs> is no longer supported, configure it on the relevant <mergePolicyFactory> instead.",
- solrConfig.__(prefix).__("maxMergeDocs")._int(0) == 0,
+ __("maxMergeDocs").exists(),
true);
assertWarnOrFail("Beginning with Solr 7.0, <mergeFactor> is no longer supported, configure it on the relevant <mergePolicyFactory> instead.",
- solrConfig.__(prefix).__("mergeFactor")._int(0) == 0,
+ __("maxMergeFactor").exists(),
true);
- String val = solrConfig.get(prefix + "/termIndexInterval", null);
- if (val != null) {
+ if (__("termIndexInterval").txt() != null) {
throw new IllegalArgumentException("Illegal parameter 'termIndexInterval'");
}
- boolean infoStreamEnabled = solrConfig.__(prefix).__("infoStream")._bool(false);
- if(infoStreamEnabled) {
- String infoStreamFile = solrConfig.__(prefix).__("infoStream").attr("file") ;
- if (infoStreamFile == null) {
+ if(__("infoStream")._bool(false)) {
+ if (__("infoStream").attr("file") == null) {
log.info("IndexWriter infoStream solr logging is enabled");
infoStream = new LoggingInfoStream();
} else {
throw new IllegalArgumentException("Remove @file from <infoStream> to output messages to solr's logfile");
}
}
- ConfigNode warmerInfo = solrConfig.__(prefix).__("mergedSegmentWarmer");
- mergedSegmentWarmerInfo = warmerInfo==null? def.mergedSegmentWarmerInfo : new PluginInfo(warmerInfo, "[solrconfig.xml] mergedSegmentWarmer" , false, false);
+ mergedSegmentWarmerInfo = getPluginInfo(__("mergedSegmentWarmer"), def.mergedSegmentWarmerInfo);
assertWarnOrFail("Beginning with Solr 5.0, <checkIntegrityAtMerge> option is no longer supported and should be removed from solrconfig.xml (these integrity checks are now automatic)",
- (null == solrConfig.__(prefix).__( "checkIntegrityAtMerge")),
+ __( "checkIntegrityAtMerge").exists(),
true);
}
@@ -218,9 +202,10 @@ public class SolrIndexConfig implements MapSerializable {
return m;
}
- private PluginInfo getPluginInfo(String path, SolrConfig solrConfig, PluginInfo def) {
- List<PluginInfo> l = solrConfig.readPluginInfos(path, false, true);
- return l.isEmpty() ? def : l.get(0);
+ private PluginInfo getPluginInfo(ConfigNode node , PluginInfo def) {
+ return node != null && node.exists() ?
+ new PluginInfo(node, "[solrconfig.xml] " + node.name(), false, true) :
+ def;
}
private static class DelayedSchemaAnalyzer extends DelegatingAnalyzerWrapper {
diff --git a/solr/core/src/java/org/apache/solr/update/VersionInfo.java b/solr/core/src/java/org/apache/solr/update/VersionInfo.java
index b97f812..cd36854 100644
--- a/solr/core/src/java/org/apache/solr/update/VersionInfo.java
+++ b/solr/core/src/java/org/apache/solr/update/VersionInfo.java
@@ -94,8 +94,8 @@ public class VersionInfo {
this.ulog = ulog;
IndexSchema schema = ulog.uhandler.core.getLatestSchema();
versionField = getAndCheckVersionField(schema);
- versionBucketLockTimeoutMs = ulog.uhandler.core.getSolrConfig().getInt("updateHandler/versionBucketLockTimeoutMs",
- Integer.parseInt(System.getProperty(SYS_PROP_BUCKET_VERSION_LOCK_TIMEOUT_MS, "0")));
+ versionBucketLockTimeoutMs = ulog.uhandler.core.getSolrConfig().__("updateHandler").__("versionBucketLockTimeoutMs")
+ ._int(Integer.parseInt(System.getProperty(SYS_PROP_BUCKET_VERSION_LOCK_TIMEOUT_MS, "0")));
buckets = new VersionBucket[ BitUtil.nextHighestPowerOfTwo(nBuckets) ];
for (int i=0; i<buckets.length; i++) {
if (versionBucketLockTimeoutMs > 0) {
diff --git a/solr/core/src/java/org/apache/solr/util/DataConfigNode.java b/solr/core/src/java/org/apache/solr/util/DataConfigNode.java
index 38940ee..04d927b 100644
--- a/solr/core/src/java/org/apache/solr/util/DataConfigNode.java
+++ b/solr/core/src/java/org/apache/solr/util/DataConfigNode.java
@@ -55,9 +55,7 @@ public class DataConfigNode implements ConfigNode {
}
public String subtituteVal(String s) {
- Function<String, String> props = SUBSTITUTES.get();
- if (props == null) return s;
- return PropertiesUtil.substitute(s, props);
+ return PropertiesUtil.substitute(s, SUBSTITUTES.get());
}
private SimpleMap<String> wrap(SimpleMap<String> delegate) {
diff --git a/solr/core/src/test/org/apache/solr/core/TestConfig.java b/solr/core/src/test/org/apache/solr/core/TestConfig.java
index 7a61fb7..fe39552 100644
--- a/solr/core/src/test/org/apache/solr/core/TestConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestConfig.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Collections;
import java.util.List;
+import java.util.function.Predicate;
import org.apache.lucene.index.ConcurrentMergeScheduler;
import org.apache.lucene.index.IndexWriterConfig;
@@ -91,14 +92,14 @@ public class TestConfig extends SolrTestCaseJ4 {
s = solrConfig.__("propTest").attr("attr2", "default");
assertEquals("default-from-config", s);
- s = solrConfig.get("propTest[@attr2='default-from-config']", "default");
- assertEquals("prefix-proptwo-suffix", s);
- List<ConfigNode> nl = solrConfig.root.children("propTest");
+ assertEquals("prefix-proptwo-suffix", solrConfig.__("propTest",
+ it -> "default-from-config".equals(it.attr("attr2"))).txt());
+
+ List<ConfigNode> nl = solrConfig.root.children ("propTest");
assertEquals(1, nl.size());
assertEquals("prefix-proptwo-suffix", nl.get(0).textValue());
-
assertEquals("prefix-proptwo-suffix", solrConfig.__("propTest"));
}
diff --git a/solr/solrj/src/java/org/apache/solr/common/ConfigNode.java b/solr/solrj/src/java/org/apache/solr/common/ConfigNode.java
index 17fd678..e88ca81 100644
--- a/solr/solrj/src/java/org/apache/solr/common/ConfigNode.java
+++ b/solr/solrj/src/java/org/apache/solr/common/ConfigNode.java
@@ -19,9 +19,7 @@ package org.apache.solr.common;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
@@ -29,6 +27,8 @@ import java.util.function.Supplier;
import org.apache.solr.cluster.api.SimpleMap;
import org.apache.solr.common.util.WrappedSimpleMap;
+import static org.apache.solr.common.ConfigNode.Helpers.*;
+
/**
* A generic interface that represents a config file, mostly XML
*/
@@ -59,11 +59,19 @@ public interface ConfigNode {
/**
* Child by name or return an empty node if null
+ * if there are multiple values , it returns the first elem
+ * This never returns a null
*/
default ConfigNode __(String name) {
ConfigNode child = child(null, name);
return child == null? EMPTY: child;
}
+ default ConfigNode __(String name, Predicate<ConfigNode> test) {
+ List<ConfigNode> children = children(test, name);
+ if(children.isEmpty()) return EMPTY;
+ return children.get(0);
+
+ }
default ConfigNode child(List<String> path) {
ConfigNode node = this;
@@ -91,12 +99,8 @@ public interface ConfigNode {
default int intAttr(String name, int def) { return __int(attributes().get(name), def); }
default boolean boolAttr(String name, boolean def){ return __bool(attributes().get(name), def); }
default String txt(String def) { return textValue() == null ? def : textValue();}
+ default String txt() { return textValue();}
default double doubleVal(double def){ return __double(textValue(), def); }
- default boolean __bool(Object v, boolean def) { return v == null ? def : Boolean.parseBoolean(v.toString()); }
- default String __txt(Object v, String def) { return v == null ? def : v.toString(); }
- default int __int(Object v, int def) { return v==null? def: Integer.parseInt(v.toString()); }
- default double __double(Object v, double def) { return v == null ? def: Double.parseDouble(v.toString()); }
-
/**Iterate through child nodes with the name and return the first child that matches
*/
default ConfigNode child(Predicate<ConfigNode> test, String name) {
@@ -138,6 +142,14 @@ public interface ConfigNode {
return children(null, Collections.singleton(name));
}
+ default boolean exists() {
+ return true;
+ }
+
+ default <T> T compute(Function<ConfigNode, T> ifNotNull, Supplier<T> ifNull) {
+ return ifNotNull.apply(this);
+ }
+
/** abortable iterate through children
*
* @param fun consume the node and return true to continue or false to abort
@@ -151,9 +163,7 @@ public interface ConfigNode {
}
@Override
- public String textValue() {
- return null;
- }
+ public String textValue() { return null; }
@Override
public SimpleMap<String> attributes() {
@@ -161,21 +171,34 @@ public interface ConfigNode {
}
@Override
- public ConfigNode child(String name) {
- return null;
- }
+ public String attr(String name) { return null; }
+
+ @Override
+ public String attr(String name, String def) { return def; }
+
+ @Override
+ public ConfigNode child(String name) { return null; }
@Override
public ConfigNode __(String name) {
return EMPTY;
}
+ public boolean exists() { return false; }
+
@Override
- public void forEachChild(Function<ConfigNode, Boolean> fun) {
+ public <T> T compute(Function<ConfigNode, T> ifNotNull, Supplier<T> ifNull) { return ifNull.get(); }
- }
+ @Override
+ public void forEachChild(Function<ConfigNode, Boolean> fun) { }
} ;
SimpleMap<String> empty_attrs = new WrappedSimpleMap<>(Collections.emptyMap());
+ class Helpers {
+ static boolean __bool(Object v, boolean def) { return v == null ? def : Boolean.parseBoolean(v.toString()); }
+ static String __txt(Object v, String def) { return v == null ? def : v.toString(); }
+ static int __int(Object v, int def) { return v==null? def: Integer.parseInt(v.toString()); }
+ static double __double(Object v, double def) { return v == null ? def: Double.parseDouble(v.toString()); }
+ }
}