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 2023/06/12 11:56:45 UTC
[solr] branch branch_9x updated: SOLR-16507:Remove NodeStateProvider & Snitch ported to 9x (#1702)
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new d16b791d295 SOLR-16507:Remove NodeStateProvider & Snitch ported to 9x (#1702)
d16b791d295 is described below
commit d16b791d295096e6b075cb3dbb3d9782f2be8913
Author: Noble Paul <no...@users.noreply.github.com>
AuthorDate: Mon Jun 12 21:56:38 2023 +1000
SOLR-16507:Remove NodeStateProvider & Snitch ported to 9x (#1702)
---
.../solr/cloud/api/collections/SplitShardCmd.java | 16 +-
.../placement/impl/AttributeFetcherImpl.java | 15 +-
.../cluster/placement/impl/NodeMetricImpl.java | 11 +-
.../solr/client/solrj/impl/NodeValueFetcher.java | 170 ++++++++++++++++++
.../solrj/impl/SolrClientNodeStateProvider.java | 182 +++-----------------
.../solr/common/cloud/rule/ImplicitSnitch.java | 191 ---------------------
.../solr/common/cloud/rule/RemoteCallback.java | 23 ---
.../org/apache/solr/common/cloud/rule/Snitch.java | 29 ----
.../solr/common/cloud/rule/SnitchContext.java | 103 -----------
.../solr/common/cloud/rule/package-info.java | 19 --
.../solrj/request/CollectionAdminRequest.java | 2 -
11 files changed, 214 insertions(+), 547 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
index 23473694b59..cfbc21743e2 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
@@ -17,7 +17,6 @@
package org.apache.solr.cloud.api.collections;
-import static org.apache.solr.client.solrj.impl.SolrClientNodeStateProvider.Variable.CORE_IDX;
import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.RANDOM;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_TYPE;
@@ -46,11 +45,13 @@ import org.apache.solr.client.solrj.cloud.DistribStateManager;
import org.apache.solr.client.solrj.cloud.NodeStateProvider;
import org.apache.solr.client.solrj.cloud.SolrCloudManager;
import org.apache.solr.client.solrj.cloud.VersionedData;
+import org.apache.solr.client.solrj.impl.NodeValueFetcher;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
import org.apache.solr.cloud.DistributedClusterStateUpdater;
import org.apache.solr.cloud.Overseer;
import org.apache.solr.cloud.api.collections.CollectionHandlingUtils.ShardRequestTracker;
import org.apache.solr.cloud.overseer.OverseerAction;
+import org.apache.solr.cluster.placement.impl.ReplicaMetricImpl;
import org.apache.solr.common.LinkedHashMapWriter;
import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException;
@@ -65,7 +66,6 @@ import org.apache.solr.common.cloud.ReplicaPosition;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
-import org.apache.solr.common.cloud.rule.ImplicitSnitch;
import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.params.CommonAdminParams;
import org.apache.solr.common.params.CommonParams;
@@ -878,10 +878,12 @@ public class SplitShardCmd implements CollApiCmds.CollectionApiCommand {
NodeStateProvider nodeStateProvider = cloudManager.getNodeStateProvider();
Map<String, Object> nodeValues =
nodeStateProvider.getNodeValues(
- parentShardLeader.getNodeName(), Collections.singletonList(ImplicitSnitch.DISK));
+ parentShardLeader.getNodeName(),
+ Collections.singletonList(NodeValueFetcher.Tags.FREEDISK.tagName));
Map<String, Map<String, List<Replica>>> infos =
nodeStateProvider.getReplicaInfo(
- parentShardLeader.getNodeName(), Collections.singletonList(CORE_IDX.metricsAttribute));
+ parentShardLeader.getNodeName(),
+ Collections.singletonList(ReplicaMetricImpl.INDEX_SIZE_GB.getInternalName()));
if (infos.get(collection) == null || infos.get(collection).get(shard) == null) {
log.warn("cannot verify information for parent shard leader");
return;
@@ -891,12 +893,12 @@ public class SplitShardCmd implements CollApiCmds.CollectionApiCommand {
Double indexSize = null;
for (Replica info : lst) {
if (info.getCoreName().equals(parentShardLeader.getCoreName())) {
- Number size = (Number) info.get(CORE_IDX.metricsAttribute);
+ Number size = (Number) info.get(ReplicaMetricImpl.INDEX_SIZE_GB.getInternalName());
if (size == null) {
log.warn("cannot verify information for parent shard leader");
return;
}
- indexSize = (Double) CORE_IDX.convertVal(size);
+ indexSize = ReplicaMetricImpl.INDEX_SIZE_GB.convert(size);
break;
}
}
@@ -904,7 +906,7 @@ public class SplitShardCmd implements CollApiCmds.CollectionApiCommand {
log.warn("missing replica information for parent shard leader");
return;
}
- Number freeSize = (Number) nodeValues.get(ImplicitSnitch.DISK);
+ Number freeSize = (Number) nodeValues.get(NodeValueFetcher.Tags.FREEDISK.tagName);
if (freeSize == null) {
log.warn("missing node disk space information for parent shard leader");
return;
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
index 0beba2366dc..251dd49759d 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
@@ -27,7 +27,7 @@ import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.apache.solr.client.solrj.cloud.SolrCloudManager;
-import org.apache.solr.client.solrj.impl.SolrClientNodeStateProvider;
+import org.apache.solr.client.solrj.impl.NodeValueFetcher;
import org.apache.solr.cluster.Node;
import org.apache.solr.cluster.SolrCollection;
import org.apache.solr.cluster.placement.AttributeFetcher;
@@ -37,7 +37,6 @@ import org.apache.solr.cluster.placement.NodeMetric;
import org.apache.solr.cluster.placement.ReplicaMetric;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.Replica;
-import org.apache.solr.common.cloud.rule.ImplicitSnitch;
import org.apache.solr.core.SolrInfoBean;
import org.apache.solr.metrics.SolrMetricManager;
import org.slf4j.Logger;
@@ -116,7 +115,7 @@ public class AttributeFetcherImpl implements AttributeFetcher {
for (NodeMetric<?> metric : requestedNodeMetricSnitchTags) {
final Map<Node, Object> metricMap = new HashMap<>();
metricSnitchToNodeToValue.put(metric, metricMap);
- String metricSnitch = getMetricSnitchTag(metric);
+ String metricSnitch = getMetricTag(metric);
allSnitchTagsToInsertion.put(
metricSnitch, (node, value) -> metricMap.put(node, metric.convert(value)));
}
@@ -231,23 +230,23 @@ public class AttributeFetcherImpl implements AttributeFetcher {
}
}
- public static String getMetricSnitchTag(NodeMetric<?> metric) {
+ public static String getMetricTag(NodeMetric<?> metric) {
if (metric.getRegistry() != NodeMetric.Registry.UNSPECIFIED) {
// regular registry + metricName
- return SolrClientNodeStateProvider.METRICS_PREFIX
+ return NodeValueFetcher.METRICS_PREFIX
+ SolrMetricManager.getRegistryName(getGroupFromMetricRegistry(metric.getRegistry()))
+ ":"
+ metric.getInternalName();
- } else if (ImplicitSnitch.tags.contains(metric.getInternalName())) {
+ } else if (NodeValueFetcher.tags.contains(metric.getInternalName())) {
// "special" well-known tag
return metric.getInternalName();
} else {
// a fully-qualified metric key
- return SolrClientNodeStateProvider.METRICS_PREFIX + metric.getInternalName();
+ return NodeValueFetcher.METRICS_PREFIX + metric.getInternalName();
}
}
public static String getSystemPropertySnitchTag(String name) {
- return ImplicitSnitch.SYSPROP + name;
+ return NodeValueFetcher.SYSPROP + name;
}
}
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
index f5f9cd8dbd6..b76013d1903 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
@@ -19,8 +19,8 @@ package org.apache.solr.cluster.placement.impl;
import java.util.Objects;
import java.util.function.Function;
+import org.apache.solr.client.solrj.impl.NodeValueFetcher;
import org.apache.solr.cluster.placement.NodeMetric;
-import org.apache.solr.common.cloud.rule.ImplicitSnitch;
/**
* Node metric identifier, corresponding to a node-level metric registry and the internal metric
@@ -40,14 +40,17 @@ public class NodeMetricImpl<T> extends MetricImpl<T> implements NodeMetric<T> {
/** Number of all cores. */
public static final NodeMetricImpl<Integer> NUM_CORES =
- new NodeMetricImpl<>(ImplicitSnitch.CORES);
+ new NodeMetricImpl<>(NodeValueFetcher.CORES);
public static final NodeMetricImpl<Double> HEAP_USAGE =
- new NodeMetricImpl<>(ImplicitSnitch.HEAPUSAGE);
+ new NodeMetricImpl<>(NodeValueFetcher.Tags.HEAPUSAGE.tagName);
/** System load average. */
public static final NodeMetricImpl<Double> SYSLOAD_AVG =
- new NodeMetricImpl<>("sysLoadAvg", Registry.SOLR_JVM, "os.systemLoadAverage");
+ new NodeMetricImpl<>(
+ NodeValueFetcher.Tags.SYSLOADAVG.tagName,
+ Registry.SOLR_JVM,
+ NodeValueFetcher.Tags.SYSLOADAVG.prefix);
/** Number of available processors. */
public static final NodeMetricImpl<Integer> AVAILABLE_PROCESSORS =
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
new file mode 100644
index 00000000000..c5832aa1432
--- /dev/null
+++ b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/NodeValueFetcher.java
@@ -0,0 +1,170 @@
+/*
+ * 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.client.solrj.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.solr.client.solrj.response.SimpleSolrResponse;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.common.util.Utils;
+
+/**
+ * This class is responsible for fetching metrics and other attributes from a given node in Solr
+ * cluster. This is a helper class that is used by {@link SolrClientNodeStateProvider}
+ */
+public class NodeValueFetcher {
+ // well known tags
+ public static final String NODE = "node";
+ public static final String PORT = "port";
+ public static final String HOST = "host";
+ public static final String CORES = "cores";
+ public static final String SYSPROP = "sysprop.";
+ public static final Set<String> tags =
+ Set.of(NODE, PORT, HOST, CORES, Tags.FREEDISK.tagName, Tags.HEAPUSAGE.tagName);
+ public static final Pattern hostAndPortPattern = Pattern.compile("(?:https?://)?([^:]+):(\\d+)");
+ public static final String METRICS_PREFIX = "metrics:";
+
+ /** Various well known tags that can be fetched from a node */
+ public enum Tags {
+ FREEDISK(
+ "freedisk", "solr.node", "CONTAINER.fs.usableSpace", "solr.node/CONTAINER.fs.usableSpace"),
+ TOTALDISK(
+ "totaldisk", "solr.node", "CONTAINER.fs.totalSpace", "solr.node/CONTAINER.fs.totalSpace"),
+ CORES("cores", "solr.node", "CONTAINER.cores", null) {
+ @Override
+ public Object extractResult(Object root) {
+ NamedList<?> node = (NamedList<?>) Utils.getObjectByPath(root, false, "solr.node");
+ int count = 0;
+ for (String leafCoreMetricName : new String[] {"lazy", "loaded", "unloaded"}) {
+ Number n = (Number) node.get("CONTAINER.cores." + leafCoreMetricName);
+ if (n != null) count += n.intValue();
+ }
+ return count;
+ }
+ },
+ SYSLOADAVG("sysLoadAvg", "solr.jvm", "os.systemLoadAverage", "solr.jvm/os.systemLoadAverage"),
+ HEAPUSAGE("heapUsage", "solr.jvm", "memory.heap.usage", "solr.jvm/memory.heap.usage");
+ // the metrics group
+ public final String group;
+ // the metrics prefix
+ public final String prefix;
+ public final String tagName;
+ // the json path in the response
+ public final String path;
+
+ Tags(String name, String group, String prefix, String path) {
+ this.group = group;
+ this.prefix = prefix;
+ this.tagName = name;
+ this.path = path;
+ }
+
+ public Object extractResult(Object root) {
+ Object v = Utils.getObjectByPath(root, true, path);
+ return v == null ? null : convertVal(v);
+ }
+
+ public Object convertVal(Object val) {
+ if (val instanceof String) {
+ return Double.valueOf((String) val);
+ } else if (val instanceof Number) {
+ Number num = (Number) val;
+ return num.doubleValue();
+
+ } else {
+ throw new IllegalArgumentException("Unknown type : " + val);
+ }
+ }
+ }
+
+ private void getRemoteInfo(
+ String solrNode, Set<String> requestedTags, SolrClientNodeStateProvider.RemoteCallCtx ctx) {
+ if (!(ctx).isNodeAlive(solrNode)) return;
+ Map<String, Set<Object>> metricsKeyVsTag = new HashMap<>();
+ for (String tag : requestedTags) {
+ if (tag.startsWith(SYSPROP)) {
+ metricsKeyVsTag
+ .computeIfAbsent(
+ "solr.jvm:system.properties:" + tag.substring(SYSPROP.length()),
+ k -> new HashSet<>())
+ .add(tag);
+ } else if (tag.startsWith(METRICS_PREFIX)) {
+ metricsKeyVsTag
+ .computeIfAbsent(tag.substring(METRICS_PREFIX.length()), k -> new HashSet<>())
+ .add(tag);
+ }
+ }
+ if (!metricsKeyVsTag.isEmpty()) {
+ SolrClientNodeStateProvider.fetchReplicaMetrics(solrNode, ctx, metricsKeyVsTag);
+ }
+
+ Set<String> groups = new HashSet<>();
+ List<String> prefixes = new ArrayList<>();
+ for (Tags t : Tags.values()) {
+ if (requestedTags.contains(t.tagName)) {
+ groups.add(t.group);
+ prefixes.add(t.prefix);
+ }
+ }
+ if (groups.isEmpty() || prefixes.isEmpty()) return;
+
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.add("group", StrUtils.join(groups, ','));
+ params.add("prefix", StrUtils.join(prefixes, ','));
+
+ try {
+ SimpleSolrResponse rsp = ctx.invokeWithRetry(solrNode, CommonParams.METRICS_PATH, params);
+ NamedList<?> metrics = (NamedList<?>) rsp.nl.get("metrics");
+ if (metrics != null) {
+ for (Tags t : Tags.values()) {
+ ctx.tags.put(t.tagName, t.extractResult(metrics));
+ }
+ }
+ } catch (Exception e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error getting remote info", e);
+ }
+ }
+
+ public void getTags(
+ String solrNode, Set<String> requestedTags, SolrClientNodeStateProvider.RemoteCallCtx ctx) {
+ try {
+ if (requestedTags.contains(NODE)) ctx.tags.put(NODE, solrNode);
+ if (requestedTags.contains(HOST)) {
+ Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
+ if (hostAndPortMatcher.find()) ctx.tags.put(HOST, hostAndPortMatcher.group(1));
+ }
+ if (requestedTags.contains(PORT)) {
+ Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
+ if (hostAndPortMatcher.find()) ctx.tags.put(PORT, hostAndPortMatcher.group(2));
+ }
+ getRemoteInfo(solrNode, requestedTags, ctx);
+ } catch (Exception e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
+ }
+ }
+}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientNodeStateProvider.java b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientNodeStateProvider.java
index 4d59091db54..1bc2aed24bc 100644
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientNodeStateProvider.java
+++ b/solr/solrj-zookeeper/src/java/org/apache/solr/client/solrj/impl/SolrClientNodeStateProvider.java
@@ -17,8 +17,6 @@
package org.apache.solr.client.solrj.impl;
-import static java.util.Collections.emptyMap;
-
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
@@ -43,28 +41,22 @@ import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
-import org.apache.solr.common.cloud.rule.ImplicitSnitch;
-import org.apache.solr.common.cloud.rule.SnitchContext;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Pair;
-import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
-import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** The <em>real</em> {@link NodeStateProvider}, which communicates with Solr via SolrJ. */
public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter {
- public static final String METRICS_PREFIX = "metrics:";
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final CloudLegacySolrClient solrClient;
protected final Map<String, Map<String, Map<String, List<Replica>>>>
nodeVsCollectionVsShardVsReplicaInfo = new HashMap<>();
- private Map<String, Object> snitchSession = new HashMap<>();
@SuppressWarnings({"rawtypes"})
private Map<String, Map> nodeVsTags = new HashMap<>();
@@ -121,10 +113,10 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
}
protected Map<String, Object> fetchTagValues(String node, Collection<String> tags) {
- MetricsFetchingSnitch snitch = new MetricsFetchingSnitch();
- ClientSnitchCtx ctx = new ClientSnitchCtx(null, node, snitchSession, solrClient);
- snitch.getTags(node, new HashSet<>(tags), ctx);
- return ctx.getTags();
+ NodeValueFetcher nodeValueFetcher = new NodeValueFetcher();
+ RemoteCallCtx ctx = new RemoteCallCtx(node, solrClient);
+ nodeValueFetcher.getTags(node, new HashSet<>(tags), ctx);
+ return ctx.tags;
}
public void forEachReplica(String node, Consumer<Replica> consumer) {
@@ -188,13 +180,13 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
Map<String, Set<Object>> collect =
metricsKeyVsTagReplica.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> Set.of(e.getKey())));
- ClientSnitchCtx ctx = new ClientSnitchCtx(null, null, emptyMap(), solrClient);
+ RemoteCallCtx ctx = new RemoteCallCtx(null, solrClient);
fetchReplicaMetrics(node, ctx, collect);
- return ctx.getTags();
+ return ctx.tags;
}
static void fetchReplicaMetrics(
- String solrNode, ClientSnitchCtx ctx, Map<String, Set<Object>> metricsKeyVsTag) {
+ String solrNode, RemoteCallCtx ctx, Map<String, Set<Object>> metricsKeyVsTag) {
if (!ctx.isNodeAlive(solrNode)) return;
ModifiableSolrParams params = new ModifiableSolrParams();
params.add("key", metricsKeyVsTag.keySet().toArray(new String[0]));
@@ -207,9 +199,9 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
if (tag instanceof Function) {
@SuppressWarnings({"unchecked"})
Pair<String, Object> p = (Pair<String, Object>) ((Function) tag).apply(v);
- ctx.getTags().put(p.first(), p.second());
+ ctx.tags.put(p.first(), p.second());
} else {
- if (v != null) ctx.getTags().put(tag.toString(), v);
+ if (v != null) ctx.tags.put(tag.toString(), v);
}
}
});
@@ -221,110 +213,22 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
@Override
public void close() throws IOException {}
- // uses metrics API to get node information
- static class MetricsFetchingSnitch extends ImplicitSnitch {
- @Override
- protected void getRemoteInfo(String solrNode, Set<String> requestedTags, SnitchContext ctx) {
- if (!((ClientSnitchCtx) ctx).isNodeAlive(solrNode)) return;
- ClientSnitchCtx snitchContext = (ClientSnitchCtx) ctx;
- Map<String, Set<Object>> metricsKeyVsTag = new HashMap<>();
- for (String tag : requestedTags) {
- if (tag.startsWith(SYSPROP)) {
- metricsKeyVsTag
- .computeIfAbsent(
- "solr.jvm:system.properties:" + tag.substring(SYSPROP.length()),
- k -> new HashSet<>())
- .add(tag);
- } else if (tag.startsWith(METRICS_PREFIX)) {
- metricsKeyVsTag
- .computeIfAbsent(tag.substring(METRICS_PREFIX.length()), k -> new HashSet<>())
- .add(tag);
- }
- }
- if (!metricsKeyVsTag.isEmpty()) {
- fetchReplicaMetrics(solrNode, snitchContext, metricsKeyVsTag);
- }
-
- Set<String> groups = new HashSet<>();
- List<String> prefixes = new ArrayList<>();
- if (requestedTags.contains(DISK)) {
- groups.add("solr.node");
- prefixes.add("CONTAINER.fs.usableSpace");
- }
- if (requestedTags.contains(Variable.TOTALDISK.tagName)) {
- groups.add("solr.node");
- prefixes.add("CONTAINER.fs.totalSpace");
- }
- if (requestedTags.contains(CORES)) {
- groups.add("solr.node");
- prefixes.add("CONTAINER.cores");
- }
- if (requestedTags.contains(SYSLOADAVG)) {
- groups.add("solr.jvm");
- prefixes.add("os.systemLoadAverage");
- }
- if (requestedTags.contains(HEAPUSAGE)) {
- groups.add("solr.jvm");
- prefixes.add("memory.heap.usage");
- }
- if (groups.isEmpty() || prefixes.isEmpty()) return;
-
- ModifiableSolrParams params = new ModifiableSolrParams();
- params.add("group", StrUtils.join(groups, ','));
- params.add("prefix", StrUtils.join(prefixes, ','));
-
- try {
- SimpleSolrResponse rsp =
- snitchContext.invokeWithRetry(solrNode, CommonParams.METRICS_PATH, params);
- NamedList<?> metrics = (NamedList<?>) rsp.nl.get("metrics");
- if (metrics != null) {
- // metrics enabled
- if (requestedTags.contains(Variable.FREEDISK.tagName)) {
- Object n = Utils.getObjectByPath(metrics, true, "solr.node/CONTAINER.fs.usableSpace");
- if (n != null)
- ctx.getTags().put(Variable.FREEDISK.tagName, Variable.FREEDISK.convertVal(n));
- }
- if (requestedTags.contains(Variable.TOTALDISK.tagName)) {
- Object n = Utils.getObjectByPath(metrics, true, "solr.node/CONTAINER.fs.totalSpace");
- if (n != null)
- ctx.getTags().put(Variable.TOTALDISK.tagName, Variable.TOTALDISK.convertVal(n));
- }
- if (requestedTags.contains(CORES)) {
- NamedList<?> node = (NamedList<?>) metrics.get("solr.node");
- int count = 0;
- for (String leafCoreMetricName : new String[] {"lazy", "loaded", "unloaded"}) {
- Number n = (Number) node.get("CONTAINER.cores." + leafCoreMetricName);
- if (n != null) count += n.intValue();
- }
- ctx.getTags().put(CORES, count);
- }
- if (requestedTags.contains(SYSLOADAVG)) {
- Number n =
- (Number) Utils.getObjectByPath(metrics, true, "solr.jvm/os.systemLoadAverage");
- if (n != null) ctx.getTags().put(SYSLOADAVG, n.doubleValue());
- }
- if (requestedTags.contains(HEAPUSAGE)) {
- Number n = (Number) Utils.getObjectByPath(metrics, true, "solr.jvm/memory.heap.usage");
- if (n != null) ctx.getTags().put(HEAPUSAGE, n.doubleValue() * 100.0d);
- }
- }
- } catch (Exception e) {
- throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR, "Error getting remote info", e);
- }
- }
- }
-
@Override
public String toString() {
return Utils.toJSONString(this);
}
- static class ClientSnitchCtx extends SnitchContext {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ /**
+ * Mostly an info object that stores all the values for a given session to fetch various values
+ * from a node
+ */
+ static class RemoteCallCtx {
ZkClientClusterStateProvider zkClientClusterStateProvider;
CloudLegacySolrClient solrClient;
+ public final Map<String, Object> tags = new HashMap<>();
+ private String node;
+ public Map<String, Object> session;
public boolean isNodeAlive(String node) {
if (zkClientClusterStateProvider != null) {
@@ -333,35 +237,13 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
return true;
}
- public ClientSnitchCtx(
- SnitchInfo perSnitch,
- String node,
- Map<String, Object> session,
- CloudLegacySolrClient solrClient) {
- super(perSnitch, node, session);
+ public RemoteCallCtx(String node, CloudLegacySolrClient solrClient) {
+ this.node = node;
this.solrClient = solrClient;
this.zkClientClusterStateProvider =
(ZkClientClusterStateProvider) solrClient.getClusterStateProvider();
}
- @Override
- @SuppressWarnings({"unchecked"})
- public Map<?, ?> getZkJson(String path) throws KeeperException, InterruptedException {
- try {
- byte[] bytes =
- zkClientClusterStateProvider
- .getZkStateReader()
- .getZkClient()
- .getData(path, null, null, true);
- if (bytes != null && bytes.length > 0) {
- return (Map<String, Object>) Utils.fromJSON(bytes);
- }
- } catch (KeeperException.NoNodeException e) {
- return emptyMap();
- }
- return emptyMap();
- }
-
/**
* Will attempt to call {@link #invoke(String, String, SolrParams)} up to five times, retrying
* on any IO Exceptions
@@ -418,31 +300,9 @@ public class SolrClientNodeStateProvider implements NodeStateProvider, MapWriter
return request.response;
}
}
- }
-
- public enum Variable {
- FREEDISK("freedisk", null, Double.class),
- TOTALDISK("totaldisk", null, Double.class),
- CORE_IDX("INDEX.sizeInGB", "INDEX.sizeInBytes", Double.class);
- public final String tagName, metricsAttribute;
- public final Class<?> type;
-
- Variable(String tagName, String metricsAttribute, Class<?> type) {
- this.tagName = tagName;
- this.metricsAttribute = metricsAttribute;
- this.type = type;
- }
- public Object convertVal(Object val) {
- if (val instanceof String) {
- return Double.valueOf((String) val);
- } else if (val instanceof Number) {
- Number num = (Number) val;
- return num.doubleValue();
-
- } else {
- throw new IllegalArgumentException("Unknown type : " + val);
- }
+ public String getNode() {
+ return node;
}
}
}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/ImplicitSnitch.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/ImplicitSnitch.java
deleted file mode 100644
index 8f84f34273a..00000000000
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/ImplicitSnitch.java
+++ /dev/null
@@ -1,191 +0,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.
- */
-package org.apache.solr.common.cloud.rule;
-
-import java.lang.invoke.MethodHandles;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.cloud.ZkStateReader;
-import org.apache.zookeeper.KeeperException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-// This is the client-side component of the snitch
-public class ImplicitSnitch extends Snitch {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- public static final Pattern hostAndPortPattern = Pattern.compile("(?:https?://)?([^:]+):(\\d+)");
-
- // well known tags
- public static final String NODE = "node";
- public static final String PORT = "port";
- public static final String HOST = "host";
- public static final String CORES = "cores";
- public static final String DISK = "freedisk";
- public static final String ROLE = "role";
- public static final String NODEROLE = "nodeRole";
- public static final String SYSPROP = "sysprop.";
- public static final String SYSLOADAVG = "sysLoadAvg";
- public static final String HEAPUSAGE = "heapUsage";
- public static final List<String> IP_SNITCHES =
- Collections.unmodifiableList(Arrays.asList("ip_1", "ip_2", "ip_3", "ip_4"));
- public static final Set<String> tags =
- Set.of(NODE, PORT, HOST, CORES, DISK, ROLE, HEAPUSAGE, "ip_1", "ip_2", "ip_3", "ip_4");
-
- @Override
- public void getTags(String solrNode, Set<String> requestedTags, SnitchContext ctx) {
- try {
- if (requestedTags.contains(NODE)) ctx.getTags().put(NODE, solrNode);
- if (requestedTags.contains(HOST)) {
- Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
- if (hostAndPortMatcher.find()) ctx.getTags().put(HOST, hostAndPortMatcher.group(1));
- }
- if (requestedTags.contains(PORT)) {
- Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
- if (hostAndPortMatcher.find()) ctx.getTags().put(PORT, hostAndPortMatcher.group(2));
- }
- if (requestedTags.contains(ROLE)) fillRole(solrNode, ctx, ROLE);
- if (requestedTags.contains(NODEROLE))
- fillRole(solrNode, ctx, NODEROLE); // for new policy framework
-
- addIpTags(solrNode, requestedTags, ctx);
-
- getRemoteInfo(solrNode, requestedTags, ctx);
- } catch (Exception e) {
- throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
- }
- }
-
- protected void getRemoteInfo(String solrNode, Set<String> requestedTags, SnitchContext ctx) {
- HashMap<String, Object> params = new HashMap<>();
- if (requestedTags.contains(CORES)) params.put(CORES, "1");
- if (requestedTags.contains(DISK)) params.put(DISK, "1");
- for (String tag : requestedTags) {
- if (tag.startsWith(SYSPROP)) params.put(tag, tag.substring(SYSPROP.length()));
- }
-
- if (params.size() > 0) {
- Map<String, Object> vals = ctx.getNodeValues(solrNode, params.keySet());
- for (Map.Entry<String, Object> e : vals.entrySet()) {
- if (e.getValue() != null) params.put(e.getKey(), e.getValue());
- }
- }
- ctx.getTags().putAll(params);
- }
-
- private void fillRole(String solrNode, SnitchContext ctx, String key)
- throws KeeperException, InterruptedException {
- Map<?, ?> roles =
- (Map<?, ?>) ctx.retrieve(ZkStateReader.ROLES); // we don't want to hit the ZK for each node
- // so cache and reuse
- try {
- if (roles == null) roles = ctx.getZkJson(ZkStateReader.ROLES);
- cacheRoles(solrNode, ctx, key, roles);
- } catch (KeeperException.NoNodeException e) {
- cacheRoles(solrNode, ctx, key, Collections.emptyMap());
- }
- }
-
- private void cacheRoles(String solrNode, SnitchContext ctx, String key, Map<?, ?> roles) {
- ctx.store(ZkStateReader.ROLES, roles);
- if (roles != null) {
- for (Map.Entry<?, ?> e : roles.entrySet()) {
- if (e.getValue() instanceof List) {
- if (((List<?>) e.getValue()).contains(solrNode)) {
- ctx.getTags().put(key, e.getKey());
- break;
- }
- }
- }
- }
- }
-
- private static final String HOST_FRAG_SEPARATOR_REGEX = "\\.";
-
- @Override
- public boolean isKnownTag(String tag) {
- return tags.contains(tag) || tag.startsWith(SYSPROP);
- }
-
- private void addIpTags(String solrNode, Set<String> requestedTags, SnitchContext context) {
-
- List<String> requestedHostTags = new ArrayList<>();
- for (String tag : requestedTags) {
- if (IP_SNITCHES.contains(tag)) {
- requestedHostTags.add(tag);
- }
- }
-
- if (requestedHostTags.isEmpty()) {
- return;
- }
-
- String[] ipFragments = getIpFragments(solrNode);
-
- if (ipFragments == null) {
- return;
- }
-
- int ipSnitchCount = IP_SNITCHES.size();
- for (int i = 0; i < ipSnitchCount; i++) {
- String currentTagValue = ipFragments[i];
- String currentTagKey = IP_SNITCHES.get(ipSnitchCount - i - 1);
-
- if (requestedHostTags.contains(currentTagKey)) {
- context.getTags().put(currentTagKey, currentTagValue);
- }
- }
- }
-
- private String[] getIpFragments(String solrNode) {
- Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
- if (hostAndPortMatcher.find()) {
- String host = hostAndPortMatcher.group(1);
- if (host != null) {
- String ip = getHostIp(host);
- if (ip != null) {
- return ip.split(HOST_FRAG_SEPARATOR_REGEX); // IPv6 support will be provided by SOLR-8523
- }
- }
- }
-
- log.warn(
- "Failed to match host IP address from node URL [{}] using regex [{}]",
- solrNode,
- hostAndPortPattern.pattern());
- return null;
- }
-
- public String getHostIp(String host) {
- try {
- InetAddress address = InetAddress.getByName(host);
- return address.getHostAddress();
- } catch (Exception e) {
- log.warn("Failed to get IP address from host [{}], with exception [{}] ", host, e);
- return null;
- }
- }
-}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/RemoteCallback.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/RemoteCallback.java
deleted file mode 100644
index a5a4e98d70f..00000000000
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/RemoteCallback.java
+++ /dev/null
@@ -1,23 +0,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.
- */
-package org.apache.solr.common.cloud.rule;
-
-import java.util.Map;
-
-public interface RemoteCallback {
- void remoteCallback(SnitchContext ctx, Map<String, Object> returnedVal);
-}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/Snitch.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/Snitch.java
deleted file mode 100644
index 916a639f647..00000000000
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/Snitch.java
+++ /dev/null
@@ -1,29 +0,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.
- */
-package org.apache.solr.common.cloud.rule;
-
-import java.util.Collections;
-import java.util.Set;
-
-public abstract class Snitch {
- public static final Set<Class<?>> WELL_KNOWN_SNITCHES =
- Collections.singleton(ImplicitSnitch.class);
-
- public abstract void getTags(String solrNode, Set<String> requestedTags, SnitchContext ctx);
-
- public abstract boolean isKnownTag(String tag);
-}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/SnitchContext.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/SnitchContext.java
deleted file mode 100644
index e63660feb5f..00000000000
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/SnitchContext.java
+++ /dev/null
@@ -1,103 +0,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.
- */
-package org.apache.solr.common.cloud.rule;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.zookeeper.KeeperException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is the context provided to the snitches to interact with the system. This is a
- * per-node-per-snitch instance.
- */
-public abstract class SnitchContext implements RemoteCallback {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final Map<String, Object> tags = new HashMap<>();
- private String node;
- private Map<String, Object> session;
- public final SnitchInfo snitchInfo;
- public Exception exception;
-
- public SnitchContext(SnitchInfo perSnitch, String node, Map<String, Object> session) {
- this.snitchInfo = perSnitch;
- this.node = node;
- this.session = session;
- }
-
- public Map<String, Object> getTags() {
- return tags;
- }
-
- public void store(String s, Object val) {
- if (session != null) session.put(s, val);
- }
-
- public Object retrieve(String s) {
- return session != null ? session.get(s) : null;
- }
-
- public Map<String, Object> getNodeValues(String node, Collection<String> tags) {
- return Collections.emptyMap();
- }
-
- public abstract Map<?, ?> getZkJson(String path) throws KeeperException, InterruptedException;
-
- public String getNode() {
- return node;
- }
-
- /**
- * make a call to solrnode/admin/cores with the given params and give a callback. This is designed
- * to be asynchronous because the system would want to batch the calls made to any given node
- *
- * @param node The node for which this call is made
- * @param params The params to be passed to the Snitch counterpart
- * @param klas The name of the class to be invoked in the remote node
- * @param callback The callback to be called when the response is obtained from remote node. If
- * this is passed as null the entire response map will be added as tags
- */
- @Deprecated
- public void invokeRemote(
- String node, ModifiableSolrParams params, String klas, RemoteCallback callback) {}
- ;
-
- @Override
- public void remoteCallback(SnitchContext ctx, Map<String, Object> returnedVal) {
- tags.putAll(returnedVal);
- }
-
- public String getErrMsg() {
- return exception == null ? null : exception.getMessage();
- }
-
- public abstract static class SnitchInfo {
- private final Map<String, Object> conf;
-
- protected SnitchInfo(Map<String, Object> conf) {
- this.conf = conf;
- }
-
- public abstract Set<String> getTagNames();
- }
-}
diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/package-info.java b/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/package-info.java
deleted file mode 100644
index ba8b61c5d2f..00000000000
--- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/rule/package-info.java
+++ /dev/null
@@ -1,19 +0,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.
- */
-
-/** Classes for managing Replica placement strategy when operating in SolrCloud mode. */
-package org.apache.solr.common.cloud.rule;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
index 0b2357dff0c..83dbd1fae8b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
@@ -1343,8 +1343,6 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
return this;
}
- // TODO support rule, snitch
-
@Override
public SolrParams getParams() {
ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();