Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 8236C200CB5 for ; Wed, 28 Jun 2017 04:26:05 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 811E5160BF6; Wed, 28 Jun 2017 02:26:05 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7D8BC160BDC for ; Wed, 28 Jun 2017 04:26:03 +0200 (CEST) Received: (qmail 48292 invoked by uid 500); 28 Jun 2017 02:26:02 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 48283 invoked by uid 99); 28 Jun 2017 02:26:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Jun 2017 02:26:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id A5AD0ED4A2; Wed, 28 Jun 2017 02:25:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ishan@apache.org To: commits@lucene.apache.org Date: Wed, 28 Jun 2017 02:25:59 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [1/2] lucene-solr:master: SOLR-10931: Refactoring the package name for autoscaling client classes archived-at: Wed, 28 Jun 2017 02:26:05 -0000 Repository: lucene-solr Updated Branches: refs/heads/master ce4a7911e -> 13a3ae292 http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Clause.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Clause.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Clause.java deleted file mode 100644 index 5e4078a..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Clause.java +++ /dev/null @@ -1,460 +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.cloud.autoscaling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.solr.cloud.autoscaling.Policy.ReplicaInfo; -import org.apache.solr.common.MapWriter; -import org.apache.solr.common.cloud.rule.ImplicitSnitch; -import org.apache.solr.common.util.StrUtils; -import org.apache.solr.common.util.Utils; - -import static java.util.Collections.singletonMap; -import static org.apache.solr.cloud.autoscaling.Clause.TestStatus.PASS; -import static org.apache.solr.cloud.autoscaling.Operand.EQUAL; -import static org.apache.solr.cloud.autoscaling.Operand.GREATER_THAN; -import static org.apache.solr.cloud.autoscaling.Operand.LESS_THAN; -import static org.apache.solr.cloud.autoscaling.Operand.NOT_EQUAL; -import static org.apache.solr.cloud.autoscaling.Operand.WILDCARD; -import static org.apache.solr.cloud.autoscaling.Policy.ANY; -import static org.apache.solr.common.params.CoreAdminParams.COLLECTION; -import static org.apache.solr.common.params.CoreAdminParams.REPLICA; -import static org.apache.solr.common.params.CoreAdminParams.SHARD; - -// a set of conditions in a policy -public class Clause implements MapWriter, Comparable { - Map original; - Condition collection, shard, replica, tag, globalTag; - - boolean strict = true; - - Clause(Map m) { - this.original = m; - strict = Boolean.parseBoolean(String.valueOf(m.getOrDefault("strict", "true"))); - Optional globalTagName = m.keySet().stream().filter(Policy.GLOBAL_ONLY_TAGS::contains).findFirst(); - if (globalTagName.isPresent()) { - globalTag = parse(globalTagName.get(), m); - if (m.size() > 2) { - throw new RuntimeException("Only one extra tag supported for the tag " + globalTagName.get() + " in " + Utils.toJSONString(m)); - } - tag = parse(m.keySet().stream() - .filter(s -> (!globalTagName.get().equals(s) && !IGNORE_TAGS.contains(s))) - .findFirst().get(), m); - } else { - collection = parse(COLLECTION, m); - shard = parse(SHARD, m); - if(m.get(REPLICA) == null){ - throw new RuntimeException(StrUtils.formatString("'replica' is required in {0}", Utils.toJSONString(m))); - } - this.replica = parse(REPLICA, m); - if (replica.op == WILDCARD) throw new RuntimeException("replica val cannot be null" + Utils.toJSONString(m)); - m.forEach((s, o) -> parseCondition(s, o)); - } - if (tag == null) - throw new RuntimeException("Invalid op, must have one and only one tag other than collection, shard,replica " + Utils.toJSONString(m)); - - } - - public boolean doesOverride(Clause that) { - return (collection.equals(that.collection) && - tag.name.equals(that.tag.name)); - - } - - public boolean isPerCollectiontag() { - return globalTag == null; - } - - void parseCondition(String s, Object o) { - if (IGNORE_TAGS.contains(s)) return; - if (tag != null) { - throw new IllegalArgumentException("Only one tag other than collection, shard, replica is possible"); - } - tag = parse(s, singletonMap(s, o)); - } - - @Override - public int compareTo(Clause that) { - try { - int v = Integer.compare(this.tag.op.priority, that.tag.op.priority); - if (v != 0) return v; - if (this.isPerCollectiontag() && that.isPerCollectiontag()) { - v = Integer.compare(this.replica.op.priority, that.replica.op.priority); - if (v == 0) { - v = Long.compare((Long) this.replica.val, (Long) that.replica.val); - v = this.replica.op == LESS_THAN ? v : v * -1; - } - return v; - } else { - return 0; - } - } catch (NullPointerException e) { - throw e; - } - } - - void addTags(List params) { - if (globalTag != null && !params.contains(globalTag.name)) params.add(globalTag.name); - if (tag != null && !params.contains(tag.name)) params.add(tag.name); - } - - static class Condition { - final String name; - final Object val; - final Operand op; - - Condition(String name, Object val, Operand op) { - this.name = name; - this.val = val; - this.op = op; - } - - TestStatus match(Row row) { - return op.match(val, row.getVal(name)); - } - - TestStatus match(Object testVal) { - return op.match(this.val, testVal); - } - - boolean isPass(Object inputVal) { - return op.match(val, validate(name, inputVal, false)) == PASS; - } - - boolean isPass(Row row) { - return op.match(val, row.getVal(name)) == PASS; - } - - @Override - public boolean equals(Object that) { - if (that instanceof Condition) { - Condition c = (Condition) that; - return Objects.equals(c.name, name) && Objects.equals(c.val, val) && c.op == op; - } - return false; - } - - public Integer delta(Object val) { - return op.delta(this.val, val); - } - } - - static Condition parse(String s, Map m) { - Object expectedVal = null; - Object val = m.get(s); - try { - String conditionName = s.trim(); - Operand operand = null; - if (val == null) { - operand = WILDCARD; - expectedVal = Policy.ANY; - } else if (val instanceof String) { - String strVal = ((String) val).trim(); - if (Policy.ANY.equals(strVal) || Policy.EACH.equals(strVal)) operand = WILDCARD; - else if (strVal.startsWith(NOT_EQUAL.operand)) operand = NOT_EQUAL; - else if (strVal.startsWith(GREATER_THAN.operand)) operand = GREATER_THAN; - else if (strVal.startsWith(LESS_THAN.operand)) operand = LESS_THAN; - else operand = EQUAL; - expectedVal = validate(s, strVal.substring(EQUAL == operand || WILDCARD == operand ? 0 : 1), true); - } else if (val instanceof Number) { - operand = EQUAL; - expectedVal = validate(s, val, true); - } - return new Condition(conditionName, expectedVal, operand); - - } catch (Exception e) { - throw new IllegalArgumentException("Invalid tag : " + s + ":" + val, e); - } - } - - public class Violation implements MapWriter { - final String shard, coll, node; - final Object actualVal; - final Integer delta;//how far is the actual value from the expected value - final Object tagKey; - private final int hash; - - - private Violation(String coll, String shard, String node, Object actualVal, Integer delta, Object tagKey) { - this.shard = shard; - this.coll = coll; - this.node = node; - this.delta = delta; - this.actualVal = actualVal; - this.tagKey = tagKey; - hash = ("" + coll + " " + shard + " " + node + " " + String.valueOf(tagKey) + " " + Utils.toJSONString(getClause().toMap(new HashMap<>()))).hashCode(); - } - - public Clause getClause() { - return Clause.this; - } - - @Override - public int hashCode() { - return hash; - } - //if the delta is lower , this violation is less serious - public boolean isLessSerious(Violation that) { - return that.delta != null && delta != null && - Math.abs(delta) < Math.abs(that.delta); - } - - @Override - public boolean equals(Object that) { - if (that instanceof Violation) { - Violation v = (Violation) that; - return Objects.equals(this.shard, v.shard) && - Objects.equals(this.coll, v.coll) && - Objects.equals(this.node, v.node) && - Objects.equals(this.tagKey, v.tagKey) - ; - } - return false; - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - ew.putIfNotNull("collection", coll); - ew.putIfNotNull("shard", shard); - ew.putIfNotNull("node", node); - ew.putIfNotNull("tagKey", String.valueOf(tagKey)); - ew.putIfNotNull("violation", (MapWriter) ew1 -> { - ew1.put(getClause().isPerCollectiontag() ? "replica" : tag.name, - String.valueOf(actualVal)); - ew1.putIfNotNull("delta", delta); - }); - ew.put("clause", getClause()); - } - } - - - public List test(List allRows) { - List violations = new ArrayList<>(); - if (isPerCollectiontag()) { - Map>> replicaCount = computeReplicaCounts(allRows); - for (Map.Entry>> e : replicaCount.entrySet()) { - if (!collection.isPass(e.getKey())) continue; - for (Map.Entry> shardVsCount : e.getValue().entrySet()) { - if (!shard.isPass(shardVsCount.getKey())) continue; - for (Map.Entry counts : shardVsCount.getValue().entrySet()) { - if (!replica.isPass(counts.getValue())) { - violations.add(new Violation( - e.getKey(), - shardVsCount.getKey(), - tag.name.equals("node") ? counts.getKey() : null, - counts.getValue(), - replica.delta(counts.getValue()), - counts.getKey() - )); - } - } - } - } - } else { - for (Row r : allRows) { - if (!tag.isPass(r)) { - violations.add(new Violation(null, null, r.node, r.getVal(tag.name), tag.delta(r.getVal(tag.name)), null)); - } - } - } - return violations; - - } - - - private Map>> computeReplicaCounts(List allRows) { - Map>> collVsShardVsTagVsCount = new HashMap<>(); - for (Row row : allRows) - for (Map.Entry>> colls : row.collectionVsShardVsReplicas.entrySet()) { - String collectionName = colls.getKey(); - if (!collection.isPass(collectionName)) continue; - collVsShardVsTagVsCount.putIfAbsent(collectionName, new HashMap<>()); - Map> collMap = collVsShardVsTagVsCount.get(collectionName); - for (Map.Entry> shards : colls.getValue().entrySet()) { - String shardName = shards.getKey(); - if (ANY.equals(shard.val)) shardName = ANY; - if (!shard.isPass(shardName)) break; - collMap.putIfAbsent(shardName, new HashMap<>()); - Map tagVsCount = collMap.get(shardName); - Object tagVal = row.getVal(tag.name); - tagVsCount.putIfAbsent(tag.isPass(tagVal) ? String.valueOf(tagVal) : "", new AtomicInteger()); - if (tag.isPass(tagVal)) { - tagVsCount.get(String.valueOf(tagVal)).addAndGet(shards.getValue().size()); - } - } - } - return collVsShardVsTagVsCount; - } - - public boolean isStrict() { - return strict; - } - - @Override - public String toString() { - return Utils.toJSONString(original); - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - for (Map.Entry e : original.entrySet()) ew.put(e.getKey(), e.getValue()); - } - - enum TestStatus { - NOT_APPLICABLE, FAIL, PASS - } - - private static final Set IGNORE_TAGS = new HashSet<>(Arrays.asList(REPLICA, COLLECTION, SHARD, "strict")); - - static class ValidateInfo { - final Class type; - final Set vals; - final Number min; - final Number max; - - - ValidateInfo(Class type, Set vals, Number min, Number max) { - this.type = type; - this.vals = vals; - this.min = min; - if(min != null && !type.isInstance(min)) throw new RuntimeException("wrong min value type, expected: " + type.getName() + " actual: " + min.getClass().getName()); - this.max = max; - if(max != null && !type.isInstance(max)) throw new RuntimeException("wrong max value type, expected: " + type.getName() + " actual: " + max.getClass().getName()); - } - } - - - /** - * - * @param name name of the condition - * @param val value of the condition - * @param isRuleVal is this provided in the rule - * @return actual validated value - */ - public static Object validate(String name, Object val, boolean isRuleVal) { - if (val == null) return null; - ValidateInfo info = validatetypes.get(name); - if (info == null && name.startsWith(ImplicitSnitch.SYSPROP)) info = validatetypes.get("STRING"); - if (info == null) throw new RuntimeException("Unknown type :" + name); - if (info.type == Double.class) { - Double num = parseDouble(name, val); - if (isRuleVal) { - if (info.min != null) - if (Double.compare(num, (Double) info.min) == -1) - throw new RuntimeException(name + ": " + val + " must be greater than " + info.min); - if (info.max != null) - if (Double.compare(num, (Double) info.max) == 1) - throw new RuntimeException(name + ": " + val + " must be less than " + info.max); - } - return num; - } else if (info.type == Long.class) { - Long num = parseLong(name, val); - if (isRuleVal) { - if (info.min != null) - if (num < info.min.longValue()) - throw new RuntimeException(name + ": " + val + " must be greater than " + info.min); - if (info.max != null) - if (num > info.max.longValue()) - throw new RuntimeException(name + ": " + val + " must be less than " + info.max); - } - return num; - } else if (info.type == String.class) { - if (isRuleVal && info.vals != null && !info.vals.contains(val)) - throw new RuntimeException(name + ": " + val + " must be one of " + StrUtils.join(info.vals, ',')); - return val; - } else { - throw new RuntimeException("Invalid type "); - } - } - - public static Long parseLong(String name, Object val) { - if (val == null) return null; - if (val instanceof Long) return (Long) val; - Number num = null; - if (val instanceof String) { - try { - num = Long.parseLong(((String) val).trim()); - } catch (NumberFormatException e) { - try { - num = Double.parseDouble((String) val); - } catch (NumberFormatException e1) { - throw new RuntimeException(name + ": " + val + "not a valid number", e); - } - } - - } else if (val instanceof Number) { - num = (Number) val; - } - - if (num != null) { - return num.longValue(); - } - throw new RuntimeException(name + ": " + val + "not a valid number"); - } - - public static Double parseDouble(String name, Object val) { - if (val == null) return null; - if (val instanceof Double) return (Double) val; - Number num = null; - if (val instanceof String) { - try { - num = Double.parseDouble((String) val); - } catch (NumberFormatException e) { - throw new RuntimeException(name + ": " + val + "not a valid number", e); - } - - } else if (val instanceof Number) { - num = (Number) val; - } - - if (num != null) { - return num.doubleValue(); - } - throw new RuntimeException(name + ": " + val + "not a valid number"); - } - - private static final Map validatetypes = new HashMap<>(); - - static { - validatetypes.put("collection", new ValidateInfo(String.class, null, null, null)); - validatetypes.put("shard", new ValidateInfo(String.class, null, null, null)); - validatetypes.put("replica", new ValidateInfo(Long.class, null, 0L, null)); - validatetypes.put(ImplicitSnitch.PORT, new ValidateInfo(Long.class, null, 1L, 65535L)); - validatetypes.put(ImplicitSnitch.DISK, new ValidateInfo(Double.class, null, 0d, Double.MAX_VALUE)); - validatetypes.put(ImplicitSnitch.NODEROLE, new ValidateInfo(String.class, Collections.singleton("overseer"), null, null)); - validatetypes.put(ImplicitSnitch.CORES, new ValidateInfo(Long.class, null, 0L, Long.MAX_VALUE)); - validatetypes.put(ImplicitSnitch.SYSLOADAVG, new ValidateInfo(Double.class, null, 0d, 100d)); - validatetypes.put(ImplicitSnitch.HEAPUSAGE, new ValidateInfo(Double.class, null, 0d, null)); - validatetypes.put("NUMBER", new ValidateInfo(Long.class, null, 0L, Long.MAX_VALUE));//generic number validation - validatetypes.put("STRING", new ValidateInfo(String.class, null, null, null));//generic string validation - validatetypes.put("node", new ValidateInfo(String.class, null, null, null)); - for (String ip : ImplicitSnitch.IP_SNITCHES) validatetypes.put(ip, new ValidateInfo(Long.class, null, 0L, 255L)); - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/ClusterDataProvider.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/ClusterDataProvider.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/ClusterDataProvider.java deleted file mode 100644 index 710db87..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/ClusterDataProvider.java +++ /dev/null @@ -1,52 +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.cloud.autoscaling; - -import java.io.Closeable; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -public interface ClusterDataProvider extends Closeable { - /**Get the value of each tag for a given node - * - * @param node node name - * @param tags tag names - * @return a map of tag vs value - */ - Map getNodeValues(String node, Collection tags); - - /** - * Get the details of each replica in a node. It attempts to fetch as much details about - * the replica as mentioned in the keys list. It is not necessary to give al details - *

- * the format is {collection:shard :[{replicadetails}]} - */ - Map>> getReplicaInfo(String node, Collection keys); - - Collection getNodes(); - - /**Get the collection-specific policy - */ - String getPolicyNameByCollection(String coll); - - @Override - default void close() throws IOException { - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/MoveReplicaSuggester.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/MoveReplicaSuggester.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/MoveReplicaSuggester.java deleted file mode 100644 index 97aef51..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/MoveReplicaSuggester.java +++ /dev/null @@ -1,83 +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.cloud.autoscaling; - -import java.util.List; - -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.cloud.autoscaling.Clause.Violation; -import org.apache.solr.cloud.autoscaling.Policy.ReplicaInfo; -import org.apache.solr.cloud.autoscaling.Policy.Suggester; -import org.apache.solr.common.util.Pair; - -public class MoveReplicaSuggester extends Suggester { - - @Override - SolrRequest init() { - SolrRequest operation = tryEachNode(true); - if (operation == null) operation = tryEachNode(false); - return operation; - } - - SolrRequest tryEachNode(boolean strict) { - //iterate through elements and identify the least loaded - List leastSeriousViolation = null; - Integer targetNodeIndex = null; - Integer fromNodeIndex = null; - ReplicaInfo fromReplicaInfo = null; - for (Pair fromReplica : getValidReplicas(true, true, -1)) { - Row fromRow = fromReplica.second(); - ReplicaInfo replicaInfo = fromReplica.first(); - String coll = replicaInfo.collection; - String shard = replicaInfo.shard; - Pair pair = fromRow.removeReplica(coll, shard); - Row tmpRow = pair.first(); - if (tmpRow == null) { - //no such replica available - continue; - } - tmpRow.violations.clear(); - - final int i = getMatrix().indexOf(fromRow); - for (int j = getMatrix().size() - 1; j > i; j--) { - Row targetRow = getMatrix().get(j); - if (!isAllowed(targetRow.node, Hint.TARGET_NODE)) continue; - targetRow = targetRow.addReplica(coll, shard); - targetRow.violations.clear(); - List errs = testChangedMatrix(strict, getModifiedMatrix(getModifiedMatrix(getMatrix(), tmpRow, i), targetRow, j)); - if (!containsNewErrors(errs) && isLessSerious(errs, leastSeriousViolation)) { - leastSeriousViolation = errs; - targetNodeIndex = j; - fromNodeIndex = i; - fromReplicaInfo = replicaInfo; - } - } - } - if (targetNodeIndex != null && fromNodeIndex != null) { - getMatrix().set(fromNodeIndex, getMatrix().get(fromNodeIndex).removeReplica(fromReplicaInfo.collection, fromReplicaInfo.shard).first()); - getMatrix().set(targetNodeIndex, getMatrix().get(targetNodeIndex).addReplica(fromReplicaInfo.collection, fromReplicaInfo.shard)); - return new CollectionAdminRequest.MoveReplica( - fromReplicaInfo.collection, - fromReplicaInfo.name, - getMatrix().get(targetNodeIndex).node); - } - return null; - } - -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Operand.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Operand.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Operand.java deleted file mode 100644 index f961cac..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Operand.java +++ /dev/null @@ -1,123 +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.cloud.autoscaling; - -import java.util.Objects; - -import org.apache.solr.cloud.autoscaling.Clause.TestStatus; - -import static org.apache.solr.cloud.autoscaling.Clause.TestStatus.FAIL; -import static org.apache.solr.cloud.autoscaling.Clause.TestStatus.NOT_APPLICABLE; -import static org.apache.solr.cloud.autoscaling.Clause.TestStatus.PASS; -import static org.apache.solr.cloud.autoscaling.Policy.ANY; - - -public enum Operand { - WILDCARD(ANY, Integer.MAX_VALUE) { - @Override - public TestStatus match(Object ruleVal, Object testVal) { - return testVal == null ? NOT_APPLICABLE : PASS; - } - - }, - EQUAL("", 0) { - @Override - public int _delta(int expected, int actual) { - return expected - actual; - } - }, - NOT_EQUAL("!", 2) { - @Override - public TestStatus match(Object ruleVal, Object testVal) { - return super.match(ruleVal, testVal) == PASS ? FAIL : PASS; - } - - @Override - public int _delta(int expected, int actual) { - return expected - actual; - } - - }, - GREATER_THAN(">", 1) { - @Override - public TestStatus match(Object ruleVal, Object testVal) { - if (testVal == null) return NOT_APPLICABLE; - if (ruleVal instanceof Double) { - return Double.compare(Clause.parseDouble("", testVal), (Double) ruleVal) == 1 ? PASS : FAIL; - } - return getLong(testVal) > getLong(ruleVal) ? PASS: FAIL ; - } - - @Override - protected int _delta(int expected, int actual) { - return actual > expected ? 0 : (expected + 1) - actual; - } - }, - LESS_THAN("<", 2) { - @Override - public TestStatus match(Object ruleVal, Object testVal) { - if (testVal == null) return NOT_APPLICABLE; - if (ruleVal instanceof Double) { - return Double.compare(Clause.parseDouble("", testVal), (Double) ruleVal) == -1 ? PASS : FAIL; - } - return getLong(testVal) < getLong(ruleVal) ? PASS: FAIL ; - } - - @Override - protected int _delta(int expected, int actual) { - return actual < expected ? 0 : (expected ) - actual; - } - - }; - public final String operand; - final int priority; - - Operand(String val, int priority) { - this.operand = val; - this.priority = priority; - } - - public String toStr(Object expectedVal) { - return operand + expectedVal.toString(); - } - - public TestStatus match(Object ruleVal, Object testVal) { - return Objects.equals(ruleVal, testVal) ? PASS : FAIL; - } - - Long getLong(Object o) { - if (o instanceof Long) return (Long) o; - if(o instanceof Number ) return ((Number) o).longValue(); - return Long.parseLong(String.valueOf(o)); - - } - - public Integer delta(Object expected, Object actual) { - try { - Integer expectedInt = Integer.parseInt(String.valueOf(expected)); - Integer actualInt = Integer.parseInt(String.valueOf(actual)); - return _delta(expectedInt, actualInt); - } catch (Exception e) { - return null; - } - } - - protected int _delta(int expected, int actual) { - return 0; - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Policy.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Policy.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Policy.java deleted file mode 100644 index c86ccf9..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Policy.java +++ /dev/null @@ -1,519 +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.cloud.autoscaling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.cloud.autoscaling.Clause.Violation; -import org.apache.solr.common.IteratorWriter; -import org.apache.solr.common.MapWriter; -import org.apache.solr.common.params.CollectionParams.CollectionAction; -import org.apache.solr.common.util.Pair; -import org.apache.solr.common.util.StrUtils; -import org.apache.solr.common.util.Utils; - -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.stream.Collectors.toList; - -/*The class that reads, parses and applies policies specified in - * autoscaling.json - * - * Create one instance of this class per unique autoscaling.json. - * This is immutable and is thread-safe - * - * Create a fresh new session for each use - * - */ -public class Policy implements MapWriter { - public static final String POLICY = "policy"; - public static final String EACH = "#EACH"; - public static final String ANY = "#ANY"; - public static final String CLUSTER_POLICY = "cluster-policy"; - public static final String CLUSTER_PREFERENCE = "cluster-preferences"; - public static final Set GLOBAL_ONLY_TAGS = Collections.singleton("cores"); - final Map> policies = new HashMap<>(); - final List clusterPolicy; - final List clusterPreferences; - final List params; - - - public Policy(Map jsonMap) { - - clusterPreferences = ((List>) jsonMap.getOrDefault(CLUSTER_PREFERENCE, emptyList())).stream() - .map(Preference::new) - .collect(toList()); - for (int i = 0; i < clusterPreferences.size() - 1; i++) { - Preference preference = clusterPreferences.get(i); - preference.next = clusterPreferences.get(i + 1); - } - if (clusterPreferences.isEmpty()) { - clusterPreferences.add(new Preference((Map) Utils.fromJSONString("{minimize : cores, precision:1}"))); - } - SortedSet paramsOfInterest = new TreeSet<>(); - for (Preference preference : clusterPreferences) { - if (paramsOfInterest.contains(preference.name.name())) { - throw new RuntimeException(preference.name + " is repeated"); - } - paramsOfInterest.add(preference.name.toString()); - } - this.params = new ArrayList<>(paramsOfInterest); - - clusterPolicy = ((List>) jsonMap.getOrDefault(CLUSTER_POLICY, emptyList())).stream() - .map(Clause::new) - .filter(clause -> { - clause.addTags(params); - return true; - }) - .collect(Collectors.toList()); - - ((Map>>) jsonMap.getOrDefault("policies", emptyMap())).forEach((s, l1) -> - this.policies.put(s, l1.stream() - .map(Clause::new) - .filter(clause -> { - if (!clause.isPerCollectiontag()) - throw new RuntimeException(clause.globalTag.name + " is only allowed in 'cluster-policy'"); - clause.addTags(params); - return true; - }) - .sorted() - .collect(toList()))); - } - - public List getClusterPolicy() { - return clusterPolicy; - } - - public List getClusterPreferences() { - return clusterPreferences; - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - if (!policies.isEmpty()) { - ew.put("policies", (MapWriter) ew1 -> { - for (Map.Entry> e : policies.entrySet()) { - ew1.put(e.getKey(), e.getValue()); - } - }); - } - if (!clusterPreferences.isEmpty()) { - ew.put("preferences", (IteratorWriter) iw -> { - for (Preference p : clusterPreferences) iw.add(p); - }); - } - - } - - /*This stores the logical state of the system, given a policy and - * a cluster state. - * - */ - public class Session implements MapWriter { - final List nodes; - final ClusterDataProvider dataProvider; - final List matrix; - Set collections = new HashSet<>(); - List expandedClauses; - List violations = new ArrayList<>(); - - private Session(List nodes, ClusterDataProvider dataProvider, - List matrix, List expandedClauses) { - this.nodes = nodes; - this.dataProvider = dataProvider; - this.matrix = matrix; - this.expandedClauses = expandedClauses; - } - - Session(ClusterDataProvider dataProvider) { - this.nodes = new ArrayList<>(dataProvider.getNodes()); - this.dataProvider = dataProvider; - for (String node : nodes) { - collections.addAll(dataProvider.getReplicaInfo(node, Collections.emptyList()).keySet()); - } - - expandedClauses = clusterPolicy.stream() - .filter(clause -> !clause.isPerCollectiontag()) - .collect(Collectors.toList()); - - for (String c : collections) { - addClausesForCollection(dataProvider, c); - } - - Collections.sort(expandedClauses); - - matrix = new ArrayList<>(nodes.size()); - for (String node : nodes) matrix.add(new Row(node, params, dataProvider)); - applyRules(); - } - - private void addClausesForCollection(ClusterDataProvider dataProvider, String c) { - String p = dataProvider.getPolicyNameByCollection(c); - if (p != null) { - List perCollPolicy = policies.get(p); - if (perCollPolicy == null) - throw new RuntimeException(StrUtils.formatString("Policy for collection {0} is {1} . It does not exist", c, p)); - } - expandedClauses.addAll(mergePolicies(c, policies.getOrDefault(p, emptyList()), clusterPolicy)); - } - - Session copy() { - return new Session(nodes, dataProvider, getMatrixCopy(), expandedClauses); - } - - List getMatrixCopy() { - return matrix.stream() - .map(Row::copy) - .collect(Collectors.toList()); - } - - Policy getPolicy() { - return Policy.this; - - } - - /** - * Apply the preferences and conditions - */ - private void applyRules() { - if (!clusterPreferences.isEmpty()) { - //this is to set the approximate value according to the precision - ArrayList tmpMatrix = new ArrayList<>(matrix); - for (Preference p : clusterPreferences) { - Collections.sort(tmpMatrix, (r1, r2) -> p.compare(r1, r2, false)); - p.setApproxVal(tmpMatrix); - } - //approximate values are set now. Let's do recursive sorting - Collections.sort(matrix, (Row r1, Row r2) -> { - int result = clusterPreferences.get(0).compare(r1, r2, true); - if (result == 0) result = clusterPreferences.get(0).compare(r1, r2, false); - return result; - }); - } - - for (Clause clause : expandedClauses) { - List errs = clause.test(matrix); - violations.addAll(errs); - } - } - - public List getViolations() { - return violations; - } - - public Suggester getSuggester(CollectionAction action) { - Suggester op = ops.get(action).get(); - if (op == null) throw new UnsupportedOperationException(action.toString() + "is not supported"); - op._init(this); - return op; - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - for (int i = 0; i < matrix.size(); i++) { - Row row = matrix.get(i); - ew.put(row.node, row); - } - } - - @Override - public String toString() { - return Utils.toJSONString(toMap(new LinkedHashMap<>())); - } - - public List getSorted() { - return Collections.unmodifiableList(matrix); - } - } - - - public Session createSession(ClusterDataProvider dataProvider) { - return new Session(dataProvider); - } - - enum SortParam { - freedisk(0, Integer.MAX_VALUE), cores(0, Integer.MAX_VALUE), heapUsage(0, Integer.MAX_VALUE), sysLoadAvg(0, 100); - - public final int min,max; - - SortParam(int min, int max) { - this.min = min; - this.max = max; - } - - static SortParam get(String m) { - for (SortParam p : values()) if (p.name().equals(m)) return p; - throw new RuntimeException(StrUtils.formatString("Invalid sort {0} Sort must be on one of these {1}", m, Arrays.asList(values()))); - } - } - - enum Sort { - maximize(1), minimize(-1); - final int sortval; - - Sort(int i) { - sortval = i; - } - - static Sort get(Map m) { - if (m.containsKey(maximize.name()) && m.containsKey(minimize.name())) { - throw new RuntimeException("Cannot have both 'maximize' and 'minimize'"); - } - if (m.containsKey(maximize.name())) return maximize; - if (m.containsKey(minimize.name())) return minimize; - throw new RuntimeException("must have either 'maximize' or 'minimize'"); - } - } - - - public static class ReplicaInfo implements MapWriter { - final String name; - String core, collection, shard; - Map variables; - - public ReplicaInfo(String name, String coll, String shard, Map vals) { - this.name = name; - this.variables = vals; - this.collection = coll; - this.shard = shard; - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - ew.put(name, variables); - } - - public String getCore() { - return core; - } - - public String getCollection() { - return collection; - } - - public String getShard() { - return shard; - } - } - - - /* A suggester is capable of suggesting a collection operation - * given a particular session. Before it suggests a new operation, - * it ensures that , - * a) load is reduced on the most loaded node - * b) it causes no new violations - * - */ - public static abstract class Suggester { - protected final EnumMap hints = new EnumMap<>(Hint.class); - Policy.Session session; - SolrRequest operation; - protected List originalViolations = new ArrayList<>(); - private boolean isInitialized = false; - - private void _init(Session session) { - this.session = session.copy(); - } - - public Suggester hint(Hint hint, Object value) { - if (hint == Hint.TARGET_NODE || hint == Hint.SRC_NODE) { - ((Set) hints.computeIfAbsent(hint, h -> new HashSet<>())).add(value); - } else { - hints.put(hint, value); - } - return this; - } - - abstract SolrRequest init(); - - - public SolrRequest getOperation() { - if (!isInitialized) { - String coll = (String) hints.get(Hint.COLL); - String shard = (String) hints.get(Hint.SHARD); - // if this is not a known collection from the existing clusterstate, - // then add it - if (session.matrix.stream().noneMatch(row -> row.collectionVsShardVsReplicas.containsKey(coll))) { - session.addClausesForCollection(session.dataProvider, coll); - Collections.sort(session.expandedClauses); - } - if (coll != null) { - for (Row row : session.matrix) { - if (!row.collectionVsShardVsReplicas.containsKey(coll)) row.collectionVsShardVsReplicas.put(coll, new HashMap<>()); - if (shard != null) { - Map> shardInfo = row.collectionVsShardVsReplicas.get(coll); - if (!shardInfo.containsKey(shard)) shardInfo.put(shard, new ArrayList<>()); - } - } - } - session.applyRules(); - originalViolations.addAll(session.getViolations()); - this.operation = init(); - isInitialized = true; - } - return operation; - } - - public Session getSession() { - return session; - } - - List getMatrix() { - return session.matrix; - - } - - //check if the fresh set of violations is less serious than the last set of violations - boolean isLessSerious(List fresh, List old) { - if (old == null || fresh.size() < old.size()) return true; - if (fresh.size() == old.size()) { - for (int i = 0; i < fresh.size(); i++) { - Violation freshViolation = fresh.get(i); - Violation oldViolation = null; - for (Violation v : old) { - if (v.equals(freshViolation)) oldViolation = v; - } - if (oldViolation != null && freshViolation.isLessSerious(oldViolation)) return true; - } - } - return false; - } - - boolean containsNewErrors(List violations) { - for (Violation v : violations) { - int idx = originalViolations.indexOf(v); - if (idx < 0 || originalViolations.get(idx).isLessSerious(v)) return true; - } - return false; - } - - List> getValidReplicas(boolean sortDesc, boolean isSource, int until) { - List> allPossibleReplicas = new ArrayList<>(); - - if (sortDesc) { - if (until == -1) until = getMatrix().size(); - for (int i = 0; i < until; i++) addReplicaToList(getMatrix().get(i), isSource, allPossibleReplicas); - } else { - if (until == -1) until = 0; - for (int i = getMatrix().size() - 1; i >= until; i--) - addReplicaToList(getMatrix().get(i), isSource, allPossibleReplicas); - } - return allPossibleReplicas; - } - - void addReplicaToList(Row r, boolean isSource, List> replicaList) { - if (!isAllowed(r.node, isSource ? Hint.SRC_NODE : Hint.TARGET_NODE)) return; - for (Map.Entry>> e : r.collectionVsShardVsReplicas.entrySet()) { - if (!isAllowed(e.getKey(), Hint.COLL)) continue; - for (Map.Entry> shard : e.getValue().entrySet()) { - if (!isAllowed(e.getKey(), Hint.SHARD)) continue; - replicaList.add(new Pair<>(shard.getValue().get(0), r)); - } - } - } - - protected List testChangedMatrix(boolean strict, List rows) { - List errors = new ArrayList<>(); - for (Clause clause : session.expandedClauses) { - if (strict || clause.strict) { - List errs = clause.test(rows); - if (!errs.isEmpty()) { - errors.addAll(errs); - } - } - } - return errors; - } - - ArrayList getModifiedMatrix(List matrix, Row tmpRow, int i) { - ArrayList copy = new ArrayList<>(matrix); - copy.set(i, tmpRow); - return copy; - } - - protected boolean isAllowed(Object v, Hint hint) { - Object hintVal = hints.get(hint); - if (hint == Hint.TARGET_NODE || hint == Hint.SRC_NODE) { - Set set = (Set) hintVal; - return set == null || set.contains(v); - } else { - return hintVal == null || Objects.equals(v, hintVal); - } - } - - public enum Hint { - COLL, SHARD, SRC_NODE, TARGET_NODE - } - - - } - - static List mergePolicies(String coll, - List collPolicy, - List globalPolicy) { - - List merged = insertColl(coll, collPolicy); - List global = insertColl(coll, globalPolicy); - merged.addAll(global.stream() - .filter(clusterPolicyClause -> merged.stream().noneMatch(perCollPolicy -> perCollPolicy.doesOverride(clusterPolicyClause))) - .collect(Collectors.toList())); - return merged; - } - - /** - * Insert the collection name into the clauses where collection is not specified - */ - static List insertColl(String coll, Collection conditions) { - return conditions.stream() - .filter(Clause::isPerCollectiontag) - .map(clause -> { - Map copy = new LinkedHashMap<>(clause.original); - if (!copy.containsKey("collection")) copy.put("collection", coll); - return new Clause(copy); - }) - .filter(it -> (it.collection.isPass(coll))) - .collect(Collectors.toList()); - - } - - private static final Map> ops = new HashMap<>(); - - static { - ops.put(CollectionAction.ADDREPLICA, () -> new AddReplicaSuggester()); - ops.put(CollectionAction.MOVEREPLICA, () -> new MoveReplicaSuggester()); - } - - -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/PolicyHelper.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/PolicyHelper.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/PolicyHelper.java deleted file mode 100644 index 33d4b97..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/PolicyHelper.java +++ /dev/null @@ -1,96 +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.cloud.autoscaling; - - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.cloud.autoscaling.Policy.Suggester.Hint; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CoreAdminParams; -import org.apache.solr.common.util.Utils; - -import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA; - -public class PolicyHelper { - public static Map> getReplicaLocations(String collName, Map autoScalingJson, - ClusterDataProvider cdp, - Map optionalPolicyMapping, - List shardNames, - int repFactor, - List nodesList) { - Map> positionMapping = new HashMap<>(); - for (String shardName : shardNames) positionMapping.put(shardName, new ArrayList<>(repFactor)); - if (optionalPolicyMapping != null) { - final ClusterDataProvider delegate = cdp; - cdp = new ClusterDataProvider() { - @Override - public Map getNodeValues(String node, Collection tags) { - return delegate.getNodeValues(node, tags); - } - - @Override - public Map>> getReplicaInfo(String node, Collection keys) { - return delegate.getReplicaInfo(node, keys); - } - - @Override - public Collection getNodes() { - return delegate.getNodes(); - } - - @Override - public String getPolicyNameByCollection(String coll) { - return optionalPolicyMapping.containsKey(coll) ? - optionalPolicyMapping.get(coll) : - delegate.getPolicyNameByCollection(coll); - } - }; - - } - - - Policy policy = new Policy(autoScalingJson); - Policy.Session session = policy.createSession(cdp); - for (String shardName : shardNames) { - for (int i = 0; i < repFactor; i++) { - Policy.Suggester suggester = session.getSuggester(ADDREPLICA) - .hint(Hint.COLL, collName) - .hint(Hint.SHARD, shardName); - if (nodesList != null) { - for (String nodeName : nodesList) { - suggester = suggester.hint(Hint.TARGET_NODE, nodeName); - } - } - SolrRequest op = suggester.getOperation(); - if (op == null) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No node can satisfy the rules "+ Utils.toJSONString(Utils.getDeepCopy(session.expandedClauses, 4, true))); - } - session = suggester.getSession(); - positionMapping.get(shardName).add(op.getParams().get(CoreAdminParams.NODE)); - } - } - - return positionMapping; - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Preference.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Preference.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Preference.java deleted file mode 100644 index 0566d25..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Preference.java +++ /dev/null @@ -1,85 +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.cloud.autoscaling; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import org.apache.solr.common.MapWriter; -import org.apache.solr.common.util.StrUtils; -import org.apache.solr.common.util.Utils; - -class Preference implements MapWriter { - final Policy.SortParam name; - Integer precision; - final Policy.Sort sort; - Preference next; - public int idx; - private final Map original; - - Preference(Map m) { - this.original = Utils.getDeepCopy(m,3); - sort = Policy.Sort.get(m); - name = Policy.SortParam.get(m.get(sort.name()).toString()); - Object p = m.getOrDefault("precision", 0); - precision = p instanceof Number ? ((Number) p).intValue() : Integer.parseInt(p.toString()); - if (precision < 0) { - throw new RuntimeException("precision must be a positive value "); - } - if(precision< name.min || precision> name.max){ - throw new RuntimeException(StrUtils.formatString("invalid precision value {0} must lie between {1} and {1}", - precision, name.min, name.max ) ); - } - - } - - // there are 2 modes of compare. - // recursive, it uses the precision to tie & when there is a tie use the next preference to compare - // in non-recursive mode, precision is not taken into consideration and sort is done on actual value - int compare(Row r1, Row r2, boolean useApprox) { - Object o1 = useApprox ? r1.cells[idx].approxVal : r1.cells[idx].val; - Object o2 = useApprox ? r2.cells[idx].approxVal : r2.cells[idx].val; - int result = 0; - if (o1 instanceof Long && o2 instanceof Long) result = ((Long) o1).compareTo((Long) o2); - else if (o1 instanceof Double && o2 instanceof Double) result = ((Double) o1).compareTo((Double) o2); - else if (!o1.getClass().getName().equals(o2.getClass().getName())) { - throw new RuntimeException("Unable to compare " + o1 + " of type: " + o1.getClass().getName() + " from " + r1.cells[idx].toString() + " and " + o2 + " of type: " + o2.getClass().getName() + " from " + r2.cells[idx].toString()); - } - return result == 0 ? (next == null ? 0 : next.compare(r1, r2, useApprox)) : sort.sortval * result; - } - - //sets the new value according to precision in val_ - void setApproxVal(List tmpMatrix) { - Object prevVal = null; - for (Row row : tmpMatrix) { - prevVal = row.cells[idx].approxVal = - (prevVal == null || Double.compare(Math.abs(((Number) prevVal).doubleValue() - ((Number) row.cells[idx].val).doubleValue()), precision) > 0) ? - row.cells[idx].val : - prevVal; - } - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - for (Object o : original.entrySet()) { - Map.Entry e = (Map.Entry) o; - ew.put(String.valueOf(e.getKey()), e.getValue()); - } - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Row.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Row.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Row.java deleted file mode 100644 index f7ab5ca..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/Row.java +++ /dev/null @@ -1,116 +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.cloud.autoscaling; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.solr.common.IteratorWriter; -import org.apache.solr.common.MapWriter; -import org.apache.solr.common.util.Pair; -import org.apache.solr.common.util.Utils; -import org.apache.solr.cloud.autoscaling.Policy.ReplicaInfo; - -import static org.apache.solr.common.params.CoreAdminParams.NODE; - - -class Row implements MapWriter { - public final String node; - final Cell[] cells; - Map>> collectionVsShardVsReplicas; - List violations = new ArrayList<>(); - boolean anyValueMissing = false; - - Row(String node, List params, ClusterDataProvider dataProvider) { - collectionVsShardVsReplicas = dataProvider.getReplicaInfo(node, params); - if (collectionVsShardVsReplicas == null) collectionVsShardVsReplicas = new HashMap<>(); - this.node = node; - cells = new Cell[params.size()]; - Map vals = dataProvider.getNodeValues(node, params); - for (int i = 0; i < params.size(); i++) { - String s = params.get(i); - cells[i] = new Cell(i, s, Clause.validate(s,vals.get(s), false)); - if (NODE.equals(s)) cells[i].val = node; - if (cells[i].val == null) anyValueMissing = true; - } - } - - Row(String node, Cell[] cells, boolean anyValueMissing, Map>> collectionVsShardVsReplicas, List violations) { - this.node = node; - this.cells = new Cell[cells.length]; - for (int i = 0; i < this.cells.length; i++) { - this.cells[i] = cells[i].copy(); - - } - this.anyValueMissing = anyValueMissing; - this.collectionVsShardVsReplicas = collectionVsShardVsReplicas; - this.violations = violations; - } - - @Override - public void writeMap(EntryWriter ew) throws IOException { - ew.put(node, (IteratorWriter) iw -> { - iw.add((MapWriter) e -> e.put("replicas", collectionVsShardVsReplicas)); - for (Cell cell : cells) iw.add(cell); - }); - } - - Row copy() { - return new Row(node, cells, anyValueMissing, Utils.getDeepCopy(collectionVsShardVsReplicas, 3), new ArrayList<>(violations)); - } - - Object getVal(String name) { - for (Cell cell : cells) if (cell.name.equals(name)) return cell.val; - return null; - } - - @Override - public String toString() { - return node; - } - - // this adds a replica to the replica info - Row addReplica(String coll, String shard) { - Row row = copy(); - Map> c = row.collectionVsShardVsReplicas.computeIfAbsent(coll, k -> new HashMap<>()); - List replicas = c.computeIfAbsent(shard, k -> new ArrayList<>()); - replicas.add(new ReplicaInfo("" + new Random().nextInt(1000) + 1000, coll, shard, new HashMap<>())); - for (Cell cell : row.cells) { - if (cell.name.equals("cores")) cell.val = ((Number) cell.val).longValue() + 1; - } - return row; - - } - - Pair removeReplica(String coll, String shard) { - Row row = copy(); - Map> c = row.collectionVsShardVsReplicas.get(coll); - if (c == null) return null; - List s = c.get(shard); - if (s == null || s.isEmpty()) return null; - for (Cell cell : row.cells) { - if (cell.name.equals("cores")) cell.val = ((Number) cell.val).longValue() -1; - } - return new Pair(row, s.remove(0)); - - } -} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/package-info.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/package-info.java b/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/package-info.java deleted file mode 100644 index 472b1ac..0000000 --- a/solr/solrj/src/java/org/apache/solr/cloud/autoscaling/package-info.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. - */ - -/** - * Common classes for autoscaling parsing filtering nodes and sorting - */ - -package org.apache.solr.cloud.autoscaling; - http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java b/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java index 5dc4ebb..b1d6ee2 100644 --- a/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java +++ b/solr/solrj/src/java/org/apache/solr/common/cloud/DocCollection.java @@ -28,7 +28,7 @@ import java.util.Objects; import java.util.Set; import java.util.function.BiConsumer; -import org.apache.solr.cloud.autoscaling.Policy; +import org.apache.solr.client.solrj.cloud.autoscaling.Policy; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.noggit.JSONUtil; http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/13a3ae29/solr/solrj/src/test/org/apache/solr/cloud/autoscaling/TestPolicy.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/test/org/apache/solr/cloud/autoscaling/TestPolicy.java b/solr/solrj/src/test/org/apache/solr/cloud/autoscaling/TestPolicy.java index 8c296b9..a036c8d 100644 --- a/solr/solrj/src/test/org/apache/solr/cloud/autoscaling/TestPolicy.java +++ b/solr/solrj/src/test/org/apache/solr/cloud/autoscaling/TestPolicy.java @@ -31,9 +31,16 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.cloud.autoscaling.Cell; +import org.apache.solr.client.solrj.cloud.autoscaling.Clause; +import org.apache.solr.client.solrj.cloud.autoscaling.ClusterDataProvider; +import org.apache.solr.client.solrj.cloud.autoscaling.Operand; +import org.apache.solr.client.solrj.cloud.autoscaling.Policy; +import org.apache.solr.client.solrj.cloud.autoscaling.PolicyHelper; +import org.apache.solr.client.solrj.cloud.autoscaling.Row; +import org.apache.solr.client.solrj.cloud.autoscaling.Clause.Violation; +import org.apache.solr.client.solrj.cloud.autoscaling.Policy.Suggester.Hint; import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.cloud.autoscaling.Clause.Violation; -import org.apache.solr.cloud.autoscaling.Policy.Suggester.Hint; import org.apache.solr.common.params.CollectionParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.Utils; @@ -219,7 +226,7 @@ public class TestPolicy extends SolrTestCaseJ4 { " }" + "}"); Policy policy = new Policy(map); - List clauses = Policy.mergePolicies("mycoll", policy.policies.get("policy1"), policy.clusterPolicy); + List clauses = Policy.mergePolicies("mycoll", policy.getPolicies().get("policy1"), policy.getClusterPolicy()); Collections.sort(clauses); assertEquals(clauses.size(), 4); assertEquals("1", String.valueOf(clauses.get(0).original.get("replica"))); @@ -240,8 +247,8 @@ public class TestPolicy extends SolrTestCaseJ4 { Policy p = new Policy((Map) Utils.fromJSONString(rules)); List clauses = new ArrayList<>(p.getClusterPolicy()); Collections.sort(clauses); - assertEquals("nodeRole", clauses.get(1).tag.name); - assertEquals("sysprop.rack", clauses.get(0).tag.name); + assertEquals("nodeRole", clauses.get(1).tag.getName()); + assertEquals("sysprop.rack", clauses.get(0).tag.getName()); } public void testRules() throws IOException { @@ -275,9 +282,9 @@ public class TestPolicy extends SolrTestCaseJ4 { List violations = session.getViolations(); assertEquals(3, violations.size()); - assertTrue(violations.stream().anyMatch(violation -> "node3".equals(violation.getClause().tag.val))); - assertTrue(violations.stream().anyMatch(violation -> "nodeRole".equals(violation.getClause().tag.name))); - assertTrue(violations.stream().anyMatch(violation -> (violation.getClause().replica.op == Operand.LESS_THAN && "node".equals(violation.getClause().tag.name)))); + assertTrue(violations.stream().anyMatch(violation -> "node3".equals(violation.getClause().tag.getValue()))); + assertTrue(violations.stream().anyMatch(violation -> "nodeRole".equals(violation.getClause().tag.getName()))); + assertTrue(violations.stream().anyMatch(violation -> (violation.getClause().replica.getOperand() == Operand.LESS_THAN && "node".equals(violation.getClause().tag.getName())))); Policy.Suggester suggester = session.getSuggester(ADDREPLICA) .hint(Hint.COLL, "gettingstarted")