Skip to content

Commit

Permalink
SOLR-9280 - make nodeName a configurable parameter in solr.xml
Browse files Browse the repository at this point in the history
  • Loading branch information
kelaban committed Jul 8, 2016
1 parent be8d56a commit b1de1f9
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,36 @@
*/
package org.apache.solr.cloud;

import static org.apache.solr.cloud.Assign.getNodesForNewReplicas;
import static org.apache.solr.common.cloud.DocCollection.SNITCH;
import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.CORE_NAME_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.CORE_NODE_NAME_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.ELECTION_NODE_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
import static org.apache.solr.common.cloud.ZkStateReader.PROPERTY_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.PROPERTY_VALUE_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REJOIN_AT_HEAD_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICAPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDROLE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.BALANCESHARDUNIQUE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETEREPLICAPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MIGRATESTATEFORMAT;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.REMOVEROLE;
import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
import static org.apache.solr.common.params.CommonParams.NAME;
import static org.apache.solr.common.util.StrUtils.formatString;
import static org.apache.solr.common.util.Utils.makeMap;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.net.URI;
Expand Down Expand Up @@ -98,36 +128,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.solr.cloud.Assign.getNodesForNewReplicas;
import static org.apache.solr.common.cloud.DocCollection.SNITCH;
import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.CORE_NAME_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.CORE_NODE_NAME_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.ELECTION_NODE_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
import static org.apache.solr.common.cloud.ZkStateReader.PROPERTY_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.PROPERTY_VALUE_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REJOIN_AT_HEAD_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICA;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDREPLICAPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDROLE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.BALANCESHARDUNIQUE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CREATESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETEREPLICAPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETESHARD;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.MIGRATESTATEFORMAT;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.REMOVEROLE;
import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
import static org.apache.solr.common.params.CommonParams.NAME;
import static org.apache.solr.common.util.StrUtils.formatString;
import static org.apache.solr.common.util.Utils.makeMap;

/**
* A {@link OverseerMessageHandler} that handles Collections API related
* overseer messages.
Expand Down Expand Up @@ -630,17 +630,20 @@ private void deleteReplica(ClusterState clusterState, ZkNodeProps message, Named
requestMap = new HashMap<>(1, 1.0f);
}

ModifiableSolrParams params = new ModifiableSolrParams();
params.add(CoreAdminParams.ACTION, CoreAdminAction.UNLOAD.toString());
params.add(CoreAdminParams.CORE, core);

params.set(CoreAdminParams.DELETE_INDEX, message.getBool(CoreAdminParams.DELETE_INDEX, true));
params.set(CoreAdminParams.DELETE_INSTANCE_DIR, message.getBool(CoreAdminParams.DELETE_INSTANCE_DIR, true));
params.set(CoreAdminParams.DELETE_DATA_DIR, message.getBool(CoreAdminParams.DELETE_DATA_DIR, true));

sendShardRequest(replica.getNodeName(), params, shardHandler, asyncId, requestMap);
//Don't send the request if the node isn't up. Getting the baseUrl will fail if there is no liveNode
if(zkStateReader.getClusterState().liveNodesContain(replica.getNodeName())) {
ModifiableSolrParams params = new ModifiableSolrParams();
params.add(CoreAdminParams.ACTION, CoreAdminAction.UNLOAD.toString());
params.add(CoreAdminParams.CORE, core);

params.set(CoreAdminParams.DELETE_INDEX, message.getBool(CoreAdminParams.DELETE_INDEX, true));
params.set(CoreAdminParams.DELETE_INSTANCE_DIR, message.getBool(CoreAdminParams.DELETE_INSTANCE_DIR, true));
params.set(CoreAdminParams.DELETE_DATA_DIR, message.getBool(CoreAdminParams.DELETE_DATA_DIR, true));

processResponses(results, shardHandler, false, null, asyncId, requestMap);
sendShardRequest(replica.getNodeName(), params, shardHandler, asyncId, requestMap);
processResponses(results, shardHandler, false, null, asyncId, requestMap);
}


//check if the core unload removed the corenode zk entry
if (waitForCoreNodeGone(collectionName, shard, replicaName, 5000)) return;
Expand Down
25 changes: 17 additions & 8 deletions solr/core/src/java/org/apache/solr/cloud/ZkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ public boolean equals(Object obj) {

private final int localHostPort; // example: 54065
private final String hostName; // example: 127.0.0.1
private final String nodeName; // example: 127.0.0.1:54065_solr
private final String genericNodeName; // example: 127.0.0.1:54065_solr
private final String nodeName; //set in solr.xml or genericNodeName as default
private String baseURL; // example: http://127.0.0.1:54065/solr

private final CloudConfig cloudConfig;
Expand Down Expand Up @@ -270,8 +271,11 @@ public ZkController(final CoreContainer cc, String zkServerAddress, int zkClient
this.zkServerAddress = zkServerAddress;
this.localHostPort = cloudConfig.getSolrHostPort();
this.hostName = normalizeHostName(cloudConfig.getHost());
this.nodeName = generateNodeName(this.hostName, Integer.toString(this.localHostPort), localHostContext);
MDCLoggingContext.setNode(nodeName);
this.genericNodeName = generateNodeName(this.hostName, Integer.toString(this.localHostPort), localHostContext);
String nodeName = cloudConfig.getNodeName();
this.nodeName = nodeName == null || nodeName.isEmpty() ? this.genericNodeName : nodeName;
String loggingContext = this.nodeName == this.genericNodeName ? this.genericNodeName : String.format("%s[%s]", this.nodeName, this.genericNodeName);
MDCLoggingContext.setNode(loggingContext);
this.leaderVoteWait = cloudConfig.getLeaderVoteWait();
this.leaderConflictResolveWait = cloudConfig.getLeaderConflictResolveWait();

Expand Down Expand Up @@ -670,7 +674,7 @@ private void init(CurrentCoreDescriptorProvider registerOnReconnect) {
try {
createClusterZkNodes(zkClient);
zkStateReader.createClusterStateWatchersAndUpdate();
this.baseURL = zkStateReader.getBaseUrlForNodeName(this.nodeName);
this.baseURL = zkStateReader.getBaseUrlFromGenericNodeName(this.genericNodeName);

checkForExistingEphemeralNode();

Expand Down Expand Up @@ -737,9 +741,10 @@ private void checkForExistingEphemeralNode() throws KeeperException, Interrupted
}

boolean deleted = deletedLatch.await(zkClient.getSolrZooKeeper().getSessionTimeout() * 2, TimeUnit.MILLISECONDS);

if (!deleted) {
throw new SolrException(ErrorCode.SERVER_ERROR, "A previous ephemeral live node still exists. " +
"Solr cannot continue. Please ensure that no other Solr process using the same port is running already.");
throw new SolrException(ErrorCode.SERVER_ERROR, "An ephemeral live node still exists named '" + this.nodeName +
"'. Solr cannot continue. Please ensure that no other Solr process using the same port is running already or configured with the same nodeName in solr.xml");
}
}

Expand Down Expand Up @@ -818,7 +823,11 @@ private void createEphemeralLiveNode() throws KeeperException,
String nodeName = getNodeName();
String nodePath = ZkStateReader.LIVE_NODES_ZKNODE + "/" + nodeName;
log.info("Register node as live in ZooKeeper:" + nodePath);
zkClient.makePath(nodePath, CreateMode.EPHEMERAL, true);
zkClient.makePath(nodePath, getGenericNodeName().getBytes(), CreateMode.EPHEMERAL, true);
}

private String getGenericNodeName() {
return genericNodeName;
}

public String getNodeName() {
Expand Down Expand Up @@ -2099,7 +2108,7 @@ public void updateLeaderInitiatedRecoveryState(String collection, String shardId
stateObj.put(ZkStateReader.STATE_PROP, state.toString());
// only update the createdBy value if it's not set
if (stateObj.get("createdByNodeName") == null) {
stateObj.put("createdByNodeName", this.nodeName);
stateObj.put("createdByNodeName", this.genericNodeName);
}
if (stateObj.get("createdByCoreNodeName") == null && leaderCoreNodeName != null) {
stateObj.put("createdByCoreNodeName", leaderCoreNodeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,27 @@ public class ImplicitSnitch extends Snitch implements CoreAdminHandler.Invocable


@Override
public void getTags(String solrNode, Set<String> requestedTags, SnitchContext ctx) {
if (requestedTags.contains(NODE)) ctx.getTags().put(NODE, solrNode);
public void getTags(String solrNodeName, Set<String> requestedTags, SnitchContext ctx) {
String baseUrl = ctx.getSnitchInfo().getCoreContainer().getZkStateReader().getBaseUrlForNodeName(solrNodeName);
if (requestedTags.contains(NODE)) ctx.getTags().put(NODE, solrNodeName);
if (requestedTags.contains(HOST)) {
Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
Matcher hostAndPortMatcher = hostAndPortPattern.matcher(baseUrl);
if (hostAndPortMatcher.find()) ctx.getTags().put(HOST, hostAndPortMatcher.group(1));
}
if (requestedTags.contains(PORT)) {
Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
Matcher hostAndPortMatcher = hostAndPortPattern.matcher(baseUrl);
if (hostAndPortMatcher.find()) ctx.getTags().put(PORT, hostAndPortMatcher.group(2));
}
if (requestedTags.contains(ROLE)) fillRole(solrNode, ctx);
addIpTags(solrNode, requestedTags, ctx);
if (requestedTags.contains(ROLE)) fillRole(solrNodeName, ctx);
addIpTags(baseUrl, requestedTags, ctx);

ModifiableSolrParams params = new ModifiableSolrParams();
if (requestedTags.contains(CORES)) params.add(CORES, "1");
if (requestedTags.contains(DISK)) params.add(DISK, "1");
for (String tag : requestedTags) {
if (tag.startsWith(SYSPROP)) params.add(SYSPROP, tag.substring(SYSPROP.length()));
}
if (params.size() > 0) ctx.invokeRemote(solrNode, params, ImplicitSnitch.class.getName(), null);
if (params.size() > 0) ctx.invokeRemote(solrNodeName, params, ImplicitSnitch.class.getName(), null);
}

private void fillRole(String solrNode, SnitchContext ctx) {
Expand Down
17 changes: 15 additions & 2 deletions solr/core/src/java/org/apache/solr/core/CloudConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ public class CloudConfig {
private final int createCollectionWaitTimeTillActive;

private final boolean createCollectionCheckLeaderActive;

private final String nodeName;

CloudConfig(String zkHost, int zkClientTimeout, int hostPort, String hostName, String hostContext, boolean useGenericCoreNames,
int leaderVoteWait, int leaderConflictResolveWait, int autoReplicaFailoverWaitAfterExpiration,
int autoReplicaFailoverWorkLoopDelay, int autoReplicaFailoverBadNodeExpiration, String zkCredentialsProviderClass,
String zkACLProviderClass, int createCollectionWaitTimeTillActive, boolean createCollectionCheckLeaderActive) {
String zkACLProviderClass, int createCollectionWaitTimeTillActive, boolean createCollectionCheckLeaderActive, String nodeName) {
this.zkHost = zkHost;
this.zkClientTimeout = zkClientTimeout;
this.hostPort = hostPort;
Expand All @@ -69,6 +71,7 @@ public class CloudConfig {
this.zkACLProviderClass = zkACLProviderClass;
this.createCollectionWaitTimeTillActive = createCollectionWaitTimeTillActive;
this.createCollectionCheckLeaderActive = createCollectionCheckLeaderActive;
this.nodeName = nodeName;

if (this.hostPort == -1)
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "'hostPort' must be configured to run SolrCloud");
Expand Down Expand Up @@ -135,6 +138,10 @@ public int getCreateCollectionWaitTimeTillActive() {
public boolean isCreateCollectionCheckLeaderActive() {
return createCollectionCheckLeaderActive;
}

public String getNodeName() {
return nodeName;
}

public static class CloudConfigBuilder {

Expand Down Expand Up @@ -164,6 +171,7 @@ public static class CloudConfigBuilder {
private String zkACLProviderClass;
private int createCollectionWaitTimeTillActive = DEFAULT_CREATE_COLLECTION_ACTIVE_WAIT;
private boolean createCollectionCheckLeaderActive = DEFAULT_CREATE_COLLECTION_CHECK_LEADER_ACTIVE;
private String nodeName = null;

public CloudConfigBuilder(String hostName, int hostPort) {
this(hostName, hostPort, null);
Expand Down Expand Up @@ -235,11 +243,16 @@ public CloudConfigBuilder setCreateCollectionCheckLeaderActive(boolean createCol
return this;
}

public CloudConfigBuilder setNodeName(String nodeName) {
this.nodeName = nodeName;
return this;
}

public CloudConfig build() {
return new CloudConfig(zkHost, zkClientTimeout, hostPort, hostName, hostContext, useGenericCoreNames, leaderVoteWait,
leaderConflictResolveWait, autoReplicaFailoverWaitAfterExpiration, autoReplicaFailoverWorkLoopDelay,
autoReplicaFailoverBadNodeExpiration, zkCredentialsProviderClass, zkACLProviderClass, createCollectionWaitTimeTillActive,
createCollectionCheckLeaderActive);
createCollectionCheckLeaderActive, nodeName);
}
}
}
4 changes: 4 additions & 0 deletions solr/core/src/java/org/apache/solr/core/CoreContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,10 @@ public ZkController getZkController() {
return zkSys.getZkController();
}

public ZkStateReader getZkStateReader() {
return isZooKeeperAware() ? zkSys.getZkController().getZkStateReader() : null;
}

public NodeConfig getConfig() {
return cfg;
}
Expand Down
3 changes: 3 additions & 0 deletions solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ private static CloudConfig fillSolrCloudSection(NamedList<Object> nl) {
case "genericCoreNodeNames":
builder.setUseGenericCoreNames(Boolean.parseBoolean(value));
break;
case "nodeName":
builder.setNodeName(value);
break;
case "zkACLProvider":
builder.setZkACLProviderClass(value);
break;
Expand Down
1 change: 1 addition & 0 deletions solr/core/src/test-files/solr/solr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<str name="hostContext">${hostContext:solr}</str>
<int name="zkClientTimeout">${solr.zkclienttimeout:30000}</int>
<bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
<str name="nodeName">${solr.nodeName:}</str>
<int name="leaderVoteWait">${leaderVoteWait:10000}</int>
<int name="distribUpdateConnTimeout">${distribUpdateConnTimeout:45000}</int>
<int name="distribUpdateSoTimeout">${distribUpdateSoTimeout:340000}</int>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,14 +618,6 @@ private NamedList realTimeGetDocId(HttpSolrClient solr, String docId) throws Sol
return solr.request(qr);
}

protected int getReplicaPort(Replica replica) {
String replicaNode = replica.getNodeName();
String tmp = replicaNode.substring(replicaNode.indexOf(':')+1);
if (tmp.indexOf('_') != -1)
tmp = tmp.substring(0,tmp.indexOf('_'));
return Integer.parseInt(tmp);
}

protected void waitToSeeReplicasActive(String testCollectionName, String shardId, Set<String> replicasToCheck, int maxWaitSecs) throws Exception {
final RTimer timer = new RTimer();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public void restartWithRolesTest() throws Exception {
numDesignateOverseers = Math.max(getShardCount(), numDesignateOverseers);
List<String> designates = new ArrayList<>();
List<CloudJettyRunner> designateJettys = new ArrayList<>();

for (int i = 0; i < numDesignateOverseers; i++) {
int n = random().nextInt(getShardCount());
String nodeName = cloudJettys.get(n).nodeName;
Expand Down
Loading

0 comments on commit b1de1f9

Please sign in to comment.