NazerkeBS commented on a change in pull request #23: URL: https://github.com/apache/solr/pull/23#discussion_r599577580
########## File path: solr/core/src/java/org/apache/solr/cloud/ZkConfigSetService.java ########## @@ -0,0 +1,319 @@ +/* + * 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; + +import java.io.File; +import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Pattern; + +import org.apache.solr.client.solrj.cloud.SolrCloudManager; +import org.apache.solr.cloud.api.collections.CreateCollectionCmd; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.cloud.SolrZkClient; +import org.apache.solr.common.cloud.ZkStateReader; +import org.apache.solr.common.cloud.ZooKeeperException; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.core.ConfigSetProperties; +import org.apache.solr.core.ConfigSetService; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.core.CoreDescriptor; +import org.apache.solr.core.SolrConfig; +import org.apache.solr.core.SolrResourceLoader; +import org.apache.solr.handler.admin.ConfigSetsHandler; +import org.apache.solr.servlet.SolrDispatchFilter; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SolrCloud Zookeeper ConfigSetService impl. + */ +public class ZkConfigSetService extends ConfigSetService { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final ZkController zkController; + private final SolrZkClient zkClient; + /** ZkNode where named configs are stored */ + public static final String CONFIGS_ZKNODE = "/configs"; + public static final String UPLOAD_FILENAME_EXCLUDE_REGEX = "^\\..*$"; + public static final Pattern UPLOAD_FILENAME_EXCLUDE_PATTERN = Pattern.compile(UPLOAD_FILENAME_EXCLUDE_REGEX); + + public ZkConfigSetService(CoreContainer cc) { + super(cc.getResourceLoader(), cc.getConfig().hasSchemaCache()); + this.zkController = cc.getZkController(); + this.zkClient = cc.getZkController().getZkClient(); + try { + bootstrapDefaultConfigSet(); + } catch (IOException e) { + log.error("Error in bootstrapping default config"); + } + } + + /** This is for ZkCLI and some tests */ + public ZkConfigSetService(SolrZkClient zkClient) { + super(null, false); + this.zkController = null; + this.zkClient = zkClient; + } + + @Override + public SolrResourceLoader createCoreResourceLoader(CoreDescriptor cd) { + final String colName = cd.getCollectionName(); + + // For back compat with cores that can create collections without the collections API + try { + if (!zkClient.exists(ZkStateReader.COLLECTIONS_ZKNODE + "/" + colName, true)) { + // TODO remove this functionality or maybe move to a CLI mechanism + log.warn("Auto-creating collection (in ZK) from core descriptor (on disk). This feature may go away!"); + CreateCollectionCmd.createCollectionZkNode(zkController.getSolrCloudManager().getDistribStateManager(), colName, cd.getCloudDescriptor().getParams()); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "Interrupted auto-creating collection", e); + } catch (KeeperException e) { + throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "Failure auto-creating collection", e); + } + + // The configSet is read from ZK and populated. Ignore CD's pre-existing configSet; only populated in standalone + final String configSetName; + try { + configSetName = zkController.getZkStateReader().readConfigName(colName); + cd.setConfigSet(configSetName); + } catch (KeeperException ex) { + throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "Trouble resolving configSet for collection " + colName + ": " + ex.getMessage()); + } + + return new ZkSolrResourceLoader(cd.getInstanceDir(), configSetName, parentLoader.getClassLoader(), zkController); + } + + @Override + @SuppressWarnings({"rawtypes"}) + protected NamedList loadConfigSetFlags(CoreDescriptor cd, SolrResourceLoader loader) { + try { + return ConfigSetProperties.readFromResourceLoader(loader, "."); + } catch (Exception ex) { + log.debug("No configSet flags", ex); + return null; + } + } + + @Override + protected Long getCurrentSchemaModificationVersion(String configSet, SolrConfig solrConfig, String schemaFile) { + String zkPath = CONFIGS_ZKNODE + "/" + configSet + "/" + schemaFile; + Stat stat; + try { + stat = zkClient.exists(zkPath, null, true); + } catch (KeeperException e) { + log.warn("Unexpected exception when getting modification time of {}", zkPath, e); + return null; // debatable; we'll see an error soon if there's a real problem + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); + } + if (stat == null) { // not found + return null; + } + return (long) stat.getVersion(); + } + + @Override + public String configSetName(CoreDescriptor cd) { + return "configset " + cd.getConfigSet(); + } + + @Override + public boolean checkConfigExists(String configName) throws IOException { + try { + return zkClient.exists(CONFIGS_ZKNODE + "/" + configName, true); + } catch (KeeperException | InterruptedException e) { + throw new IOException("Error checking whether config exists", + SolrZkClient.checkInterrupted(e)); + } + } + + @Override + public void deleteConfigDir(String configName) throws IOException { + try { + zkClient.clean(CONFIGS_ZKNODE + "/" + configName); + } catch (KeeperException | InterruptedException e) { + throw new IOException("Error checking whether config exists", + SolrZkClient.checkInterrupted(e)); + } + } + + @Override + public void copyConfigDir(String fromConfig, String toConfig) throws IOException { + copyConfigDir(fromConfig, toConfig, null); + } + + @Override + public void copyConfigDir(String fromConfig, String toConfig, Set<String> copiedToZkPaths) throws IOException { + String fromConfigPath = CONFIGS_ZKNODE + "/" + fromConfig; + String toConfigPath = CONFIGS_ZKNODE + "/" + toConfig; + try { + copyData(copiedToZkPaths, fromConfigPath, toConfigPath); + } catch (KeeperException | InterruptedException e) { + throw new IOException("Error config " + fromConfig + " to " + toConfig, + SolrZkClient.checkInterrupted(e)); + } + copyConfigDirFromZk(fromConfigPath, toConfigPath, copiedToZkPaths); + } + + @Override + public void uploadConfigDir(Path dir, String configName) throws IOException { + zkClient.uploadToZK(dir, CONFIGS_ZKNODE + "/" + configName, ZkConfigSetService.UPLOAD_FILENAME_EXCLUDE_PATTERN); + } + + @Override + public void downloadConfigDir(String configName, Path dir) throws IOException { + zkClient.downloadFromZK(CONFIGS_ZKNODE + "/" + configName, dir); + } + + @Override + public List<String> listConfigs() throws IOException { + try { + return zkClient.getChildren(CONFIGS_ZKNODE, null, true); + } catch (KeeperException.NoNodeException e) { + return Collections.emptyList(); + } catch (KeeperException | InterruptedException e) { + throw new IOException("Error listing configs", SolrZkClient.checkInterrupted(e)); + } + } + + private void bootstrapDefaultConfigSet() throws IOException { Review comment: We call this method during initialisation of ZkConfigSetService -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected]
