Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.apache.ignite.internal.processors.resource.GridResourceProcessor;
import org.apache.ignite.internal.processors.rest.IgniteRestProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.RollingUpgradeProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteNodeFeatureSet;
import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter;
import org.apache.ignite.internal.processors.security.IgniteSecurity;
import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor;
Expand Down Expand Up @@ -140,6 +141,9 @@ public interface GridKernalContext extends Iterable<GridComponent> {
*/
public GridKernalGateway gateway();

/** @return Local node features. */
public IgniteNodeFeatureSet localNodeFeatures();

/**
* Gets grid instance managed by kernal.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
import org.apache.ignite.internal.processors.resource.GridResourceProcessor;
import org.apache.ignite.internal.processors.rest.IgniteRestProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.RollingUpgradeProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteNodeFeatureSet;
import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter;
import org.apache.ignite.internal.processors.security.IgniteSecurity;
import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor;
Expand Down Expand Up @@ -632,6 +633,11 @@ else if (!(comp instanceof DiscoveryNodeValidationProcessor
return gw;
}

/** {@inheritDoc} */
@Override public IgniteNodeFeatureSet localNodeFeatures() {
return rollUpProc.features().localVersionFeatures();
}

/** {@inheritDoc} */
@Override public IgniteEx grid() {
return grid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
import org.apache.ignite.internal.processors.resource.GridResourceProcessor;
import org.apache.ignite.internal.processors.rest.IgniteRestProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.RollingUpgradeProcessor;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteCoreFeatureSet;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteNodeFeatureSet;
import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter;
import org.apache.ignite.internal.processors.security.IgniteSecurity;
import org.apache.ignite.internal.processors.security.NoOpIgniteSecurityProcessor;
Expand Down Expand Up @@ -177,6 +179,9 @@ public class StandaloneGridKernalContext implements GridKernalContext {
/** Operation context dispacther. */
private final OperationContextDispatcher opCtxDispatcher = new OperationContextDispatcher();

/** */
private final IgniteNodeFeatureSet locNodeFeatures = new IgniteNodeFeatureSet(IgniteCoreFeatureSet.local());

/**
* @param log Logger.
* @param ft Node file tree.
Expand Down Expand Up @@ -317,6 +322,11 @@ protected IgniteConfiguration prepareIgniteConfiguration() {
return null;
}

/** {@inheritDoc} */
@Override public IgniteNodeFeatureSet localNodeFeatures() {
return locNodeFeatures;
}

/** {@inheritDoc} */
@Override public IgniteEx grid() {
final IgniteEx kernal = new IgniteKernal() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import org.apache.ignite.spi.discovery.tcp.internal.DiscoveryDataPacket;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNodesRing;
import org.apache.ignite.spi.discovery.tcp.internal.UnsupportedNodeVersionException;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryAbstractMessage;
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryAuthFailedMessage;
Expand Down Expand Up @@ -708,7 +709,7 @@ private static void sleepEx(long millis, Runnable before, Runnable after) throws

TcpDiscoveryIoSession ses = createSession(sock);

TcpDiscoveryHandshakeRequest req = new TcpDiscoveryHandshakeRequest(locNodeId);
TcpDiscoveryHandshakeRequest req = new TcpDiscoveryHandshakeRequest(locNodeId, spi.localNodeFeatures());

req.client(true);
req.dcId(locNode.dataCenterId());
Expand All @@ -717,6 +718,8 @@ private static void sleepEx(long millis, Runnable before, Runnable after) throws

TcpDiscoveryHandshakeResponse res = spi.readHandshakeResponse(ses, ackTimeout0);

spi.validateRemoteFeatures(res.nodeFeatures());

// Convert the addresses once.
Collection<InetSocketAddress> redirectAddrs = res.redirectAddresses();

Expand Down Expand Up @@ -791,6 +794,16 @@ private static void sleepEx(long millis, Runnable before, Runnable after) throws

errs.add(e);

if (e instanceof UnsupportedNodeVersionException) {
LT.error(log, e, "Failed to initialize a connection with the remote node. The remote node is running" +
" components with an incompatible versions, so the nodes cannot agree on serialization protocol" +
" [rmtAddr=" + addr + ']');

throw new IgniteSpiException("Failed to initialize a connection with the remote node. The remote node" +
" is running components with an incompatible versions, so the nodes cannot agree on serialization" +
" protocol [rmtAddr=" + addr + ']', e);
}

if (X.hasCause(e, SSLException.class)) {
if (--sslConnectAttempts == 0)
throw new IgniteSpiException("Unable to establish secure connection. " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNodesRing;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoverySpiState;
import org.apache.ignite.spi.discovery.tcp.internal.UnsupportedNodeVersionException;
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryAbstractMessage;
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryAuthFailedMessage;
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryCheckFailedMessage;
Expand Down Expand Up @@ -1512,13 +1513,15 @@ else if (U.millisSinceNanos(joinStartNanos) > spi.joinTimeout)

openSock = true;

TcpDiscoveryHandshakeRequest req = new TcpDiscoveryHandshakeRequest(locNodeId);
TcpDiscoveryHandshakeRequest req = new TcpDiscoveryHandshakeRequest(locNodeId, spi.localNodeFeatures());

// Handshake.
spi.writeMessage(ses, req, timeoutHelper.nextTimeoutChunk(spi.getSocketTimeout()));

TcpDiscoveryHandshakeResponse res = spi.readHandshakeResponse(ses, timeoutHelper.nextTimeoutChunk(ackTimeout0));

spi.validateRemoteFeatures(res.nodeFeatures());

if (msg instanceof TcpDiscoveryJoinRequestMessage) {
boolean ignore = false;

Expand Down Expand Up @@ -1597,6 +1600,16 @@ else if (U.millisSinceNanos(joinStartNanos) > spi.joinTimeout)

errs.add(e);

if (e instanceof UnsupportedNodeVersionException) {
LT.error(log, e, "Failed to initialize a connection with the remote node. The remote node is running" +
" components with an incompatible versions, so the nodes cannot agree on serialization protocol" +
" [rmtAddr=" + addr + ']');

throw new IgniteException("Failed to initialize a connection with the remote node. The remote node" +
" is running components with an incompatible versions, so the nodes cannot agree on a serialization" +
" protocol [rmtAddr=" + addr + ']', e);
}

if (X.hasCause(e, SSLException.class)) {
if (--sslConnectAttempts == 0)
throw new IgniteException("Unable to establish secure connection. " +
Expand Down Expand Up @@ -3412,7 +3425,7 @@ else if (log.isTraceEnabled())
openSock = true;

// Handshake.
TcpDiscoveryHandshakeRequest hndMsg = new TcpDiscoveryHandshakeRequest(locNodeId);
TcpDiscoveryHandshakeRequest hndMsg = new TcpDiscoveryHandshakeRequest(locNodeId, spi.localNodeFeatures());

if (sndState != null) {
// If want a forced connection, we set the change-topology node flag to current node id.
Expand Down Expand Up @@ -3441,6 +3454,8 @@ else if (!sndState.isStartingPoint())
if (log.isDebugEnabled())
log.debug("Handshake response: " + res);

spi.validateRemoteFeatures(res.nodeFeatures());

// We should take previousNodeAlive flag into account
// only if we received the response from the correct node.
if (res.creatorNodeId().equals(next.id()) && res.previousNodeAlive() && sndState != null) {
Expand Down Expand Up @@ -6593,8 +6608,11 @@ else if (log.isDebugEnabled())
U.enhanceThreadName(U.id8(nodeId) + ' ' + sock.getInetAddress().getHostAddress()
+ ":" + sock.getPort() + (req.client() ? " client" : ""));

TcpDiscoveryHandshakeResponse res =
new TcpDiscoveryHandshakeResponse(locNodeId, locNode.internalOrder());
TcpDiscoveryHandshakeResponse res = new TcpDiscoveryHandshakeResponse(
locNodeId,
locNode.internalOrder(),
spi.localNodeFeatures()
);

if (req.client()) {
if (req.dcId() != null && !Objects.equals(req.dcId(), locNode.dataCenterId())) {
Expand Down Expand Up @@ -6708,6 +6726,8 @@ else if (log.isInfoEnabled()) {

spi.writeMessage(ses, res, spi.getEffectiveSocketTimeout(srvSock));

spi.validateRemoteFeatures(req.nodeFeatures());

// It can happen if a remote node is stopped and it has a loopback address in the list of addresses,
// the local node sends a handshake request message on the loopback address, so we get here.
if (locNodeId.equals(nodeId)) {
Expand Down Expand Up @@ -6804,21 +6824,26 @@ else if ((X.hasCause(e, ObjectStreamException.class) || !sock.isClosed())

onException("Caught exception on handshake [err=" + e + ", sock=" + sock + ']', e);

if (e.hasCause(SocketTimeoutException.class))
if (e instanceof UnsupportedNodeVersionException) {
LT.warn(log, "Failed to initialize a connection with the remote node. The remote node is running" +
" components with an incompatible versions, so the nodes cannot agree on serialization protocol" +
" [rmtAddr=" + rmtAddr + ']', e);
}
else if (e.hasCause(SocketTimeoutException.class)) {
LT.warn(log, "Socket operation timed out on handshake " +
"(consider increasing 'networkTimeout' configuration property) " +
"[netTimeout=" + spi.netTimeout + ']');

else if (e.hasCause(ClassNotFoundException.class))
}
else if (e.hasCause(ClassNotFoundException.class)) {
LT.warn(log, "Failed to read message due to ClassNotFoundException " +
"(make sure same versions of all classes are available on all nodes) " +
"[rmtAddr=" + rmtAddr +
", err=" + X.cause(e, ClassNotFoundException.class).getMessage() + ']');

}
else if (e.hasCause(ObjectStreamException.class) || (!sock.isClosed() && !e.hasCause(IOException.class))) {
// Always report marshalling problems.
else if (e.hasCause(ObjectStreamException.class) ||
(!sock.isClosed() && !e.hasCause(IOException.class)))
LT.error(log, e, "Failed to initialize connection [sock=" + sock + ']');
}

return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
import org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi;
import org.apache.ignite.internal.processors.failure.FailureProcessor;
import org.apache.ignite.internal.processors.metric.MetricRegistryImpl;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteComponentFeatureSet;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteNodeFeatureSet;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
Expand Down Expand Up @@ -99,6 +101,7 @@
import org.apache.ignite.spi.discovery.tcp.internal.DiscoveryDataPacket;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryStatistics;
import org.apache.ignite.spi.discovery.tcp.internal.UnsupportedNodeVersionException;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
Expand Down Expand Up @@ -468,6 +471,9 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter implements IgniteDiscovery
/** For test purposes. */
private boolean skipAddrsRandomization = false;

/** */
private IgniteNodeFeatureSet locNodeFeatures;

/**
* Gets current SPI state.
*
Expand Down Expand Up @@ -1189,6 +1195,8 @@ protected void initLocalNode(int srvPort, boolean addExtAddrAttr) {
// Init local node.
initAddresses();

locNodeFeatures = ((IgniteEx)ignite).context().localNodeFeatures();

locNode = new TcpDiscoveryNode(
ignite.configuration().getNodeId(),
addrs.get1(),
Expand Down Expand Up @@ -1686,6 +1694,40 @@ Socket createSocket() throws IOException {
}
}

/** */
IgniteNodeFeatureSet localNodeFeatures() {
return locNodeFeatures;
}

/** */
void validateRemoteFeatures(IgniteNodeFeatureSet rmtFeatures) throws IgniteCheckedException {
if (rmtFeatures == null)
throw new UnsupportedNodeVersionException("Remote node component versions are not supported" +
" [locComponents=" + locNodeFeatures +
", rmtComponents=" + rmtFeatures + ']');

for (IgniteComponentFeatureSet rmtCmpFeatures : rmtFeatures.values()) {
IgniteComponentFeatureSet locCmpFeatures = locNodeFeatures.componentFeatures(rmtCmpFeatures.componentName());

if (locCmpFeatures == null)
continue;

int c = locCmpFeatures.version().compareTo(rmtCmpFeatures.version());

if (c == 0)
continue;

IgniteComponentFeatureSet src = c > 0 ? rmtCmpFeatures : locCmpFeatures;
IgniteComponentFeatureSet target = c > 0 ? locCmpFeatures : rmtCmpFeatures;

if (!src.isUpgradableTo(target)) {
throw new UnsupportedNodeVersionException("Remote node component versions are not supported" +
" [locComponents=" + locNodeFeatures +
", rmtComponents=" + rmtFeatures + ']');
}
}
}

/**
* Writes message to the socket.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.ignite.spi.discovery.tcp.internal;

import org.apache.ignite.IgniteCheckedException;

/** */
public class UnsupportedNodeVersionException extends IgniteCheckedException {
/** */
private static final long serialVersionUID = 0L;

/** */
public UnsupportedNodeVersionException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import java.util.UUID;
import org.apache.ignite.internal.Order;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteComponentFeatureSet;
import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteNodeFeatureSet;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.plugin.extensions.communication.MessageFactory;
import org.jetbrains.annotations.Nullable;
Expand All @@ -35,6 +37,10 @@ public class TcpDiscoveryHandshakeRequest extends TcpDiscoveryAbstractMessage {
@Order(1)
@Nullable String dcId;

/** */
@Order(2)
IgniteComponentFeatureSet[] nodeFeatures;

/**
* Default constructor for {@link MessageFactory}.
*/
Expand All @@ -46,9 +52,12 @@ public TcpDiscoveryHandshakeRequest() {
* Constructor.
*
* @param creatorNodeId Creator node ID.
* @param locNodeFeatures Local node features.
*/
public TcpDiscoveryHandshakeRequest(UUID creatorNodeId) {
public TcpDiscoveryHandshakeRequest(UUID creatorNodeId, IgniteNodeFeatureSet locNodeFeatures) {
super(creatorNodeId);

this.nodeFeatures = locNodeFeatures.values();
}

/**
Expand Down Expand Up @@ -79,6 +88,11 @@ public void dcId(String dcId) {
this.dcId = dcId;
}

/** @return Features supported by the sender node. */
public IgniteNodeFeatureSet nodeFeatures() {
return nodeFeatures == null ? null : new IgniteNodeFeatureSet(nodeFeatures);
}

/** {@inheritDoc} */
@Override public String toString() {
return S.toString(TcpDiscoveryHandshakeRequest.class, this, "super", super.toString(),
Expand Down
Loading
Loading