Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOLR-17269: Do not publish synthetic solr core (of Coordinator node) to ZK #2438

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
39 changes: 9 additions & 30 deletions solr/core/src/java/org/apache/solr/cloud/ZkConfigSetService.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,9 @@
import java.util.Map;
import java.util.Objects;
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.ZkMaintenanceUtils;
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.common.util.Utils;
import org.apache.solr.core.ConfigSetProperties;
Expand Down Expand Up @@ -71,36 +68,18 @@ public ZkConfigSetService(SolrZkClient 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(),
zkController.getCoreContainer().getConfigSetService());
}
} 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);
// Currently, cd.getConfigSet() is always null. Except that it's explicitly set by
// {@link org.apache.solr.core.SyntheticSolrCore}.
// Should we consider setting it for all cores as a part of CoreDescriptor creation/loading
// process?
if (cd.getConfigSet() == null) {
String configSetName =
zkController.getClusterState().getCollection(cd.getCollectionName()).getConfigName();
cd.setConfigSet(configSetName);
}

// The configSet is read from ZK and populated. Ignore CD's pre-existing configSet; only
// populated in standalone
String configSetName = zkController.getClusterState().getCollection(colName).getConfigName();
cd.setConfigSet(configSetName);

return new ZkSolrResourceLoader(
cd.getInstanceDir(), configSetName, parentLoader.getClassLoader(), zkController);
cd.getInstanceDir(), cd.getConfigSet(), parentLoader.getClassLoader(), zkController);
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion solr/core/src/java/org/apache/solr/core/SolrCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ private SolrCore(
}

/** Set UpdateLog to buffer updates if the slice is in construction. */
private void bufferUpdatesIfConstructing(CoreDescriptor coreDescriptor) {
protected void bufferUpdatesIfConstructing(CoreDescriptor coreDescriptor) {

if (coreContainer != null && coreContainer.isZooKeeperAware()) {
if (reqHandlers.get("/get") == null) {
Expand Down
75 changes: 75 additions & 0 deletions solr/core/src/java/org/apache/solr/core/SyntheticSolrCore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.core;

import java.nio.file.Path;
import java.util.Map;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.rest.RestManager;

/**
* A synthetic core that is created only in memory and not registered against Zookeeper.
*
* <p>This is only used in Coordinator node to support a subset of SolrCore functionalities required
* by Coordinator operations such as aggregating and writing out response and providing configset
* info.
*
* <p>There should only be one instance of SyntheticSolrCore per configset
*/
public class SyntheticSolrCore extends SolrCore {
public SyntheticSolrCore(CoreContainer coreContainer, CoreDescriptor cd, ConfigSet configSet) {
super(coreContainer, cd, configSet);
}

public static SyntheticSolrCore createAndRegisterCore(
CoreContainer coreContainer, String syntheticCoreName, String configSetName) {
Map<String, String> coreProps = Map.of(CoreAdminParams.COLLECTION, syntheticCoreName);

CoreDescriptor syntheticCoreDescriptor =
new CoreDescriptor(
syntheticCoreName,
Path.of(coreContainer.getSolrHome(), syntheticCoreName),
coreProps,
coreContainer.getContainerProperties(),
coreContainer.getZkController());
syntheticCoreDescriptor.setConfigSet(configSetName);
ConfigSet coreConfig =
coreContainer.getConfigSetService().loadConfigSet(syntheticCoreDescriptor);
syntheticCoreDescriptor.setConfigSetTrusted(coreConfig.isTrusted());
SyntheticSolrCore syntheticCore =
new SyntheticSolrCore(coreContainer, syntheticCoreDescriptor, coreConfig);
coreContainer.registerCore(syntheticCoreDescriptor, syntheticCore, false, false);

return syntheticCore;
}

@Override
protected void bufferUpdatesIfConstructing(CoreDescriptor coreDescriptor) {
// no updates to SyntheticSolrCore
}

@Override
protected RestManager initRestManager() throws SolrException {
// returns an initialized RestManager. As init routines requires reading configname of the
// core's collection from ZK
// which synthetic core is not registered in ZK.
// We do not expect RestManager ops on Coordinator Nodes
Comment on lines +69 to +72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrap.

Glad to see this kind of comment. Hmm; I wonder if it's actually prevented? Like how does this overall feature (which I confess knowing nothing about) actually prevent these cores from being used for anything except the one thing it needs to exist for -- distributed-search? e.g. maybe. no handlers should be loaded except those extending SearchHandler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, this special core is restricted by the getCoreByCollection of CoordinatorHttpSolrCall/CoordinatorV2HttpSolrCall which only accept suffix /select.

return new RestManager();
}
}