SOLR-14613: Avoid multiple ZK write

This commit is contained in:
noblepaul 2020-09-24 17:26:41 +10:00
parent 26bb6415d1
commit cafa449769
2 changed files with 24 additions and 11 deletions

View File

@ -17,7 +17,6 @@
package org.apache.solr.handler;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -28,6 +27,7 @@ import org.apache.solr.client.solrj.request.beans.ClusterPropInfo;
import org.apache.solr.client.solrj.request.beans.CreateConfigInfo;
import org.apache.solr.cloud.OverseerConfigSetMessageHandler;
import org.apache.solr.cluster.placement.impl.PlacementPluginConfigImpl;
import org.apache.solr.common.MapWriterMap;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.annotation.JsonProperty;
import org.apache.solr.common.cloud.ClusterProperties;
@ -212,22 +212,18 @@ public class ClusterAPI {
@Command(name = "set-placement-plugin")
public void setPlacementPlugin(PayloadObj<Map<String, Object>> obj) {
Map<String, Object> placementPluginConfig = obj.getDataMap();
if(placementPluginConfig.isEmpty()) placementPluginConfig = null;
ClusterProperties clusterProperties = new ClusterProperties(getCoreContainer().getZkController().getZkClient());
// When the json contains { "set-placement-plugin" : null }, the map is empty, not null.
final boolean unset = placementPluginConfig.isEmpty();
// Very basic sanity check. Real validation will be done when the config is used...
if (!unset && !placementPluginConfig.containsKey(PlacementPluginConfigImpl.CONFIG_CLASS)) {
if (!(placementPluginConfig == null) && !placementPluginConfig.containsKey(PlacementPluginConfigImpl.CONFIG_CLASS)) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Must contain " + PlacementPluginConfigImpl.CONFIG_CLASS + " attribute (or be null)");
}
try {
// Need to reset to null first otherwise the mappings in placementPluginConfig are added to existing ones
// in /clusterprops.json rather than replacing them. If removing the config, that's all we do.
clusterProperties.setClusterProperties(
Collections.singletonMap(PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY, null));
if (!unset) {
clusterProperties.setClusterProperties(
Collections.singletonMap(PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY, placementPluginConfig));
}
clusterProperties.update(placementPluginConfig == null?
null:
new MapWriterMap(placementPluginConfig),
PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY);
} catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e);
}

View File

@ -19,11 +19,13 @@ package org.apache.solr.common.cloud;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.util.Utils;
@ -116,6 +118,21 @@ public class ClusterProperties {
});
}
/**Set this object at the json path
*
* @param obj the Object to be set
* @param path the json path
*/
@SuppressWarnings("unchecked")
public void update(MapWriter obj, String... path) throws KeeperException, InterruptedException{
client.atomicUpdate(ZkStateReader.CLUSTER_PROPS, bytes -> {
Map<String, Object> zkJson = (Map<String, Object>) Utils.fromJSON(bytes);
Utils.setObjectByPath(zkJson, Arrays.asList(path), obj);
return Utils.toJSON(zkJson);
});
}
/**
* See SOLR-12827 for background. We auto convert any "collectionDefaults" keys to "defaults/collection" format.
* This method will modify the given map and return the same object. Remove this method in Solr 9.