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; package org.apache.solr.handler;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.client.solrj.request.beans.CreateConfigInfo;
import org.apache.solr.cloud.OverseerConfigSetMessageHandler; import org.apache.solr.cloud.OverseerConfigSetMessageHandler;
import org.apache.solr.cluster.placement.impl.PlacementPluginConfigImpl; 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.SolrException;
import org.apache.solr.common.annotation.JsonProperty; import org.apache.solr.common.annotation.JsonProperty;
import org.apache.solr.common.cloud.ClusterProperties; import org.apache.solr.common.cloud.ClusterProperties;
@ -212,22 +212,18 @@ public class ClusterAPI {
@Command(name = "set-placement-plugin") @Command(name = "set-placement-plugin")
public void setPlacementPlugin(PayloadObj<Map<String, Object>> obj) { public void setPlacementPlugin(PayloadObj<Map<String, Object>> obj) {
Map<String, Object> placementPluginConfig = obj.getDataMap(); Map<String, Object> placementPluginConfig = obj.getDataMap();
if(placementPluginConfig.isEmpty()) placementPluginConfig = null;
ClusterProperties clusterProperties = new ClusterProperties(getCoreContainer().getZkController().getZkClient()); ClusterProperties clusterProperties = new ClusterProperties(getCoreContainer().getZkController().getZkClient());
// When the json contains { "set-placement-plugin" : null }, the map is empty, not null. // 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... // 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)"); throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Must contain " + PlacementPluginConfigImpl.CONFIG_CLASS + " attribute (or be null)");
} }
try { try {
// Need to reset to null first otherwise the mappings in placementPluginConfig are added to existing ones clusterProperties.update(placementPluginConfig == null?
// in /clusterprops.json rather than replacing them. If removing the config, that's all we do. null:
clusterProperties.setClusterProperties( new MapWriterMap(placementPluginConfig),
Collections.singletonMap(PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY, null)); PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY);
if (!unset) {
clusterProperties.setClusterProperties(
Collections.singletonMap(PlacementPluginConfigImpl.PLACEMENT_PLUGIN_CONFIG_KEY, placementPluginConfig));
}
} catch (Exception e) { } catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", 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.io.IOException;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CollectionAdminParams; import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.util.Utils; 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. * 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. * This method will modify the given map and return the same object. Remove this method in Solr 9.