This is an automated email from the ASF dual-hosted git repository. agoncharuk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 0260ba0 IGNITE-13362 Add warmup stop command to control.sh - Fixes #8201. 0260ba0 is described below commit 0260ba0c8fa3be6ddce9efc473f45b13d11f7784 Author: ktkalenko <ktkale...@gridgain.com> AuthorDate: Thu Sep 10 17:51:29 2020 +0300 IGNITE-13362 Add warmup stop command to control.sh - Fixes #8201. Signed-off-by: Alexey Goncharuk <alexey.goncha...@gmail.com> --- .../ignite/internal/commandline/Command.java | 31 ++++ .../ignite/internal/commandline/CommandList.java | 5 +- .../ignite/internal/commandline/WarmUpCommand.java | 121 +++++++++++++ .../commandline/CommandHandlerParsingTest.java | 36 +++- .../apache/ignite/util/GridCommandHandlerTest.java | 58 +++++++ .../internal/client/GridClientBeforeNodeStart.java | 66 +++++++ .../ignite/internal/client/GridClientFactory.java | 33 +++- .../client/GridClientNodeStateBeforeStart.java} | 16 +- .../internal/client/impl/GridClientImpl.java | 190 +++++++++++++++------ .../impl/GridClientNodeStateBeforeStartImpl.java | 49 ++++++ .../impl/connection/GridClientConnection.java | 9 + .../connection/GridClientConnectionManager.java | 12 ++ .../GridClientConnectionManagerAdapter.java | 156 +++++++++++------ .../GridClientConnectionManagerOsImpl.java | 7 +- .../connection/GridClientNioTcpConnection.java | 8 + .../client/router/impl/GridRouterClientImpl.java | 2 +- .../internal/processors/rest/GridRestCommand.java | 8 +- .../processors/rest/GridRestProcessor.java | 11 +- .../internal/processors/rest/GridRestProtocol.java | 5 + .../GridClientNodeStateBeforeStartRequest.java} | 16 +- .../client/message/GridClientWarmUpRequest.java | 90 ++++++++++ .../NodeStateBeforeStartCommandHandler.java | 75 ++++++++ .../rest/protocols/GridRestProtocolAdapter.java | 5 + .../rest/protocols/tcp/GridTcpRestNioListener.java | 22 +++ .../rest/protocols/tcp/GridTcpRestProtocol.java | 6 +- .../GridRestNodeStateBeforeStartRequest.java} | 13 +- .../rest/request/GridRestWarmUpRequest.java | 54 ++++++ .../main/resources/META-INF/classnames.properties | 2 + .../cache/warmup/BlockedWarmUpConfiguration.java | 4 +- ...ockedWarmUp.java => BlockedWarmUpStrategy.java} | 6 +- .../SimpleObservableWarmUpConfiguration.java | 2 +- ...Up.java => SimpleObservableWarmUpStrategy.java} | 2 +- .../processors/cache/warmup/WarmUpSelfTest.java | 10 +- .../cache/warmup/WarmUpTestPluginProvider.java | 8 +- ...ridCommandHandlerClusterByClassTest_help.output | 3 + ...andHandlerClusterByClassWithSSLTest_help.output | 3 + .../Cache/PartitionLossTest.cs | 12 +- 37 files changed, 1003 insertions(+), 153 deletions(-) diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/Command.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/Command.java index b147933..5b00a78 100644 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/Command.java +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/Command.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.logging.Logger; import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.internal.client.GridClient; +import org.apache.ignite.internal.client.GridClientBeforeNodeStart; import org.apache.ignite.internal.client.GridClientConfiguration; import org.apache.ignite.internal.client.GridClientException; import org.apache.ignite.internal.client.GridClientFactory; @@ -69,6 +70,36 @@ public interface Command<T> { } /** + * Method to create thin client for communication with node before it starts. + * If node has already started, there will be an error. + * + * @param clientCfg Thin client configuration. + * @return Grid thin client instance which is already connected to node before it starts. + * @throws Exception If error occur. + */ + public static GridClientBeforeNodeStart startClientBeforeNodeStart( + GridClientConfiguration clientCfg + ) throws Exception { + GridClientBeforeNodeStart client = GridClientFactory.startBeforeNodeStart(clientCfg); + + // If connection is unsuccessful, fail before doing any operations: + if (!client.connected()) { + GridClientException lastErr = client.checkLastError(); + + try { + client.close(); + } + catch (Throwable e) { + lastErr.addSuppressed(e); + } + + throw lastErr; + } + + return client; + } + + /** * Print command usage. * * @param logger Logger to use. diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java index 1e3df5d..4190604 100644 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java @@ -74,7 +74,10 @@ public enum CommandList { SHUTDOWN_POLICY("--shutdown-policy", new ShutdownPolicyCommand()), /** */ - TRACING_CONFIGURATION("--tracing-configuration", new TracingConfigurationCommand()); + TRACING_CONFIGURATION("--tracing-configuration", new TracingConfigurationCommand()), + + /** Warm-up command. */ + WARM_UP("--warm-up", new WarmUpCommand()); /** Private values copy so there's no need in cloning it every time. */ private static final CommandList[] VALUES = CommandList.values(); diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/WarmUpCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/WarmUpCommand.java new file mode 100644 index 0000000..1d69f09 --- /dev/null +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/WarmUpCommand.java @@ -0,0 +1,121 @@ +/* + * 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.internal.commandline; + +import java.util.logging.Logger; +import org.apache.ignite.internal.client.GridClientBeforeNodeStart; +import org.apache.ignite.internal.client.GridClientConfiguration; +import org.apache.ignite.internal.client.GridClientDisconnectedException; +import org.apache.ignite.internal.client.GridClientException; +import org.apache.ignite.internal.commandline.argument.CommandArg; +import org.apache.ignite.internal.commandline.argument.CommandArgUtils; + +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; +import static org.apache.ignite.internal.commandline.CommandList.WARM_UP; + +/** + * Command for interacting with warm-up. + */ +public class WarmUpCommand implements Command<Void> { + /** {@inheritDoc} */ + @Override public void printUsage(Logger logger) { + Command.usage(logger, "Stop warm-up:", WARM_UP, WarmUpCommandArg.STOP.argName()); + } + + /** {@inheritDoc} */ + @Override public String name() { + return CommandList.WARM_UP.toCommandName(); + } + + /** {@inheritDoc} */ + @Override public Void arg() { + return null; + } + + /** {@inheritDoc} */ + @Override public void parseArguments(CommandArgIterator argIter) { + boolean stop = false; + + while (nonNull(argIter.peekNextArg())) { + WarmUpCommandArg arg = CommandArgUtils.of(argIter.nextArg(""), WarmUpCommandArg.class); + + if (isNull(arg)) + break; + + switch (arg) { + case STOP: + stop = true; + break; + + default: + throw new AssertionError(); + } + } + + if (!stop) + throw new IllegalArgumentException(WarmUpCommandArg.STOP.argName() + " argument is missing."); + } + + /** {@inheritDoc} */ + @Override public String confirmationPrompt() { + return "Warning: command will stop warm-up."; + } + + /** {@inheritDoc} */ + @Override public Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception { + try (GridClientBeforeNodeStart client = Command.startClientBeforeNodeStart(clientCfg)) { + client.beforeStartState().stopWarmUp(); + } + catch (GridClientDisconnectedException e) { + throw new GridClientException(e.getCause()); + } + + return true; + } + + /** + * Warm-up command arguments name. + */ + private enum WarmUpCommandArg implements CommandArg { + /** Stop warm-up argument. */ + STOP("--stop"); + + /** Option name. */ + private final String name; + + /** + * Constructor. + * + * @param name Argument name. + */ + WarmUpCommandArg(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public String argName() { + return name; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return name; + } + } +} diff --git a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java index f3705df..a9ae762 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java @@ -57,6 +57,7 @@ import static org.apache.ignite.internal.commandline.CommandList.CLUSTER_CHANGE_ import static org.apache.ignite.internal.commandline.CommandList.SET_STATE; import static org.apache.ignite.internal.commandline.CommandList.SHUTDOWN_POLICY; import static org.apache.ignite.internal.commandline.CommandList.WAL; +import static org.apache.ignite.internal.commandline.CommandList.WARM_UP; import static org.apache.ignite.internal.commandline.CommonArgParser.CMD_VERBOSE; import static org.apache.ignite.internal.commandline.TaskExecutor.DFLT_HOST; import static org.apache.ignite.internal.commandline.TaskExecutor.DFLT_PORT; @@ -70,6 +71,7 @@ import static org.apache.ignite.testframework.GridTestUtils.assertThrows; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -378,6 +380,8 @@ public class CommandHandlerParsingTest { args = parseArgs(asList(cmdL.text(), "ACTIVE")); else if (cmdL == CLUSTER_CHANGE_TAG) args = parseArgs(asList(cmdL.text(), "newTagValue")); + else if (cmdL == WARM_UP) + args = parseArgs(asList(cmdL.text(), "--stop")); else args = parseArgs(asList(cmdL.text())); @@ -455,6 +459,12 @@ public class CommandHandlerParsingTest { break; } + case WARM_UP: { + args = parseArgs(asList(cmdL.text(), "--stop", "--yes")); + + break; + } + default: fail("Unknown command: " + cmd); } @@ -937,6 +947,29 @@ public class CommandHandlerParsingTest { } /** + * Test verifies correctness of parsing of arguments --warm-up command. + */ + @Test + public void testWarmUpArgs() { + String[][] args = { + {"--warm-up"}, + {"--warm-up", "1"}, + {"--warm-up", "stop"} + }; + + for (String[] arg : args) { + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList(arg)), + IllegalArgumentException.class, + "--stop argument is missing." + ); + } + + assertNotNull(parseArgs(asList("--warm-up", "--stop"))); + } + + /** * @param args Raw arg list. * @return Common parameters container object. */ @@ -994,6 +1027,7 @@ public class CommandHandlerParsingTest { cmd == CommandList.KILL || cmd == CommandList.SNAPSHOT || cmd == CommandList.CLUSTER_CHANGE_TAG || - cmd == CommandList.METADATA; + cmd == CommandList.METADATA || + cmd == CommandList.WARM_UP; } } diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java index 62a7f17..fcacd9b 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java @@ -35,6 +35,7 @@ import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -89,6 +90,9 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; import org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; +import org.apache.ignite.internal.processors.cache.warmup.BlockedWarmUpConfiguration; +import org.apache.ignite.internal.processors.cache.warmup.BlockedWarmUpStrategy; +import org.apache.ignite.internal.processors.cache.warmup.WarmUpTestPluginProvider; import org.apache.ignite.internal.processors.cluster.GridClusterStateProcessor; import org.apache.ignite.internal.util.lang.GridAbsPredicate; import org.apache.ignite.internal.util.typedef.G; @@ -2330,6 +2334,60 @@ public class GridCommandHandlerTest extends GridCommandHandlerClusterPerMethodAb } /** + * Verification of successful warm-up stop. + * <p/> + * Steps: + * 1)Starting node with warm-up; + * 2)Stop warm-up; + * 3)Waiting for a successful stop of warm-up and start of node. + * + * @throws Exception If failed. + */ + @Test + public void testSuccessStopWarmUp() throws Exception { + WarmUpTestPluginProvider provider = new WarmUpTestPluginProvider(); + + IgniteConfiguration cfg = getConfiguration(getTestIgniteInstanceName(0)).setPluginProviders(provider); + cfg.getDataStorageConfiguration().setDefaultWarmUpConfiguration(new BlockedWarmUpConfiguration()); + + cfg.getConnectorConfiguration().setHost("localhost"); + + IgniteInternalFuture<IgniteEx> fut = runAsync(() -> startGrid(cfg)); + + BlockedWarmUpStrategy blockedWarmUpStgy = (BlockedWarmUpStrategy)provider.strats.get(1); + + try { + U.await(blockedWarmUpStgy.startLatch, 60, TimeUnit.SECONDS); + + assertEquals(EXIT_CODE_OK, execute("--warm-up", "--stop", "--yes")); + + fut.get(60_000); + } + catch (Throwable t) { + blockedWarmUpStgy.stopLatch.countDown(); + + throw t; + } + } + + /** + * Check that command will not be executed because node has already started. + * <p/> + * Steps: + * 1)Starting node; + * 2)Attempt to stop warm-up; + * 3)Waiting for an error because node has already started. + * + * @throws Exception If failed. + */ + @Test + public void testFailStopWarmUp() throws Exception { + startGrid(0); + + assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--warm-up", "--stop", "--yes")); + } + + /** * @param ignite Ignite to execute task on. * @param delFoundGarbage If clearing mode should be used. * @return Result of task run. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientBeforeNodeStart.java b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientBeforeNodeStart.java new file mode 100644 index 0000000..d8cc76b --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientBeforeNodeStart.java @@ -0,0 +1,66 @@ +/* + * 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.internal.client; + +import java.util.UUID; + +/** + * Ignite Java client API for communicate with node before it start. + * If node has already started, then there will be errors. + * For get an instance, need to use {@link GridClientFactory#startBeforeNodeStart}. + */ +public interface GridClientBeforeNodeStart extends AutoCloseable { + /** + * Gets a unique client identifier. This identifier is generated by factory on client creation + * and used in identification and authentication procedure on server node. + * + * @return Generated client id. + */ + public UUID id(); + + /** + * Indicates whether client is connected to remote Grid. + * In other words it allow to determine if client is able to communicate + * with Grid right now. It can be used only fo diagnostic and monitoring purposes. + * + * @return Whether client is connected to remote Grid. + */ + public boolean connected(); + + /** + * Closes client instance. This method is identical to + * {@link GridClientFactory#stop(UUID) GridClientFactory.stop(clientId)}. + */ + @Override public void close(); + + /** + * Checking for an error. + * + * @return {@code Exception} if client was not connected. + */ + public GridClientException checkLastError(); + + /** + * Getting a client projection of node state before its start. + * + * @return Projection of node state before its start. + * + * @see GridClientNodeStateBeforeStart + */ + public GridClientNodeStateBeforeStart beforeStartState(); +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java index 00d9308..d40b466 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java @@ -32,7 +32,7 @@ public class GridClientFactory { private static ConcurrentMap<UUID, GridClientImpl> openClients = new ConcurrentHashMap<>(); /** Lock to prevent concurrent adding of clients while stopAll is working. */ - private static ReadWriteLock busyLock = new ReentrantReadWriteLock(); + private static final ReadWriteLock busyLock = new ReentrantReadWriteLock(); /** * Ensure singleton. @@ -50,12 +50,41 @@ public class GridClientFactory { * @throws GridClientException If client could not be created. */ public static GridClient start(GridClientConfiguration cfg) throws GridClientException { + return start(cfg, false); + } + + /** + * Starts a client before node start with given configuration. + * If node has already started, there will be an error. + * + * @param cfg Client configuration. + * @return Started client. + * @throws GridClientException If client could not be created. + */ + public static GridClientBeforeNodeStart startBeforeNodeStart( + GridClientConfiguration cfg + ) throws GridClientException { + return start(cfg, true); + } + + /** + * Starts a client with given configuration. + * + * @param cfg Client configuration. + * @param beforeNodeStart Before node start. + * @return Started client. + * @throws GridClientException If client could not be created. + */ + private static GridClientImpl start( + GridClientConfiguration cfg, + boolean beforeNodeStart + ) throws GridClientException { busyLock.readLock().lock(); try { UUID clientId = UUID.randomUUID(); - GridClientImpl client = new GridClientImpl(clientId, cfg, false); + GridClientImpl client = new GridClientImpl(clientId, cfg, false, beforeNodeStart); GridClientImpl old = openClients.putIfAbsent(clientId, client); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientNodeStateBeforeStart.java similarity index 67% copy from modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java copy to modules/core/src/main/java/org/apache/ignite/internal/client/GridClientNodeStateBeforeStart.java index d050133..7eec8ad 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientNodeStateBeforeStart.java @@ -15,13 +15,17 @@ * limitations under the License. */ -package org.apache.ignite.internal.processors.cache.warmup; - -import org.apache.ignite.configuration.WarmUpConfiguration; +package org.apache.ignite.internal.client; /** - * Configuration for {@link SimpleObservableWarmUp}. + * Interface for managing state of a node before it starts and getting information about it. + * An exception will be thrown if node has already started. */ -class SimpleObservableWarmUpConfiguration implements WarmUpConfiguration { - // No-op. +public interface GridClientNodeStateBeforeStart { + /** + * Stop warm-up. + * + * @throws GridClientException In case of error. + */ + void stopWarmUp() throws GridClientException; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientImpl.java index fb2546b..c52241c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientImpl.java @@ -34,8 +34,10 @@ import java.util.logging.Logger; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.internal.client.GridClient; +import org.apache.ignite.internal.client.GridClientBeforeNodeStart; import org.apache.ignite.internal.client.GridClientCacheMode; import org.apache.ignite.internal.client.GridClientClosedException; import org.apache.ignite.internal.client.GridClientClusterState; @@ -48,12 +50,14 @@ import org.apache.ignite.internal.client.GridClientDisconnectedException; import org.apache.ignite.internal.client.GridClientException; import org.apache.ignite.internal.client.GridClientFactory; import org.apache.ignite.internal.client.GridClientNode; +import org.apache.ignite.internal.client.GridClientNodeStateBeforeStart; import org.apache.ignite.internal.client.GridClientPartitionAffinity; import org.apache.ignite.internal.client.GridClientPredicate; import org.apache.ignite.internal.client.GridClientTopologyListener; import org.apache.ignite.internal.client.GridServerUnreachableException; import org.apache.ignite.internal.client.balancer.GridClientLoadBalancer; import org.apache.ignite.internal.client.balancer.GridClientRandomBalancer; +import org.apache.ignite.internal.client.impl.connection.GridClientConnection; import org.apache.ignite.internal.client.impl.connection.GridClientConnectionManager; import org.apache.ignite.internal.client.impl.connection.GridClientConnectionManagerOsImpl; import org.apache.ignite.internal.client.impl.connection.GridClientTopology; @@ -68,7 +72,7 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MACS; /** * Client implementation. */ -public class GridClientImpl implements GridClient { +public class GridClientImpl implements GridClient, GridClientBeforeNodeStart { /** Null mask object. */ private static final Object NULL_MASK = new Object(); @@ -99,28 +103,28 @@ public class GridClientImpl implements GridClient { protected final GridClientConfiguration cfg; /** SSL context if ssl enabled. */ - private SSLContext sslCtx; + private final SSLContext sslCtx; /** Main compute projection. */ - private final GridClientComputeImpl compute; + @Nullable private final GridClientComputeImpl compute; /** Cluster state projection. */ - private final GridClientClusterStateImpl clusterState; + @Nullable private final GridClientClusterStateImpl clusterState; /** Data projections. */ - private ConcurrentMap<Object, GridClientDataImpl> dataMap = new ConcurrentHashMap<>(); + private final ConcurrentMap<Object, GridClientDataImpl> dataMap = new ConcurrentHashMap<>(); /** Topology. */ - protected GridClientTopology top; + protected final GridClientTopology top; /** Topology updater thread. */ - private final Thread topUpdateThread; + @Nullable private final Thread topUpdateThread; /** Closed flag. */ - private AtomicBoolean closed = new AtomicBoolean(); + private final AtomicBoolean closed = new AtomicBoolean(); /** Connection manager. */ - protected GridClientConnectionManager connMgr; + protected final GridClientConnectionManager connMgr; /** Routers. */ private final Collection<InetSocketAddress> routers; @@ -128,18 +132,29 @@ public class GridClientImpl implements GridClient { /** Servers. */ private final Collection<InetSocketAddress> srvs; + /** Projection of node state before its start. */ + @Nullable private final GridClientNodeStateBeforeStart beforeStartState; + /** * Creates a new client based on a given configuration. + * <p/> + * If {@code beforeNodeStart == true}, topology will not be received/updated, + * and there will also be errors when trying to work with topology, compute, state and cache. * * @param id Client identifier. * @param cfg0 Client configuration. * @param routerClient Router client flag. + * @param beforeNodeStart Connecting to a node before it start. * @throws GridClientException If client configuration is incorrect. - * @throws GridServerUnreachableException If none of the servers specified in configuration can - * be reached. + * @throws GridServerUnreachableException If none of the servers specified in configuration can be reached. */ @SuppressWarnings("CallToThreadStartDuringObjectConstruction") - public GridClientImpl(UUID id, GridClientConfiguration cfg0, boolean routerClient) throws GridClientException { + public GridClientImpl( + UUID id, + GridClientConfiguration cfg0, + boolean routerClient, + boolean beforeNodeStart + ) throws GridClientException { this.id = id; cfg = new GridClientConfiguration(cfg0); @@ -149,14 +164,16 @@ public class GridClientImpl implements GridClient { try { top = new GridClientTopology(cfg); - for (GridClientDataConfiguration dataCfg : cfg.getDataConfigurations()) { - GridClientDataAffinity aff = dataCfg.getAffinity(); + if (!beforeNodeStart) { + for (GridClientDataConfiguration dataCfg : cfg.getDataConfigurations()) { + GridClientDataAffinity aff = dataCfg.getAffinity(); - if (aff instanceof GridClientTopologyListener) - addTopologyListener((GridClientTopologyListener)aff); + if (aff instanceof GridClientTopologyListener) + addTopologyListener((GridClientTopologyListener)aff); + } } - if (cfg.getBalancer() instanceof GridClientTopologyListener) + if (!beforeNodeStart && cfg.getBalancer() instanceof GridClientTopologyListener) top.addTopologyListener((GridClientTopologyListener)cfg.getBalancer()); GridSslContextFactory factory = cfg.getSslContextFactory(); @@ -170,6 +187,8 @@ public class GridClientImpl implements GridClient { "check ssl context factory configuration): " + e.getMessage(), e); } } + else + sslCtx = null; if (cfg.isAutoFetchMetrics() && !cfg.isEnableMetricsCache()) log.warning("Auto-fetch for metrics is enabled without enabling caching for them."); @@ -189,11 +208,11 @@ public class GridClientImpl implements GridClient { throw new GridClientException("Servers addresses and routers addresses cannot both be provided " + "for client (please fix configuration and restart): " + this); - connMgr = createConnectionManager(id, sslCtx, cfg, routers, top, null, routerClient); + connMgr = createConnectionManager(id, sslCtx, cfg, routers, top, null, routerClient, beforeNodeStart); try { - // Init connection manager, it should cause topology update. - tryInitTopology(); + // Init connection manager. + tryInit(); } catch (GridClientException e) { top.fail(e); @@ -206,15 +225,28 @@ public class GridClientImpl implements GridClient { throw new GridClientException("Client startup was interrupted.", e); } - topUpdateThread = new TopologyUpdaterThread(); + if (!beforeNodeStart) { + beforeStartState = null; - topUpdateThread.setDaemon(true); + topUpdateThread = new TopologyUpdaterThread(); - topUpdateThread.start(); + topUpdateThread.setDaemon(true); + + topUpdateThread.start(); + + compute = new GridClientComputeImpl(this, null, null, cfg.getBalancer()); + + clusterState = new GridClientClusterStateImpl(this, null, null, cfg.getBalancer()); + } + else { + topUpdateThread = null; - compute = new GridClientComputeImpl(this, null, null, cfg.getBalancer()); + compute = null; - clusterState = new GridClientClusterStateImpl(this, null, null, cfg.getBalancer()); + clusterState = null; + + beforeStartState = new GridClientNodeStateBeforeStartImpl(this); + } if (log.isLoggable(Level.INFO)) log.info("Client started [id=" + id + ", protocol=" + cfg.getProtocol() + ']'); @@ -265,6 +297,8 @@ public class GridClientImpl implements GridClient { @Override public GridClientData data(@Nullable final String cacheName) throws GridClientException { checkClosed(); + checkBeforeNodeStartMode(); + Object key = maskNull(cacheName); GridClientDataImpl data = dataMap.get(key); @@ -303,26 +337,36 @@ public class GridClientImpl implements GridClient { /** {@inheritDoc} */ @Override public GridClientCompute compute() { + checkBeforeNodeStartMode(); + return compute; } /** {@inheritDoc} */ @Override public GridClientClusterState state() { + checkBeforeNodeStartMode(); + return clusterState; } /** {@inheritDoc} */ @Override public void addTopologyListener(GridClientTopologyListener lsnr) { + checkBeforeNodeStartMode(); + top.addTopologyListener(lsnr); } /** {@inheritDoc} */ @Override public void removeTopologyListener(GridClientTopologyListener lsnr) { + checkBeforeNodeStartMode(); + top.removeTopologyListener(lsnr); } /** {@inheritDoc} */ @Override public Collection<GridClientTopologyListener> topologyListeners() { + checkBeforeNodeStartMode(); + return top.topologyListeners(); } @@ -342,6 +386,8 @@ public class GridClientImpl implements GridClient { * @return Topology instance. */ public GridClientTopology topology() { + checkBeforeNodeStartMode(); + return top; } @@ -350,6 +396,11 @@ public class GridClientImpl implements GridClient { return top.lastError(); } + /** {@inheritDoc} */ + @Override @Nullable public GridClientNodeStateBeforeStart beforeStartState() { + return beforeStartState; + } + /** * @return Connection manager. */ @@ -382,6 +433,16 @@ public class GridClientImpl implements GridClient { } /** + * Checks and throws an exception if mode is "before node start". + * + * @throws IgniteException If mode is "before node start". + */ + private void checkBeforeNodeStartMode() throws IgniteException { + if (beforeStartState != null) + throw new IgniteException("It is possible to work with a node only before it starts."); + } + + /** * Masks null cache name with unique object. * * @param cacheName Name to be masked. @@ -423,9 +484,11 @@ public class GridClientImpl implements GridClient { * @return New connection manager based on current client settings. * @throws GridClientException If failed to start connection server. */ - public GridClientConnectionManager newConnectionManager(@Nullable Byte marshId, boolean routerClient) - throws GridClientException { - return createConnectionManager(id, sslCtx, cfg, routers, top, marshId, routerClient); + public GridClientConnectionManager newConnectionManager( + @Nullable Byte marshId, + boolean routerClient + ) throws GridClientException { + return createConnectionManager(id, sslCtx, cfg, routers, top, marshId, routerClient, beforeStartState != null); } /** @@ -434,22 +497,65 @@ public class GridClientImpl implements GridClient { * @param cfg Client configuration. * @param routers Routers or empty collection to use endpoints from topology info. * @param top Topology. + * @param beforeNodeStart Connecting to a node before starting it without getting/updating topology. * @throws GridClientException In case of error. */ private GridClientConnectionManager createConnectionManager(UUID clientId, SSLContext sslCtx, GridClientConfiguration cfg, Collection<InetSocketAddress> routers, GridClientTopology top, - @Nullable Byte marshId, boolean routerClient) - throws GridClientException { - return new GridClientConnectionManagerOsImpl(clientId, sslCtx, cfg, routers, top, marshId, routerClient); + @Nullable Byte marshId, boolean routerClient, boolean beforeNodeStart) throws GridClientException { + return new GridClientConnectionManagerOsImpl( + clientId, + sslCtx, + cfg, + routers, + top, + marshId, + routerClient, + beforeNodeStart + ); } /** - * Tries to init client topology using configured set of servers or routers. + * Tries to init connection manager using configured set of servers or routers. * * @throws GridClientException If initialisation failed. * @throws InterruptedException If initialisation was interrupted. */ - private void tryInitTopology() throws GridClientException, InterruptedException { + private void tryInit() throws GridClientException, InterruptedException { + connMgr.init(addresses()); + + Map<String, GridClientCacheMode> overallCaches = new HashMap<>(); + + for (GridClientNodeImpl node : top.nodes()) + overallCaches.putAll(node.caches()); + + for (Map.Entry<String, GridClientCacheMode> entry : overallCaches.entrySet()) { + GridClientDataAffinity affinity = affinity(entry.getKey()); + + if (affinity instanceof GridClientPartitionAffinity && entry.getValue() != + GridClientCacheMode.PARTITIONED) + log.warning(GridClientPartitionAffinity.class.getSimpleName() + " is used for a cache configured " + + "for non-partitioned mode [cacheName=" + entry.getKey() + ", cacheMode=" + entry.getValue() + ']'); + } + } + + /** + * Getting a client connection without topology information. + * + * @return Client connection. + * @throws GridClientException If failed. + */ + public GridClientConnection connection() throws GridClientException, InterruptedException { + return connectionManager().connection(addresses()); + } + + /** + * Return addresses for connection. + * + * @return Addresses for connection. + * @throws GridClientException If failed. + */ + private Collection<InetSocketAddress> addresses() throws GridClientException { boolean hasSrvs = routers.isEmpty(); final Collection<InetSocketAddress> connSrvs = (hasSrvs) ? new LinkedHashSet<>(srvs) : routers; @@ -486,21 +592,7 @@ public class GridClientImpl implements GridClient { } } - connMgr.init(connSrvs); - - Map<String, GridClientCacheMode> overallCaches = new HashMap<>(); - - for (GridClientNodeImpl node : top.nodes()) - overallCaches.putAll(node.caches()); - - for (Map.Entry<String, GridClientCacheMode> entry : overallCaches.entrySet()) { - GridClientDataAffinity affinity = affinity(entry.getKey()); - - if (affinity instanceof GridClientPartitionAffinity && entry.getValue() != - GridClientCacheMode.PARTITIONED) - log.warning(GridClientPartitionAffinity.class.getSimpleName() + " is used for a cache configured " + - "for non-partitioned mode [cacheName=" + entry.getKey() + ", cacheMode=" + entry.getValue() + ']'); - } + return connSrvs; } /** @@ -517,7 +609,7 @@ public class GridClientImpl implements GridClient { /** {@inheritDoc} */ @Override public void iteration() throws InterruptedException { try { - tryInitTopology(); + tryInit(); } catch (GridClientException e) { top.fail(e); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientNodeStateBeforeStartImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientNodeStateBeforeStartImpl.java new file mode 100644 index 0000000..1d1f92f6 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/GridClientNodeStateBeforeStartImpl.java @@ -0,0 +1,49 @@ +/* + * 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.internal.client.impl; + +import org.apache.ignite.internal.client.GridClientException; +import org.apache.ignite.internal.client.GridClientNodeStateBeforeStart; +import org.apache.ignite.internal.processors.rest.client.message.GridClientWarmUpRequest; + +/** + * Implementation {@link GridClientNodeStateBeforeStart}. + */ +public class GridClientNodeStateBeforeStartImpl implements GridClientNodeStateBeforeStart { + /** Client instance. */ + private final GridClientImpl client; + + /** + * Constructor. + * + * @param client Client instance. + */ + public GridClientNodeStateBeforeStartImpl(GridClientImpl client) { + this.client = client; + } + + /** {@inheritDoc} */ + @Override public void stopWarmUp() throws GridClientException { + try { + client.connection().messageBeforeStart(new GridClientWarmUpRequest().stopWarmUp(true)).get(); + } + catch (InterruptedException e) { + throw new GridClientException("Interrupted when (re)trying to perform request.", e); + } + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java index 00759e0..8a60545 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java @@ -405,6 +405,15 @@ public abstract class GridClientConnection { public abstract GridClientFutureAdapter<?> forwardMessage(Object body) throws GridClientException; /** + * Sending messages before node starts and getting a response to it. + * + * @param msg A raw message to send. + * @return Future holding server's response. + * @throws GridClientException In case of error. + */ + public abstract GridClientFutureAdapter<?> messageBeforeStart(Object msg) throws GridClientException; + + /** * @return {@code True} if connection is closed. */ public boolean isClosed() { diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManager.java index dbab8be..94c9a73 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManager.java @@ -71,4 +71,16 @@ public interface GridClientConnectionManager { * (and receiving responses for all pending requests), otherwise it will return immediately. */ public void stop(boolean waitCompletion); + + /** + * Returns connection to node using given server addresses. + * + * @param srvs Server addresses. + * @return Established connection. + * @throws GridClientException If failed. + * @throws InterruptedException If was interrupted while waiting for connection to be established. + */ + public GridClientConnection connection( + Collection<InetSocketAddress> srvs + ) throws GridClientException, InterruptedException; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java index 6fde7ad..63f19c4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java @@ -54,6 +54,7 @@ import org.apache.ignite.internal.client.util.GridClientStripedLock; import org.apache.ignite.internal.client.util.GridClientUtils; import org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientMessage; +import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeStateBeforeStartRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientPingPacket; import org.apache.ignite.internal.processors.rest.protocols.tcp.GridTcpRestParser; import org.apache.ignite.internal.util.nio.GridNioCodecFilter; @@ -68,6 +69,7 @@ import org.apache.ignite.logger.java.JavaLogger; import org.apache.ignite.plugin.security.SecurityCredentials; import org.jetbrains.annotations.Nullable; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.logging.Level.INFO; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MACS; import static org.apache.ignite.internal.client.impl.connection.GridClientConnectionCloseReason.CLIENT_CLOSED; @@ -128,6 +130,9 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo /** Marshaller ID. */ private final Byte marshId; + /** Connecting to a node before starting it without getting/updating topology. */ + private final boolean beforeNodeStart; + /** * @param clientId Client ID. * @param sslCtx SSL context to enable secured connection or {@code null} to use unsecured one. @@ -135,6 +140,7 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo * @param routers Routers or empty collection to use endpoints from topology info. * @param top Topology. * @param marshId Marshaller ID. + * @param beforeNodeStart Connecting to a node before starting it without getting/updating topology. * @throws GridClientException In case of error. */ @SuppressWarnings("unchecked") @@ -144,8 +150,9 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo Collection<InetSocketAddress> routers, GridClientTopology top, @Nullable Byte marshId, - boolean routerClient) - throws GridClientException { + boolean routerClient, + boolean beforeNodeStart + ) throws GridClientException { assert clientId != null : "clientId != null"; assert cfg != null : "cfg != null"; assert routers != null : "routers != null"; @@ -156,6 +163,7 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo this.cfg = cfg; this.routers = new ArrayList<>(routers); this.top = top; + this.beforeNodeStart = beforeNodeStart; log = Logger.getLogger(getClass().getName()); @@ -218,59 +226,19 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo } /** {@inheritDoc} */ - @SuppressWarnings("BusyWait") @Override public void init(Collection<InetSocketAddress> srvs) throws GridClientException, InterruptedException { init0(); - GridClientException firstEx = null; - - for (int i = 0; i < INIT_RETRY_CNT; i++) { - Collection<InetSocketAddress> srvsCp = new ArrayList<>(srvs); - - while (!srvsCp.isEmpty()) { - GridClientConnection conn = null; - - try { - conn = connect(null, srvsCp); - - conn.topology(cfg.isAutoFetchAttributes(), cfg.isAutoFetchMetrics(), null).get(); - - return; - } - catch (GridServerUnreachableException e) { - // No connection could be opened to any of initial addresses - exit to retry loop. - assert conn == null : - "GridClientConnectionResetException was thrown from GridClientConnection#topology"; - - if (firstEx == null) - firstEx = e; - - break; - } - catch (GridClientConnectionResetException e) { - // Connection was established but topology update failed - - // trying other initial addresses if any. - assert conn != null : "GridClientConnectionResetException was thrown from connect()"; - - if (firstEx == null) - firstEx = e; - - if (!srvsCp.remove(conn.serverAddress())) - // We have misbehaving collection or equals - just exit to avoid infinite loop. - break; - } + connect(srvs, conn -> { + if (beforeNodeStart) { + conn.messageBeforeStart(new GridClientNodeStateBeforeStartRequest()) + .get(cfg.getConnectTimeout(), MILLISECONDS); } - - Thread.sleep(INIT_RETRY_INTERVAL); - } - - for (GridClientConnection c : conns.values()) { - conns.remove(c.serverAddress(), c); - - c.close(FAILED, false); - } - - throw firstEx; + else { + conn.topology(cfg.isAutoFetchAttributes(), cfg.isAutoFetchMetrics(), null) + .get(cfg.getConnectTimeout(), MILLISECONDS); + } + }); } /** @@ -553,6 +521,78 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo srv.stop(); } + /** {@inheritDoc} */ + @Override public GridClientConnection connection( + Collection<InetSocketAddress> srvs + ) throws GridClientException, InterruptedException { + return connect(srvs, null); + } + + /** + * Returns connection to node using given server addresses. + * + * @param srvs Server addresses. + * @param clo Client connection closure. + * @return Established connection. + * @throws GridClientException If failed. + * @throws InterruptedException If was interrupted while waiting for connection to be established. + */ + private GridClientConnection connect( + Collection<InetSocketAddress> srvs, + @Nullable GridClientConnectionInClosure clo + ) throws InterruptedException, GridClientException { + GridClientException firstEx = null; + + for (int i = 0; i < INIT_RETRY_CNT; i++) { + Collection<InetSocketAddress> srvsCp = new ArrayList<>(srvs); + + while (!srvsCp.isEmpty()) { + GridClientConnection conn = null; + + try { + conn = connect(null, srvsCp); + + if (clo != null) + clo.apply(conn); + + return conn; + } + catch (GridServerUnreachableException e) { + // No connection could be opened to any of initial addresses - exit to retry loop. + assert conn == null : + "GridClientConnectionResetException was thrown from GridClientConnection#topology"; + + if (firstEx == null) + firstEx = e; + + break; + } + catch (GridClientConnectionResetException e) { + // Connection was established but topology update failed - + // trying other initial addresses if any. + assert conn != null : "GridClientConnectionResetException was thrown from connect()"; + + if (firstEx == null) + firstEx = e; + + if (!srvsCp.remove(conn.serverAddress())) + // We have misbehaving collection or equals - just exit to avoid infinite loop. + break; + } + } + + Thread.sleep(INIT_RETRY_INTERVAL); + } + + for (GridClientConnection c : conns.values()) { + conns.remove(c.serverAddress(), c); + + c.close(FAILED, false); + } + + throw firstEx; + } + /** * Close all connections idling for more then * {@link GridClientConfiguration#getMaxConnectionIdleTime()} milliseconds. @@ -696,4 +736,18 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo ses.close(); } } + + /** + * Client connection in closure. + */ + @FunctionalInterface + private static interface GridClientConnectionInClosure { + /** + * Closure body. + * + * @param conn Client connection. + * @throws GridClientException If failed. + */ + void apply(GridClientConnection conn) throws GridClientException; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerOsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerOsImpl.java index 3329a3b..881f4df 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerOsImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerOsImpl.java @@ -34,12 +34,13 @@ public class GridClientConnectionManagerOsImpl extends GridClientConnectionManag * @param cfg Client configuration. * @param routers Routers or empty collection to use endpoints from topology info. * @param top Topology. + * @param beforeNodeStart Connecting to a node before starting it without getting/updating topology. * @throws GridClientException In case of error. */ public GridClientConnectionManagerOsImpl(UUID clientId, SSLContext sslCtx, GridClientConfiguration cfg, - Collection<InetSocketAddress> routers, GridClientTopology top, Byte marshId, boolean routerClient) - throws GridClientException { - super(clientId, sslCtx, cfg, routers, top, marshId, routerClient); + Collection<InetSocketAddress> routers, GridClientTopology top, Byte marshId, boolean routerClient, + boolean beforeNodeStart) throws GridClientException { + super(clientId, sslCtx, cfg, routers, top, marshId, routerClient, beforeNodeStart); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java index fefe68d..6a898e9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java @@ -67,6 +67,7 @@ import org.apache.ignite.internal.processors.rest.client.message.GridClientHands import org.apache.ignite.internal.processors.rest.client.message.GridClientMessage; import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeBean; import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeMetricsBean; +import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeStateBeforeStartRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientPingPacket; import org.apache.ignite.internal.processors.rest.client.message.GridClientResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientTaskRequest; @@ -1082,6 +1083,13 @@ public class GridClientNioTcpConnection extends GridClientConnection { return nodeBuilder.build(); } + /** {@inheritDoc} */ + @Override public GridClientFutureAdapter<?> messageBeforeStart(Object msg) throws GridClientException { + assert msg instanceof GridClientNodeStateBeforeStartRequest; + + return makeRequest((GridClientMessage)msg, new TcpClientFuture<>()); + } + /** * Future extension that holds client tcp message and auth retry flag. */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/router/impl/GridRouterClientImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/client/router/impl/GridRouterClientImpl.java index 8a5a746..163b872 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/router/impl/GridRouterClientImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/router/impl/GridRouterClientImpl.java @@ -77,7 +77,7 @@ public class GridRouterClientImpl implements GridClient { this.cliCfg = cliCfg; - clientImpl = new GridClientImpl(id, cliCfg, true); + clientImpl = new GridClientImpl(id, cliCfg, true, false); if (cliCfg.getProtocol() != GridClientProtocol.TCP) throw new AssertionError("Unknown protocol: " + cliCfg.getProtocol()); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java index 66a7a62..c97c26a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java @@ -217,7 +217,13 @@ public enum GridRestCommand { DATA_REGION_METRICS("dataregion"), /** Data storage metrics. */ - DATA_STORAGE_METRICS("datastorage"); + DATA_STORAGE_METRICS("datastorage"), + + /** Node state before its start. */ + NODE_STATE_BEFORE_START("nodestatebeforestart"), + + /** Warm-up. */ + WARM_UP("warmup"); /** Enum values. */ private static final GridRestCommand[] VALS = values(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java index 9c1cdc2..5f1ea66 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java @@ -47,6 +47,7 @@ import org.apache.ignite.internal.processors.authentication.AuthorizationContext import org.apache.ignite.internal.processors.rest.client.message.GridClientTaskResultBean; import org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandler; import org.apache.ignite.internal.processors.rest.handlers.auth.AuthenticationCommandHandler; +import org.apache.ignite.internal.processors.rest.handlers.beforeStart.NodeStateBeforeStartCommandHandler; import org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler; import org.apache.ignite.internal.processors.rest.handlers.cluster.GridBaselineCommandHandler; import org.apache.ignite.internal.processors.rest.handlers.cluster.GridChangeClusterStateCommandHandler; @@ -62,6 +63,7 @@ import org.apache.ignite.internal.processors.rest.handlers.user.UserActionComman import org.apache.ignite.internal.processors.rest.handlers.version.GridVersionCommandHandler; import org.apache.ignite.internal.processors.rest.protocols.tcp.GridTcpRestProtocol; import org.apache.ignite.internal.processors.rest.request.GridRestCacheRequest; +import org.apache.ignite.internal.processors.rest.request.GridRestNodeStateBeforeStartRequest; import org.apache.ignite.internal.processors.rest.request.GridRestRequest; import org.apache.ignite.internal.processors.rest.request.GridRestTaskRequest; import org.apache.ignite.internal.processors.rest.request.RestQueryRequest; @@ -229,7 +231,11 @@ public class GridRestProcessor extends GridProcessorAdapter implements IgniteRes * @return Future. */ private IgniteInternalFuture<GridRestResponse> handleRequest(final GridRestRequest req) { - if (startLatch.getCount() > 0) { + if (req instanceof GridRestNodeStateBeforeStartRequest) { + if (startLatch.getCount() == 0) + return new GridFinishedFuture<>(new IgniteCheckedException("Node has already started.")); + } + else if (startLatch.getCount() > 0) { try { startLatch.await(); } @@ -549,6 +555,7 @@ public class GridRestProcessor extends GridProcessorAdapter implements IgniteRes addHandler(new UserActionCommandHandler(ctx)); addHandler(new GridBaselineCommandHandler(ctx)); addHandler(new MemoryMetricsCommandHandler(ctx)); + addHandler(new NodeStateBeforeStartCommandHandler(ctx)); // Start protocols. startTcpProtocol(); @@ -571,6 +578,8 @@ public class GridRestProcessor extends GridProcessorAdapter implements IgniteRes ctx.addNodeAttribute(key, p.getValue()); } } + + proto.onProcessorStart(); } } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProtocol.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProtocol.java index 1313862..073ce0c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProtocol.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProtocol.java @@ -55,4 +55,9 @@ public interface GridRestProtocol { * Stops protocol. */ public abstract void stop(); + + /** + * Processor start callback. + */ + void onProcessorStart(); } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientNodeStateBeforeStartRequest.java similarity index 60% copy from modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java copy to modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientNodeStateBeforeStartRequest.java index d050133..c8c77bd 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientNodeStateBeforeStartRequest.java @@ -15,13 +15,19 @@ * limitations under the License. */ -package org.apache.ignite.internal.processors.cache.warmup; +package org.apache.ignite.internal.processors.rest.client.message; -import org.apache.ignite.configuration.WarmUpConfiguration; +import org.apache.ignite.internal.util.typedef.internal.S; /** - * Configuration for {@link SimpleObservableWarmUp}. + * Request to manage and obtain information about node before its start. */ -class SimpleObservableWarmUpConfiguration implements WarmUpConfiguration { - // No-op. +public class GridClientNodeStateBeforeStartRequest extends GridClientAbstractMessage { + /** Serial version uid. */ + private static final long serialVersionUID = 0L; + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(GridClientNodeStateBeforeStartRequest.class, this, super.toString()); + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientWarmUpRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientWarmUpRequest.java new file mode 100644 index 0000000..b3de271 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/client/message/GridClientWarmUpRequest.java @@ -0,0 +1,90 @@ +/* + * 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.internal.processors.rest.client.message; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Objects; +import org.apache.ignite.internal.util.typedef.internal.S; + +public class GridClientWarmUpRequest extends GridClientNodeStateBeforeStartRequest { + /** Serial version uid. */ + private static final long serialVersionUID = 0L; + + /** Stop warm-up. */ + private boolean stopWarmUp; + + /** + * Return {@code true} to stop warm-up. + * + * @return {@code true} to stop warm-up. + */ + public boolean stopWarmUp() { + return stopWarmUp; + } + + /** + * Set need to stop warm-up. + * + * @param stopWarmUp {@code true} to stop warm-up. + * @return {@code this} instance. + */ + public GridClientWarmUpRequest stopWarmUp(boolean stopWarmUp) { + this.stopWarmUp = stopWarmUp; + + return this; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeBoolean(stopWarmUp); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + stopWarmUp = in.readBoolean(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + GridClientWarmUpRequest req = (GridClientWarmUpRequest)o; + + return stopWarmUp == req.stopWarmUp; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(stopWarmUp); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(GridClientWarmUpRequest.class, this, super.toString()); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/beforeStart/NodeStateBeforeStartCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/beforeStart/NodeStateBeforeStartCommandHandler.java new file mode 100644 index 0000000..fcb2ef9 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/beforeStart/NodeStateBeforeStartCommandHandler.java @@ -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.ignite.internal.processors.rest.handlers.beforeStart; + +import java.util.Arrays; +import java.util.Collection; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.processors.rest.GridRestCommand; +import org.apache.ignite.internal.processors.rest.GridRestResponse; +import org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandlerAdapter; +import org.apache.ignite.internal.processors.rest.request.GridRestNodeStateBeforeStartRequest; +import org.apache.ignite.internal.processors.rest.request.GridRestRequest; +import org.apache.ignite.internal.processors.rest.request.GridRestWarmUpRequest; +import org.apache.ignite.internal.util.future.GridFinishedFuture; +import org.apache.ignite.internal.util.typedef.internal.U; + +/** + * Command handler for managing state of a node before it starts and getting information about it. + */ +public class NodeStateBeforeStartCommandHandler extends GridRestCommandHandlerAdapter { + /** + * Construecor. + * + * @param ctx Kernal context. + */ + public NodeStateBeforeStartCommandHandler(GridKernalContext ctx) { + super(ctx); + } + + /** {@inheritDoc} */ + @Override public Collection<GridRestCommand> supportedCommands() { + return Arrays.asList(GridRestCommand.NODE_STATE_BEFORE_START, GridRestCommand.WARM_UP); + } + + /** {@inheritDoc} */ + @Override public IgniteInternalFuture<GridRestResponse> handleAsync(GridRestRequest req) { + GridRestNodeStateBeforeStartRequest restReq = (GridRestNodeStateBeforeStartRequest)req; + + if (log.isDebugEnabled()) + log.debug("Handling REST request: " + req); + + try { + if (restReq instanceof GridRestWarmUpRequest) { + GridRestWarmUpRequest warmUpReq = (GridRestWarmUpRequest)restReq; + + if (warmUpReq.stopWarmUp()) + ctx.cache().stopWarmUp(); + } + } + catch (IgniteCheckedException e) { + U.error(log, "Failed to execute cache command: " + req, e); + + return new GridFinishedFuture<>(e); + } + + return new GridFinishedFuture<>(new GridRestResponse()); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/GridRestProtocolAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/GridRestProtocolAdapter.java index 76c6926..0a639c4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/GridRestProtocolAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/GridRestProtocolAdapter.java @@ -194,4 +194,9 @@ public abstract class GridRestProtocolAdapter implements GridRestProtocol { @Override public void onKernalStart() { // No-op. } + + /** {@inheritDoc} */ + @Override public void onProcessorStart() { + // No-op. + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestNioListener.java index 20bf5c5..29f89a4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestNioListener.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestNioListener.java @@ -41,11 +41,13 @@ import org.apache.ignite.internal.processors.rest.client.message.GridClientClust import org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientMessage; +import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeStateBeforeStartRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientPingPacket; import org.apache.ignite.internal.processors.rest.client.message.GridClientResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientStateRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientTaskRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientTopologyRequest; +import org.apache.ignite.internal.processors.rest.client.message.GridClientWarmUpRequest; import org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheRestMetrics; import org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisMessage; import org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisNioListener; @@ -53,9 +55,11 @@ import org.apache.ignite.internal.processors.rest.request.GridRestCacheRequest; import org.apache.ignite.internal.processors.rest.request.GridRestChangeStateRequest; import org.apache.ignite.internal.processors.rest.request.GridRestClusterNameRequest; import org.apache.ignite.internal.processors.rest.request.GridRestClusterStateRequest; +import org.apache.ignite.internal.processors.rest.request.GridRestNodeStateBeforeStartRequest; import org.apache.ignite.internal.processors.rest.request.GridRestRequest; import org.apache.ignite.internal.processors.rest.request.GridRestTaskRequest; import org.apache.ignite.internal.processors.rest.request.GridRestTopologyRequest; +import org.apache.ignite.internal.processors.rest.request.GridRestWarmUpRequest; import org.apache.ignite.internal.util.nio.GridNioFuture; import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter; import org.apache.ignite.internal.util.nio.GridNioSession; @@ -82,8 +86,10 @@ import static org.apache.ignite.internal.processors.rest.GridRestCommand.CLUSTER import static org.apache.ignite.internal.processors.rest.GridRestCommand.CLUSTER_STATE; import static org.apache.ignite.internal.processors.rest.GridRestCommand.EXE; import static org.apache.ignite.internal.processors.rest.GridRestCommand.NODE; +import static org.apache.ignite.internal.processors.rest.GridRestCommand.NODE_STATE_BEFORE_START; import static org.apache.ignite.internal.processors.rest.GridRestCommand.NOOP; import static org.apache.ignite.internal.processors.rest.GridRestCommand.TOPOLOGY; +import static org.apache.ignite.internal.processors.rest.GridRestCommand.WARM_UP; import static org.apache.ignite.internal.processors.rest.client.message.GridClientCacheRequest.GridCacheOperation.APPEND; import static org.apache.ignite.internal.processors.rest.client.message.GridClientCacheRequest.GridCacheOperation.CAS; import static org.apache.ignite.internal.processors.rest.client.message.GridClientCacheRequest.GridCacheOperation.GET; @@ -416,6 +422,22 @@ public class GridTcpRestNioListener extends GridNioServerListenerAdapter<GridCli } else if (msg instanceof GridClientClusterNameRequest) restReq = new GridRestClusterNameRequest(); + else if (msg instanceof GridClientNodeStateBeforeStartRequest) { + GridClientNodeStateBeforeStartRequest reqClient = (GridClientNodeStateBeforeStartRequest)msg; + + if (reqClient instanceof GridClientWarmUpRequest) { + GridClientWarmUpRequest warmUpReqClient = (GridClientWarmUpRequest)reqClient; + + restReq = new GridRestWarmUpRequest().stopWarmUp(warmUpReqClient.stopWarmUp()); + + restReq.command(WARM_UP); + } + else { + restReq = new GridRestNodeStateBeforeStartRequest(); + + restReq.command(NODE_STATE_BEFORE_START); + } + } if (restReq != null) { restReq.destinationId(msg.destinationId()); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java index 7e4637c..afb5525 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java @@ -138,8 +138,8 @@ public class GridTcpRestProtocol extends GridRestProtocolAdapter { } /** {@inheritDoc} */ - @Override public void onKernalStart() { - super.onKernalStart(); + @Override public void onProcessorStart() { + super.onProcessorStart(); Map<Byte, GridClientMarshaller> marshMap = new HashMap<>(); @@ -151,7 +151,7 @@ public class GridTcpRestProtocol extends GridRestProtocolAdapter { marshMap.put(GridClientZipOptimizedMarshaller.ID, new GridClientZipOptimizedMarshaller(optMarsh, providers)); try { - IgnitePredicate<String> clsFilter = MarshallerUtils.classNameFilter(this.getClass().getClassLoader()); + IgnitePredicate<String> clsFilter = MarshallerUtils.classNameFilter(getClass().getClassLoader()); marshMap.put(GridClientJdkMarshaller.ID, new GridClientJdkMarshaller(clsFilter)); } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestNodeStateBeforeStartRequest.java similarity index 65% copy from modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java copy to modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestNodeStateBeforeStartRequest.java index d050133..5e9c5e6 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestNodeStateBeforeStartRequest.java @@ -15,13 +15,16 @@ * limitations under the License. */ -package org.apache.ignite.internal.processors.cache.warmup; +package org.apache.ignite.internal.processors.rest.request; -import org.apache.ignite.configuration.WarmUpConfiguration; +import org.apache.ignite.internal.util.typedef.internal.S; /** - * Configuration for {@link SimpleObservableWarmUp}. + * Request to manage and obtain information about node before its start. */ -class SimpleObservableWarmUpConfiguration implements WarmUpConfiguration { - // No-op. +public class GridRestNodeStateBeforeStartRequest extends GridRestRequest { + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(GridRestNodeStateBeforeStartRequest.class, this, super.toString()); + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestWarmUpRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestWarmUpRequest.java new file mode 100644 index 0000000..37c9722 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestWarmUpRequest.java @@ -0,0 +1,54 @@ +/* + * 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.internal.processors.rest.request; + +import org.apache.ignite.internal.util.typedef.internal.S; + +/** + * Grid warm-up request. + */ +public class GridRestWarmUpRequest extends GridRestNodeStateBeforeStartRequest { + /** Stop warm-up. */ + private boolean stopWarmUp; + + /** + * Return {@code true} to stop warm-up. + * + * @return {@code true} to stop warm-up. + */ + public boolean stopWarmUp() { + return stopWarmUp; + } + + /** + * Set need to stop warm-up. + * + * @param stopWarmUp {@code true} to stop warm-up. + * @return {@code this} instance. + */ + public GridRestWarmUpRequest stopWarmUp(boolean stopWarmUp) { + this.stopWarmUp = stopWarmUp; + + return this; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(GridRestWarmUpRequest.class, this, super.toString()); + } +} diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties index f97d546..9815054 100644 --- a/modules/core/src/main/resources/META-INF/classnames.properties +++ b/modules/core/src/main/resources/META-INF/classnames.properties @@ -1630,6 +1630,8 @@ org.apache.ignite.internal.processors.rest.client.message.GridClientTaskResultBe org.apache.ignite.internal.processors.rest.client.message.GridClientTopologyRequest org.apache.ignite.internal.processors.rest.client.message.GridRouterRequest org.apache.ignite.internal.processors.rest.client.message.GridRouterResponse +org.apache.ignite.internal.processors.rest.client.message.GridClientNodeStateBeforeStartRequest +org.apache.ignite.internal.processors.rest.client.message.GridClientWarmUpRequest org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler$2 org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler$3 org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler$4 diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpConfiguration.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpConfiguration.java index 079021c..6f20023 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpConfiguration.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpConfiguration.java @@ -20,8 +20,8 @@ package org.apache.ignite.internal.processors.cache.warmup; import org.apache.ignite.configuration.WarmUpConfiguration; /** - * Configuration for {@link BlockedWarmUp}. + * Configuration for {@link BlockedWarmUpStrategy}. */ -class BlockedWarmUpConfiguration implements WarmUpConfiguration { +public class BlockedWarmUpConfiguration implements WarmUpConfiguration { // No-op. } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUp.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpStrategy.java similarity index 88% rename from modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUp.java rename to modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpStrategy.java index 25a1a3b..0244ba5 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUp.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/BlockedWarmUpStrategy.java @@ -25,12 +25,12 @@ import org.apache.ignite.internal.util.typedef.internal.U; /** * Warm-up strategy that only waits for {@link #stop} call. */ -class BlockedWarmUp implements WarmUpStrategy<BlockedWarmUpConfiguration> { +public class BlockedWarmUpStrategy implements WarmUpStrategy<BlockedWarmUpConfiguration> { /** Stop latch. */ - final CountDownLatch stopLatch = new CountDownLatch(1); + public final CountDownLatch stopLatch = new CountDownLatch(1); /** Start latch. */ - final CountDownLatch startLatch = new CountDownLatch(1); + public final CountDownLatch startLatch = new CountDownLatch(1); /** {@inheritDoc} */ @Override public Class<BlockedWarmUpConfiguration> configClass() { diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java index d050133..0246ad9 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpConfiguration.java @@ -20,7 +20,7 @@ package org.apache.ignite.internal.processors.cache.warmup; import org.apache.ignite.configuration.WarmUpConfiguration; /** - * Configuration for {@link SimpleObservableWarmUp}. + * Configuration for {@link SimpleObservableWarmUpStrategy}. */ class SimpleObservableWarmUpConfiguration implements WarmUpConfiguration { // No-op. diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUp.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpStrategy.java similarity index 94% rename from modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUp.java rename to modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpStrategy.java index e743dd5..ac327b4 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUp.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/SimpleObservableWarmUpStrategy.java @@ -26,7 +26,7 @@ import org.apache.ignite.internal.processors.cache.persistence.DataRegion; /** * Warm-up strategy that only records which regions have visited it and how many times. */ -class SimpleObservableWarmUp implements WarmUpStrategy<SimpleObservableWarmUpConfiguration> { +class SimpleObservableWarmUpStrategy implements WarmUpStrategy<SimpleObservableWarmUpConfiguration> { /** Visited regions with a counter. */ final Map<String, AtomicInteger> visitRegions = new ConcurrentHashMap<>(); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpSelfTest.java index 55acf79..4591604 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpSelfTest.java @@ -202,10 +202,10 @@ public class WarmUpSelfTest extends GridCommonAbstractTest { * Test checks that strategies are executed according to configuration. * <p> * Steps: - * 1)Starting a node with a single region that has been configured for {@link SimpleObservableWarmUp}; + * 1)Starting a node with a single region that has been configured for {@link SimpleObservableWarmUpStrategy}; * 2)Check that strategy was executed only for it region; * 3)Restarting node with default {@link SimpleObservableWarmUpConfiguration}; - * 4)Checks that {@link SimpleObservableWarmUp} was only executed for persistent regions + * 4)Checks that {@link SimpleObservableWarmUpStrategy} was only executed for persistent regions * that were not configured by {@link SimpleObservableWarmUpConfiguration}. * * @throws Exception If failed. @@ -226,7 +226,7 @@ public class WarmUpSelfTest extends GridCommonAbstractTest { startGrid(cfg); WarmUpTestPluginProvider pluginProvider = (WarmUpTestPluginProvider)cfg.getPluginProviders()[0]; - SimpleObservableWarmUp observableWarmUp = (SimpleObservableWarmUp)pluginProvider.strats.get(0); + SimpleObservableWarmUpStrategy observableWarmUp = (SimpleObservableWarmUpStrategy)pluginProvider.strats.get(0); assertEquals(1, observableWarmUp.visitRegions.size()); assertTrue(observableWarmUp.visitRegions.containsKey("2")); @@ -251,7 +251,7 @@ public class WarmUpSelfTest extends GridCommonAbstractTest { startGrid(cfg); pluginProvider = (WarmUpTestPluginProvider)cfg.getPluginProviders()[0]; - observableWarmUp = (SimpleObservableWarmUp)pluginProvider.strats.get(0); + observableWarmUp = (SimpleObservableWarmUpStrategy)pluginProvider.strats.get(0); assertEquals(2, observableWarmUp.visitRegions.size()); @@ -349,7 +349,7 @@ public class WarmUpSelfTest extends GridCommonAbstractTest { IgniteInternalFuture<IgniteEx> stratFut = GridTestUtils.runAsync(() -> startGrid(cfg)); WarmUpTestPluginProvider pluginProvider = (WarmUpTestPluginProvider)cfg.getPluginProviders()[0]; - BlockedWarmUp strat = (BlockedWarmUp)pluginProvider.strats.get(1); + BlockedWarmUpStrategy strat = (BlockedWarmUpStrategy)pluginProvider.strats.get(1); strat.startLatch.await(1, TimeUnit.MINUTES); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpTestPluginProvider.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpTestPluginProvider.java index ca8ff86..67c3553 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpTestPluginProvider.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/warmup/WarmUpTestPluginProvider.java @@ -28,11 +28,11 @@ import org.apache.ignite.plugin.PluginContext; /** * Test plugin provider for test strategies. */ -class WarmUpTestPluginProvider extends AbstractTestPluginProvider { +public class WarmUpTestPluginProvider extends AbstractTestPluginProvider { /** Collection of strategies. */ - final List<WarmUpStrategy<?>> strats = new ArrayList<>(Arrays.asList( - new SimpleObservableWarmUp(), - new BlockedWarmUp() + public final List<WarmUpStrategy<?>> strats = new ArrayList<>(Arrays.asList( + new SimpleObservableWarmUpStrategy(), + new BlockedWarmUpStrategy() )); /** {@inheritDoc} */ diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output index 0a13460..c0f5887 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output @@ -165,6 +165,9 @@ If the file name isn't specified the output file name is: '<typeId>.bin' Set new tracing configuration. If both --scope and --label are specified then add or override label specific configuration, if only --scope is specified, then override scope specific configuration. Print applied configuration. control.(sh|bat) --tracing-configuration set (--scope DISCOVERY|EXCHANGE|COMMUNICATION|TX [--label] [--sampling-rate Decimal value between 0 and 1, where 0 means never and 1 means always. More or less reflects the probability of sampling specific trace.] [--included-scopes Set of scopes with comma as separator DISCOVERY|EXCHANGE|COMMUNICATION|TX]) + Stop warm-up: + control.(sh|bat) --warm-up --stop + By default commands affecting the cluster require interactive confirmation. Use --yes option to disable it. diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output index 0a13460..c0f5887 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output @@ -165,6 +165,9 @@ If the file name isn't specified the output file name is: '<typeId>.bin' Set new tracing configuration. If both --scope and --label are specified then add or override label specific configuration, if only --scope is specified, then override scope specific configuration. Print applied configuration. control.(sh|bat) --tracing-configuration set (--scope DISCOVERY|EXCHANGE|COMMUNICATION|TX [--label] [--sampling-rate Decimal value between 0 and 1, where 0 means never and 1 means always. More or less reflects the probability of sampling specific trace.] [--included-scopes Set of scopes with comma as separator DISCOVERY|EXCHANGE|COMMUNICATION|TX]) + Stop warm-up: + control.(sh|bat) --warm-up --stop + By default commands affecting the cluster require interactive confirmation. Use --yes option to disable it. diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PartitionLossTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PartitionLossTest.cs index d138654..c4d6e19 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PartitionLossTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PartitionLossTest.cs @@ -20,7 +20,6 @@ namespace Apache.Ignite.Core.Tests.Cache using System; using System.Collections.Generic; using System.Linq; - using System.Threading; using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Cache.Affinity.Rendezvous; using Apache.Ignite.Core.Cache.Configuration; @@ -220,6 +219,9 @@ namespace Apache.Ignite.Core.Tests.Cache Backups = 0, WriteSynchronizationMode = CacheWriteSynchronizationMode.FullSync, PartitionLossPolicy = policy, + RebalanceDelay = TimeSpan.Zero, + RebalanceMode = CacheRebalanceMode.Sync, + RebalanceThrottle = TimeSpan.Zero, AffinityFunction = new RendezvousAffinityFunction { ExcludeNeighbors = false, @@ -249,13 +251,7 @@ namespace Apache.Ignite.Core.Tests.Cache // Wait for rebalance to complete. var node = ignite.GetCluster().GetLocalNode(); Func<int, bool> isPrimary = x => affinity.IsPrimary(node, x); - - while (!keys.Any(isPrimary)) - { - Thread.Sleep(10); - } - - Thread.Sleep(100); // Some extra wait. + TestUtils.WaitForTrueCondition(() => keys.Any(isPrimary)); return keys.First(isPrimary); }