mirror of https://github.com/apache/lucene.git
SOLR-10278: suggesters implemented
This commit is contained in:
parent
bec41550db
commit
e3a46732bb
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.recipe;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.solr.common.util.Utils;
|
||||||
|
import org.apache.solr.recipe.RuleSorter.BaseSuggester;
|
||||||
|
import org.apache.solr.recipe.RuleSorter.Session;
|
||||||
|
|
||||||
|
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
|
||||||
|
import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
|
||||||
|
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA;
|
||||||
|
import static org.apache.solr.common.params.CoreAdminParams.NODE;
|
||||||
|
|
||||||
|
class AddReplicaSuggester extends BaseSuggester {
|
||||||
|
|
||||||
|
AddReplicaSuggester(String coll, String shard, Session session) {
|
||||||
|
super(coll, shard, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map get() {
|
||||||
|
Map operation = tryEachNode(true);
|
||||||
|
if (operation == null) operation = tryEachNode(false);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map tryEachNode(boolean strict) {
|
||||||
|
//iterate through elements and identify the least loaded
|
||||||
|
for (int i = matrix.size() - 1; i >= 0; i--) {
|
||||||
|
Row row = matrix.get(i);
|
||||||
|
row = row.addReplica(coll, shard);
|
||||||
|
row.violations.clear();
|
||||||
|
for (Clause clause : session.getRuleSorter().clauses) {
|
||||||
|
if (strict || clause.strict) clause.test(row);
|
||||||
|
}
|
||||||
|
if (row.violations.isEmpty()) {
|
||||||
|
return Utils.makeMap("operation", ADDREPLICA,
|
||||||
|
COLLECTION_PROP, coll,
|
||||||
|
SHARD_ID_PROP, shard,
|
||||||
|
NODE, row.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.recipe;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.solr.common.MapWriter;
|
||||||
|
|
||||||
|
class Cell implements MapWriter {
|
||||||
|
final int index;
|
||||||
|
final String name;
|
||||||
|
Object val, val_;
|
||||||
|
|
||||||
|
Cell(int index, String name, Object val) {
|
||||||
|
this.index = index;
|
||||||
|
this.name = name;
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell(int index, String name, Object val, Object val_) {
|
||||||
|
this.index = index;
|
||||||
|
this.name = name;
|
||||||
|
this.val = val;
|
||||||
|
this.val_ = val_;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeMap(EntryWriter ew) throws IOException {
|
||||||
|
ew.put(name, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cell copy() {
|
||||||
|
return new Cell(index, name, val, val_);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,10 +26,8 @@ import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.apache.solr.common.MapWriter;
|
import org.apache.solr.common.MapWriter;
|
||||||
import org.apache.solr.common.params.CommonParams;
|
|
||||||
import org.apache.solr.common.util.Utils;
|
import org.apache.solr.common.util.Utils;
|
||||||
import org.apache.solr.recipe.RuleSorter.ReplicaStat;
|
import org.apache.solr.recipe.RuleSorter.ReplicaStat;
|
||||||
import org.apache.solr.recipe.RuleSorter.Row;
|
|
||||||
|
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
import static org.apache.solr.common.params.CoreAdminParams.COLLECTION;
|
import static org.apache.solr.common.params.CoreAdminParams.COLLECTION;
|
||||||
|
@ -46,7 +44,7 @@ import static org.apache.solr.recipe.Operand.WILDCARD;
|
||||||
import static org.apache.solr.recipe.RuleSorter.ANY;
|
import static org.apache.solr.recipe.RuleSorter.ANY;
|
||||||
import static org.apache.solr.recipe.RuleSorter.EACH;
|
import static org.apache.solr.recipe.RuleSorter.EACH;
|
||||||
|
|
||||||
|
// a set of conditions in a policy
|
||||||
public class Clause implements MapWriter {
|
public class Clause implements MapWriter {
|
||||||
Map<String, Object> original;
|
Map<String, Object> original;
|
||||||
Condition collection, shard, replica, tag;
|
Condition collection, shard, replica, tag;
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.recipe;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.solr.common.util.Pair;
|
||||||
|
import org.apache.solr.common.util.Utils;
|
||||||
|
import org.apache.solr.recipe.RuleSorter.BaseSuggester;
|
||||||
|
import org.apache.solr.recipe.RuleSorter.Session;
|
||||||
|
|
||||||
|
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
|
||||||
|
import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
|
||||||
|
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MOVEREPLICA;
|
||||||
|
import static org.apache.solr.common.params.CoreAdminParams.NODE;
|
||||||
|
import static org.apache.solr.common.params.CoreAdminParams.REPLICA;
|
||||||
|
|
||||||
|
public class MoveReplicaSuggester extends BaseSuggester{
|
||||||
|
|
||||||
|
MoveReplicaSuggester(String coll, String shard, Session session) {
|
||||||
|
super(coll, shard, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map get() {
|
||||||
|
Map operation = tryEachNode(true);
|
||||||
|
if (operation == null) operation = tryEachNode(false);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map tryEachNode(boolean strict) {
|
||||||
|
//iterate through elements and identify the least loaded
|
||||||
|
for (int i = 0; i < matrix.size(); i++) {
|
||||||
|
Row fromRow = matrix.get(i);
|
||||||
|
Pair<Row, RuleSorter.ReplicaStat> pair = fromRow.removeReplica(coll, shard);
|
||||||
|
fromRow = pair.first();
|
||||||
|
if(fromRow == null){
|
||||||
|
//no such replica available
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Clause clause : session.getRuleSorter().clauses) {
|
||||||
|
if (strict || clause.strict) clause.test(fromRow);
|
||||||
|
}
|
||||||
|
if (fromRow.violations.isEmpty()) {
|
||||||
|
for (int j = matrix.size() - 1; j > i; i--) {
|
||||||
|
Row targetRow = matrix.get(i);
|
||||||
|
targetRow = targetRow.addReplica(coll, shard);
|
||||||
|
for (Clause clause : session.getRuleSorter().clauses) {
|
||||||
|
if (strict || clause.strict) clause.test(targetRow);
|
||||||
|
}
|
||||||
|
if (targetRow.violations.isEmpty()) {
|
||||||
|
return Utils.makeMap("operation", MOVEREPLICA.toLower(),
|
||||||
|
COLLECTION_PROP, coll,
|
||||||
|
SHARD_ID_PROP, shard,
|
||||||
|
NODE, fromRow.node,
|
||||||
|
REPLICA, pair.second().name,
|
||||||
|
"target", targetRow.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ class Preference {
|
||||||
// there are 2 modes of compare.
|
// there are 2 modes of compare.
|
||||||
// recursive, it uses the precision to tie & when there is a tie use the next preference to 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
|
// in non-recursive mode, precision is not taken into consideration and sort is done on actual value
|
||||||
int compare(RuleSorter.Row r1, RuleSorter.Row r2, boolean recursive) {
|
int compare(Row r1, Row r2, boolean recursive) {
|
||||||
Object o1 = recursive ? r1.cells[idx].val_ : r1.cells[idx].val;
|
Object o1 = recursive ? r1.cells[idx].val_ : r1.cells[idx].val;
|
||||||
Object o2 = recursive ? r2.cells[idx].val_ : r2.cells[idx].val;
|
Object o2 = recursive ? r2.cells[idx].val_ : r2.cells[idx].val;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@ -50,9 +50,9 @@ class Preference {
|
||||||
}
|
}
|
||||||
|
|
||||||
//sets the new value according to precision in val_
|
//sets the new value according to precision in val_
|
||||||
void setApproxVal(List<RuleSorter.Row> tmpMatrix) {
|
void setApproxVal(List<Row> tmpMatrix) {
|
||||||
Object prevVal = null;
|
Object prevVal = null;
|
||||||
for (RuleSorter.Row row : tmpMatrix) {
|
for (Row row : tmpMatrix) {
|
||||||
prevVal = row.cells[idx].val_ =
|
prevVal = row.cells[idx].val_ =
|
||||||
prevVal == null || Math.abs(((Number) prevVal).longValue() - ((Number) row.cells[idx].val).longValue()) > precision ?
|
prevVal == null || Math.abs(((Number) prevVal).longValue() - ((Number) row.cells[idx].val).longValue()) > precision ?
|
||||||
row.cells[idx].val :
|
row.cells[idx].val :
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* 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.recipe;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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 static org.apache.solr.common.params.CoreAdminParams.NODE;
|
||||||
|
|
||||||
|
|
||||||
|
class Row implements MapWriter {
|
||||||
|
public final String node;
|
||||||
|
final Cell[] cells;
|
||||||
|
Map<String, Map<String, List<RuleSorter.ReplicaStat>>> replicaInfo;
|
||||||
|
List<Clause> violations = new ArrayList<>();
|
||||||
|
boolean anyValueMissing = false;
|
||||||
|
|
||||||
|
Row(String node, List<String> params, RuleSorter.NodeValueProvider snitch) {
|
||||||
|
replicaInfo = snitch.getReplicaCounts(node, params);
|
||||||
|
if (replicaInfo == null) replicaInfo = Collections.emptyMap();
|
||||||
|
this.node = node;
|
||||||
|
cells = new Cell[params.size()];
|
||||||
|
Map<String, Object> vals = snitch.getValues(node, params);
|
||||||
|
for (int i = 0; i < params.size(); i++) {
|
||||||
|
String s = params.get(i);
|
||||||
|
cells[i] = new Cell(i, s, vals.get(s));
|
||||||
|
if (NODE.equals(s)) cells[i].val = node;
|
||||||
|
if (cells[i].val == null) anyValueMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(String node, Cell[] cells, boolean anyValueMissing, Map<String, Map<String, List<RuleSorter.ReplicaStat>>> replicaInfo, List<Clause> 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.replicaInfo = replicaInfo;
|
||||||
|
this.violations = violations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeMap(EntryWriter ew) throws IOException {
|
||||||
|
ew.put(node, (IteratorWriter) iw -> {
|
||||||
|
iw.add((MapWriter) e -> e.put("replicas", replicaInfo));
|
||||||
|
for (Cell cell : cells) iw.add(cell);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row copy() {
|
||||||
|
return new Row(node, cells, anyValueMissing, Utils.getDeepCopy(replicaInfo, 2), new ArrayList<>(violations));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getVal(String name) {
|
||||||
|
for (Cell cell : cells) if (cell.name.equals(name)) return cell.val;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Row addReplica(String coll, String shard) {
|
||||||
|
Row row = copy();
|
||||||
|
Map<String, List<RuleSorter.ReplicaStat>> c = row.replicaInfo.get(coll);
|
||||||
|
if (c == null) row.replicaInfo.put(coll, c = new HashMap<>());
|
||||||
|
List<RuleSorter.ReplicaStat> s = c.get(shard);
|
||||||
|
if (s == null) c.put(shard, s = new ArrayList<>());
|
||||||
|
return row;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Row, RuleSorter.ReplicaStat> removeReplica(String coll, String shard) {
|
||||||
|
Row row = copy();
|
||||||
|
Map<String, List<RuleSorter.ReplicaStat>> c = row.replicaInfo.get(coll);
|
||||||
|
if(c == null) return null;
|
||||||
|
List<RuleSorter.ReplicaStat> s = c.get(shard);
|
||||||
|
if (s == null || s.isEmpty()) return null;
|
||||||
|
return new Pair(row,s.remove(0));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -29,18 +30,12 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.solr.common.IteratorWriter;
|
|
||||||
import org.apache.solr.common.MapWriter;
|
import org.apache.solr.common.MapWriter;
|
||||||
import org.apache.solr.common.params.CollectionParams.CollectionAction;
|
import org.apache.solr.common.params.CollectionParams.CollectionAction;
|
||||||
import org.apache.solr.common.util.Utils;
|
import org.apache.solr.common.util.Utils;
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA;
|
|
||||||
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETEREPLICA;
|
|
||||||
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MOVEREPLICA;
|
|
||||||
import static org.apache.solr.common.params.CollectionParams.CollectionAction.SPLITSHARD;
|
|
||||||
import static org.apache.solr.common.params.CoreAdminParams.NODE;
|
|
||||||
|
|
||||||
public class RuleSorter {
|
public class RuleSorter {
|
||||||
public static final String EACH = "#EACH";
|
public static final String EACH = "#EACH";
|
||||||
|
@ -91,6 +86,10 @@ public class RuleSorter {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuleSorter getRuleSorter() {
|
||||||
|
return RuleSorter.this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**Apply the preferences and conditions
|
/**Apply the preferences and conditions
|
||||||
*/
|
*/
|
||||||
|
@ -122,10 +121,10 @@ public class RuleSorter {
|
||||||
.collect(Collectors.toMap(r -> r.node, r -> r.violations));
|
.collect(Collectors.toMap(r -> r.node, r -> r.violations));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operation suggest(CollectionAction action) {
|
public Map suggest(CollectionAction action, String collection, String shard) {
|
||||||
if (!supportedActions.contains(action))
|
Suggester op = ops.get(action);
|
||||||
throw new UnsupportedOperationException(action.toString() + "is not supported");
|
if (op == null) throw new UnsupportedOperationException(action.toString() + "is not supported");
|
||||||
return null;
|
return op.suggest(collection, shard, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,7 +150,7 @@ public class RuleSorter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<Map<String, Object>> getListOfMap(String key, Map<String, Object> jsonMap) {
|
static List<Map<String, Object>> getListOfMap(String key, Map<String, Object> jsonMap) {
|
||||||
Object o = jsonMap.get(key);
|
Object o = jsonMap.get(key);
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
if (!(o instanceof List)) o = singletonList(o);
|
if (!(o instanceof List)) o = singletonList(o);
|
||||||
|
@ -190,96 +189,6 @@ public class RuleSorter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Row implements MapWriter {
|
|
||||||
public final String node;
|
|
||||||
final Cell[] cells;
|
|
||||||
Map<String, Map<String, List<ReplicaStat>>> replicaInfo;
|
|
||||||
List<Clause> violations = new ArrayList<>();
|
|
||||||
boolean anyValueMissing = false;
|
|
||||||
|
|
||||||
Row(String node, List<String> params, NodeValueProvider snitch) {
|
|
||||||
replicaInfo = snitch.getReplicaCounts(node, params);
|
|
||||||
if (replicaInfo == null) replicaInfo = Collections.emptyMap();
|
|
||||||
this.node = node;
|
|
||||||
cells = new Cell[params.size()];
|
|
||||||
Map<String, Object> vals = snitch.getValues(node, params);
|
|
||||||
for (int i = 0; i < params.size(); i++) {
|
|
||||||
String s = params.get(i);
|
|
||||||
cells[i] = new Cell(i, s, vals.get(s));
|
|
||||||
if (NODE.equals(s)) cells[i].val = node;
|
|
||||||
if (cells[i].val == null) anyValueMissing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(String node, Cell[] cells, boolean anyValueMissing, Map<String, Map<String, List<ReplicaStat>>> replicaInfo) {
|
|
||||||
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.replicaInfo = replicaInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeMap(EntryWriter ew) throws IOException {
|
|
||||||
ew.put(node, (IteratorWriter) iw -> {
|
|
||||||
iw.add((MapWriter) e -> e.put("replicas", replicaInfo));
|
|
||||||
for (Cell cell : cells) iw.add(cell);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Row copy() {
|
|
||||||
return new Row(node, cells, anyValueMissing, replicaInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getVal(String name) {
|
|
||||||
for (Cell cell : cells) if (cell.name.equals(name)) return cell.val;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Cell implements MapWriter {
|
|
||||||
final int index;
|
|
||||||
final String name;
|
|
||||||
Object val, val_;
|
|
||||||
|
|
||||||
Cell(int index, String name, Object val) {
|
|
||||||
this.index = index;
|
|
||||||
this.name = name;
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cell(int index, String name, Object val, Object val_) {
|
|
||||||
this.index = index;
|
|
||||||
this.name = name;
|
|
||||||
this.val = val;
|
|
||||||
this.val_ = val_;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeMap(EntryWriter ew) throws IOException {
|
|
||||||
ew.put(name, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cell copy() {
|
|
||||||
return new Cell(index, name, val, val_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Operation {
|
|
||||||
CollectionAction action;
|
|
||||||
String node, collection, shard, replica;
|
|
||||||
String targetNode;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static class ReplicaStat implements MapWriter {
|
static class ReplicaStat implements MapWriter {
|
||||||
final String name;
|
final String name;
|
||||||
|
@ -304,12 +213,39 @@ public class RuleSorter {
|
||||||
* Get the details of each replica in a node. It attempts to fetch as much details about
|
* 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
|
* the replica as mentioned in the keys list
|
||||||
* <p>
|
* <p>
|
||||||
* the format is {collection:shard :[{replicaetails}]}
|
* the format is {collection:shard :[{replicadetails}]}
|
||||||
*/
|
*/
|
||||||
Map<String, Map<String, List<ReplicaStat>>> getReplicaCounts(String node, Collection<String> keys);
|
Map<String, Map<String, List<ReplicaStat>>> getReplicaCounts(String node, Collection<String> keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Set<CollectionAction> supportedActions = new HashSet<>(Arrays.asList(ADDREPLICA, DELETEREPLICA, MOVEREPLICA, SPLITSHARD));
|
interface Suggester {
|
||||||
|
Map<String, Object> suggest(String coll, String shard, Session session);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BaseSuggester {
|
||||||
|
final String coll;
|
||||||
|
final String shard;
|
||||||
|
final RuleSorter.Session session;
|
||||||
|
List<Row> matrix;
|
||||||
|
|
||||||
|
BaseSuggester(String coll, String shard, RuleSorter.Session session) {
|
||||||
|
this.coll = coll;
|
||||||
|
this.shard = shard;
|
||||||
|
this.session = session;
|
||||||
|
matrix = session.getMatrixCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<CollectionAction, Suggester> ops = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ops.put(CollectionAction.ADDREPLICA, (coll, shard, session) -> new AddReplicaSuggester(coll, shard, session).get());
|
||||||
|
ops.put(CollectionAction.MOVEREPLICA, (coll, shard, session) -> new MoveReplicaSuggester(coll, shard, session).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ public class TestRuleSorter extends SolrTestCaseJ4 {
|
||||||
session = ruleSorter.createSession(Arrays.asList("node1", "node2", "node3", "node4"), snitch);
|
session = ruleSorter.createSession(Arrays.asList("node1", "node2", "node3", "node4"), snitch);
|
||||||
|
|
||||||
session.applyRules();
|
session.applyRules();
|
||||||
List<RuleSorter.Row> l = session.getSorted();
|
List<Row> l = session.getSorted();
|
||||||
assertEquals("node1",l.get(0).node);
|
assertEquals("node1",l.get(0).node);
|
||||||
assertEquals("node3",l.get(1).node);
|
assertEquals("node3",l.get(1).node);
|
||||||
assertEquals("node4",l.get(2).node);
|
assertEquals("node4",l.get(2).node);
|
||||||
|
|
Loading…
Reference in New Issue