diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientClusterImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientClusterImpl.java
index 6dfc5bf483e65..e2fba8e0113b7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientClusterImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientClusterImpl.java
@@ -26,7 +26,7 @@
/**
* Implementation of {@link ClientCluster}.
*/
-class ClientClusterImpl extends ClientClusterGroupImpl implements ClientCluster {
+public class ClientClusterImpl extends ClientClusterGroupImpl implements ClientCluster {
/** Default cluster group. */
private final ClientClusterGroupImpl dfltClusterGrp;
@@ -54,6 +54,20 @@ class ClientClusterImpl extends ClientClusterGroupImpl implements ClientCluster
/** {@inheritDoc} */
@Override public void state(ClusterState newState) throws ClientException {
+ state(newState, true);
+ }
+
+ /**
+ * Changes current cluster state to given {@code newState} cluster state.
+ *
+ * NOTE:
+ * Deactivation clears in-memory caches (without persistence) including the system caches.
+ *
+ * @param newState New cluster state.
+ * @param forceDeactivation If {@code true}, cluster deactivation will be forced.
+ * @throws ClientException If change state operation failed.
+ */
+ public void state(ClusterState newState, boolean forceDeactivation) throws ClientException {
try {
ch.service(ClientOperation.CLUSTER_CHANGE_STATE,
req -> {
@@ -67,6 +81,14 @@ class ClientClusterImpl extends ClientClusterGroupImpl implements ClientCluster
}
req.out().writeByte((byte)newState.ordinal());
+
+ if (protocolCtx.isFeatureSupported(ProtocolBitmaskFeature.FORCE_DEACTIVATION_FLAG))
+ req.out().writeBoolean(forceDeactivation);
+ else if (!forceDeactivation) {
+ throw new ClientFeatureNotSupportedByServerException(
+ "Force deactivation flag is not supported by the server"
+ );
+ }
},
null
);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
index 1a0fb9d714829..e3ff013fd8604 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
@@ -21,6 +21,7 @@
import java.util.Collection;
import java.util.EnumSet;
import org.apache.ignite.client.ClientServices;
+import org.apache.ignite.cluster.ClusterState;
/**
* Defines supported bitmask features for thin client.
@@ -83,7 +84,10 @@ public enum ProtocolBitmaskFeature {
CACHE_INVOKE(17),
/** Transaction aware queries. */
- TX_AWARE_QUERIES(18);
+ TX_AWARE_QUERIES(18),
+
+ /** Force deactivation flag. See {@link org.apache.ignite.client.ClientCluster#state(ClusterState, boolean)}. */
+ FORCE_DEACTIVATION_FLAG(19);
/** */
private static final EnumSet ALL_FEATURES_AS_ENUM_SET =
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
index d51b8eaaa743e..dc3187b955453 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
@@ -19,6 +19,7 @@
import java.util.EnumSet;
import org.apache.ignite.client.ClientServices;
+import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.internal.ThinProtocolFeature;
import org.apache.ignite.internal.client.thin.TcpClientCache;
@@ -81,7 +82,10 @@ public enum ClientBitmaskFeature implements ThinProtocolFeature {
CACHE_INVOKE(17),
/** Transaction aware queries. */
- TX_AWARE_QUERIES(18);
+ TX_AWARE_QUERIES(18),
+
+ /** Force deactivation flag. See {@link org.apache.ignite.client.ClientCluster#state(ClusterState, boolean)}. */
+ FORCE_DEACTIVATION_FLAG(19);
/** */
private static final EnumSet ALL_FEATURES_AS_ENUM_SET =
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index 60a897685d353..8684a6a1fed36 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -615,7 +615,7 @@ public ClientListenerRequest decode(BinaryReaderExImpl reader) {
return new ClientClusterGetStateRequest(reader);
case OP_CLUSTER_CHANGE_STATE:
- return new ClientClusterChangeStateRequest(reader);
+ return new ClientClusterChangeStateRequest(reader, protocolCtx);
case OP_CLUSTER_CHANGE_WAL_STATE:
return new ClientClusterWalChangeStateRequest(reader);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cluster/ClientClusterChangeStateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cluster/ClientClusterChangeStateRequest.java
index e8b737962c4d7..126f056591b1d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cluster/ClientClusterChangeStateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cluster/ClientClusterChangeStateRequest.java
@@ -17,12 +17,17 @@
package org.apache.ignite.internal.processors.platform.client.cluster;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.binary.BinaryRawReader;
import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientProtocolContext;
import org.apache.ignite.internal.processors.platform.client.ClientRequest;
import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import static org.apache.ignite.internal.processors.platform.client.ClientBitmaskFeature.FORCE_DEACTIVATION_FLAG;
+
/**
* Cluster status request.
*/
@@ -30,21 +35,35 @@ public class ClientClusterChangeStateRequest extends ClientRequest {
/** Next state. */
private final ClusterState state;
+ /** If {@code true}, cluster deactivation will be forced. */
+ private final boolean forceDeactivation;
+
/**
* Constructor.
*
* @param reader Reader.
*/
- public ClientClusterChangeStateRequest(BinaryRawReader reader) {
+ public ClientClusterChangeStateRequest(BinaryRawReader reader, ClientProtocolContext protocolCtx) {
super(reader);
state = ClusterState.fromOrdinal(reader.readByte());
+ forceDeactivation = !protocolCtx.isFeatureSupported(FORCE_DEACTIVATION_FLAG) || reader.readBoolean();
}
/** {@inheritDoc} */
@Override public ClientResponse process(ClientConnectionContext ctx) {
- ctx.kernalContext().grid().cluster().state(state);
+ try {
+ ctx.kernalContext().state().changeGlobalState(
+ state,
+ forceDeactivation,
+ ctx.kernalContext().cluster().get().forServers().nodes(),
+ false
+ ).get();
- return new ClientResponse(requestId());
+ return new ClientResponse(requestId());
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
}
}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ClusterApiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ClusterApiTest.java
index 5540ea3833a60..5d031dca3d9f9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ClusterApiTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ClusterApiTest.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.client.thin;
import org.apache.ignite.IgniteCluster;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.client.ClientCacheConfiguration;
import org.apache.ignite.client.ClientCluster;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.cluster.ClusterState;
@@ -26,6 +28,8 @@
import org.apache.ignite.configuration.IgniteConfiguration;
import org.junit.Test;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
+
/**
* Checks cluster state/WAL state operations for thin client.
*/
@@ -35,7 +39,9 @@ public class ClusterApiTest extends AbstractThinClientTest {
return super.getConfiguration(igniteInstanceName)
.setDataStorageConfiguration(new DataStorageConfiguration()
.setDefaultDataRegionConfiguration(new DataRegionConfiguration()
- .setPersistenceEnabled(true)))
+ .setPersistenceEnabled(true))
+ .setDataRegionConfigurations(new DataRegionConfiguration()
+ .setName("non-persistent")))
.setClusterStateOnStart(ClusterState.INACTIVE);
}
@@ -73,6 +79,30 @@ public void testClusterState() throws Exception {
}
}
+ /**
+ * Test change cluster state operation by thin client.
+ */
+ @Test
+ public void testForceDeactivation() {
+ try (IgniteClient client = startClient(0)) {
+ client.cluster().state(ClusterState.ACTIVE);
+
+ client.getOrCreateCache(new ClientCacheConfiguration()
+ .setName("non-persistent-cache")
+ .setDataRegionName("non-persistent"));
+
+ assertThrows(log, () -> ((ClientClusterImpl)client.cluster()).state(ClusterState.INACTIVE, false),
+ IgniteException.class, "Deactivation stopped. " +
+ "Deactivation clears in-memory caches (without persistence) including the system caches.");
+
+ assertTrue(grid(0).cluster().state().active());
+
+ ((ClientClusterImpl)client.cluster()).state(ClusterState.INACTIVE, true);
+
+ assertFalse(grid(0).cluster().state().active());
+ }
+ }
+
/**
* Test change WAL state for cache operation by thin client.
*/