blob: 37e7c27752bc090ae0c2f85b556a1fca22a0587a [file] [log] [blame]
/*
* 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.cloud.autoscaling;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MOVEREPLICA;
/**
*
* @deprecated to be removed in Solr 9.0 (see SOLR-14656)
*/
public class CoresVariable extends VariableBase {
public CoresVariable(Type type) {
super(type);
}
@Override
public Object validate(String name, Object val, boolean isRuleVal) {
return VariableBase.getOperandAdjustedValue(super.validate(name, val, isRuleVal), val);
}
public boolean addViolatingReplicas(Violation.Ctx ctx) {
for (Row row : ctx.allRows) {
if (row.node.equals(ctx.currentViolation.node)) {
row.forEachReplica(replicaInfo -> ctx.currentViolation
.addReplica(new Violation.ReplicaInfoAndErr(replicaInfo)
.withDelta(ctx.currentViolation.replicaCountDelta)));
}
}
return true;
}
@Override
public void getSuggestions(Suggestion.Ctx ctx) {
if (ctx.violation == null || ctx.violation.replicaCountDelta == 0) return;
if (ctx.violation.replicaCountDelta > 0) {//there are more replicas than necessary
for (int i = 0; i < Math.abs(ctx.violation.replicaCountDelta); i++) {
if (!ctx.needMore()) return;
Suggester suggester = ctx.session.getSuggester(MOVEREPLICA)
.hint(Suggester.Hint.SRC_NODE, ctx.violation.node);
if (ctx.addSuggestion(suggester) == null) break;
}
}
}
@Override
public void projectAddReplica(Cell cell, ReplicaInfo ri, Consumer<Row.OperationInfo> ops, boolean strictMode) {
cell.val = cell.val == null ? 0 : ((Number) cell.val).doubleValue() + 1;
}
@Override
public void projectRemoveReplica(Cell cell, ReplicaInfo ri, Consumer<Row.OperationInfo> opCollector) {
cell.val = cell.val == null ? 0 : ((Number) cell.val).doubleValue() - 1;
}
@Override
public Object computeValue(Policy.Session session, Condition condition, String collection, String shard, String node) {
if (condition.computedType == ComputedType.EQUAL) {
AtomicInteger liveNodes = new AtomicInteger(0);
int coresCount = getTotalCores(session, liveNodes);
int numBuckets = condition.clause.tag.op == Operand.IN ?
((Collection) condition.clause.tag.val).size() :
liveNodes.get();
return numBuckets == 0 || coresCount == 0 ? 0d : (double) coresCount / (double) numBuckets;
} else if (condition.computedType == ComputedType.PERCENT) {
return ComputedType.PERCENT.compute(getTotalCores(session, new AtomicInteger()), condition);
} else {
throw new IllegalArgumentException("Invalid computed type in " + condition);
}
}
static final String TOTALCORES = CoresVariable.class.getSimpleName() + ".totalcores";
private int getTotalCores(Policy.Session session, AtomicInteger liveNodes) {
int coresCount = 0;
for (Row row : session.matrix) {
if (!row.isLive) continue;
liveNodes.incrementAndGet();
Integer res = row.computeCacheIfAbsent(TOTALCORES, o -> {
int[] result = new int[1];
row.forEachReplica(replicaInfo -> result[0]++);
return result[0];
});
if (res != null)
coresCount += res;
}
return coresCount;
}
@Override
public String postValidate(Condition condition) {
Condition nodeTag = condition.getClause().getTag();
if (nodeTag.varType != Type.NODE) return "'cores' attribute can only be used with 'node' attribute";
if (condition.computedType == ComputedType.EQUAL) {
if (nodeTag.name.equals("node") && (nodeTag.op == Operand.WILDCARD || nodeTag.op == Operand.IN)) {
return null;
} else {
return "cores: '#EQUAL' can be used only with node: '#ANY', node :[....]";
}
} else {
return ReplicaVariable.checkNonEqualOp(condition);
}
}
@Override
public Operand getOperand(Operand expected, Object strVal, ComputedType computedType) {
return ReplicaVariable.checkForRangeOperand(expected, strVal, computedType);
}
}