blob: 0fd19ac21db2d592b97cda5d97d195ae373d340f [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.cloud.api.collections;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.cloud.autoscaling.AutoScalingConfig;
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.Suggester;
import org.apache.solr.client.solrj.request.V2Request;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP;
import static org.apache.solr.common.params.AutoScalingParams.NODE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MOVEREPLICA;
import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
public class UtilizeNodeCmd implements OverseerCollectionMessageHandler.Cmd {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final OverseerCollectionMessageHandler ocmh;
public UtilizeNodeCmd(OverseerCollectionMessageHandler ocmh) {
this.ocmh = ocmh;
}
@Override
public void call(ClusterState state, ZkNodeProps message, @SuppressWarnings({"rawtypes"})NamedList results) throws Exception {
ocmh.checkRequired(message, NODE);
String nodeName = message.getStr(NODE);
String async = message.getStr(ASYNC);
AutoScalingConfig autoScalingConfig = ocmh.overseer.getSolrCloudManager().getDistribStateManager().getAutoScalingConfig();
//first look for any violation that may use this replica
List<ZkNodeProps> requests = new ArrayList<>();
//first look for suggestions if any
List<Suggester.SuggestionInfo> suggestions = PolicyHelper.getSuggestions(autoScalingConfig, ocmh.overseer.getSolrCloudManager());
for (Suggester.SuggestionInfo suggestionInfo : suggestions) {
if (log.isInfoEnabled()) {
log.info("op: {}", suggestionInfo.getOperation());
}
String coll = null;
List<String> pieces = StrUtils.splitSmart(suggestionInfo.getOperation().getPath(), '/');
if (pieces.size() > 1) {
coll = pieces.get(2);
} else {
continue;
}
log.info("coll: {}", coll);
if (suggestionInfo.getOperation() instanceof V2Request) {
String targetNode = (String) Utils.getObjectByPath(suggestionInfo.getOperation(), true, "command/move-replica/targetNode");
if (Objects.equals(targetNode, nodeName)) {
String replica = (String) Utils.getObjectByPath(suggestionInfo.getOperation(), true, "command/move-replica/replica");
requests.add(new ZkNodeProps(COLLECTION_PROP, coll,
CollectionParams.TARGET_NODE, targetNode,
ASYNC, async,
REPLICA_PROP, replica));
}
}
}
executeAll(requests);
PolicyHelper.SessionWrapper sessionWrapper = PolicyHelper.getSession(ocmh.overseer.getSolrCloudManager());
Policy.Session session = sessionWrapper.get();
Suggester initialsuggester = session.getSuggester(MOVEREPLICA)
.hint(Suggester.Hint.TARGET_NODE, nodeName);
Suggester suggester = null;
for (; ; ) {
suggester = session.getSuggester(MOVEREPLICA)
.hint(Suggester.Hint.TARGET_NODE, nodeName);
@SuppressWarnings({"rawtypes"})
SolrRequest request = suggester.getSuggestion();
if (requests.size() > 10) {
log.info("too_many_suggestions");
PolicyHelper.logState(ocmh.overseer.getSolrCloudManager(), initialsuggester);
break;
}
log.info("SUGGESTION: {}", request);
if (request == null) break;
session = suggester.getSession();
requests.add(new ZkNodeProps(COLLECTION_PROP, request.getParams().get(COLLECTION_PROP),
CollectionParams.TARGET_NODE, request.getParams().get(CollectionParams.TARGET_NODE),
REPLICA_PROP, request.getParams().get(REPLICA_PROP),
ASYNC, request.getParams().get(ASYNC)));
}
if (log.isInfoEnabled()) {
log.info("total_suggestions: {}", requests.size());
}
if (requests.size() == 0) {
PolicyHelper.logState(ocmh.overseer.getSolrCloudManager(), initialsuggester);
}
sessionWrapper.returnSession(session);
try {
executeAll(requests);
} finally {
sessionWrapper.release();
}
}
private void executeAll(List<ZkNodeProps> requests) throws Exception {
if (requests.isEmpty()) return;
for (ZkNodeProps props : requests) {
@SuppressWarnings({"rawtypes"})
NamedList result = new NamedList();
ocmh.commandMap.get(MOVEREPLICA)
.call(ocmh.overseer.getSolrCloudManager().getClusterStateProvider().getClusterState(),
props,
result);
}
requests.clear();
}
}