This is an automated email from the ASF dual-hosted git repository.

irakov 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 ef6764e  IGNITE-12478 Add long running operation timeout to MXBean for 
manipulate in run-time - Fixes #7191.
ef6764e is described below

commit ef6764e99c318a857ec92d6a270d8ef621cfde66
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Wed Jan 29 19:47:54 2020 +0300

    IGNITE-12478 Add long running operation timeout to MXBean for manipulate in 
run-time - Fixes #7191.
    
    Signed-off-by: Ivan Rakov <[email protected]>
---
 .../org/apache/ignite/internal/IgniteFeatures.java |   5 +-
 .../org/apache/ignite/internal/IgniteKernal.java   |  47 +++--
 .../ignite/internal/TransactionsMXBeanImpl.java    |  10 +
 .../cache/LongOperationsDumpSettingsClosure.java   |  57 +++++
 .../cache/transactions/IgniteTxManager.java        |  49 ++++-
 .../apache/ignite/mxbean/TransactionsMXBean.java   |  28 +++
 .../internal/TransactionsMXBeanImplTest.java       | 235 +++++++++++++++++++--
 7 files changed, 391 insertions(+), 40 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java 
b/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
index fa6bd0a..88526f5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
@@ -85,7 +85,10 @@ public enum IgniteFeatures {
     MASTER_KEY_CHANGE(20),
 
     /** ContinuousQuery with security subject id support. */
-    CONT_QRY_SECURITY_AWARE(21);
+    CONT_QRY_SECURITY_AWARE(21),
+
+    /** Long operations dump timeout. */
+    LONG_OPERATIONS_DUMP_TIMEOUT(30);
 
     /**
      * Unique feature identifier.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java 
b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 1840451..9892574 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -233,6 +233,7 @@ import 
org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
 import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
 import org.jetbrains.annotations.Nullable;
 
+import static java.util.Objects.nonNull;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONFIG_URL;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_DAEMON;
@@ -1521,21 +1522,7 @@ public class IgniteKernal implements IgniteEx, 
IgniteMXBean, Externalizable {
             }, metricsLogFreq, metricsLogFreq);
         }
 
-        final long longOpDumpTimeout = IgniteSystemProperties.getLong(
-                IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT,
-                DFLT_LONG_OPERATIONS_DUMP_TIMEOUT
-        );
-
-        if (longOpDumpTimeout > 0) {
-            longOpDumpTask = ctx.timeout().schedule(new Runnable() {
-                @Override public void run() {
-                    GridKernalContext ctx = IgniteKernal.this.ctx;
-
-                    if (ctx != null)
-                        
ctx.cache().context().exchange().dumpLongRunningOperations(longOpDumpTimeout);
-                }
-            }, longOpDumpTimeout, longOpDumpTimeout);
-        }
+        
scheduleLongOperationsDumpTask(ctx.cache().context().tm().longOperationsDumpTimeout());
 
         ctx.performance().add("Disable assertions (remove '-ea' from JVM 
options)", !U.assertionsEnabled());
 
@@ -1561,6 +1548,36 @@ public class IgniteKernal implements IgniteEx, 
IgniteMXBean, Externalizable {
     }
 
     /**
+     * Scheduling tasks for dumping long operations. Closes current task
+     * (if any) and if the {@code longOpDumpTimeout > 0} schedules a new task
+     * with a new timeout, delay and start period equal to
+     * {@code longOpDumpTimeout}, otherwise task is deleted.
+     *
+     * @param longOpDumpTimeout Long operations dump timeout.
+     */
+    public void scheduleLongOperationsDumpTask(long longOpDumpTimeout) {
+        if (isStopping())
+            return;
+
+        synchronized (this) {
+            GridTimeoutProcessor.CancelableTask task = longOpDumpTask;
+
+            if (nonNull(task))
+                task.close();
+
+            if (longOpDumpTimeout > 0) {
+                longOpDumpTask = ctx.timeout().schedule(
+                    () -> 
ctx.cache().context().exchange().dumpLongRunningOperations(longOpDumpTimeout),
+                    longOpDumpTimeout,
+                    longOpDumpTimeout
+                );
+            }
+            else
+                longOpDumpTask = null;
+        }
+    }
+
+    /**
      * @return Ignite security processor. See {@link IgniteSecurity} for 
details.
      */
     private GridProcessor securityProcessor() throws IgniteCheckedException {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/TransactionsMXBeanImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/TransactionsMXBeanImpl.java
index f430439..4420a29 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/TransactionsMXBeanImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/TransactionsMXBeanImpl.java
@@ -172,6 +172,16 @@ public class TransactionsMXBeanImpl implements 
TransactionsMXBean {
     }
 
     /** {@inheritDoc} */
+    @Override public void setLongOperationsDumpTimeout(long timeout) {
+        
ctx.cache().context().tm().longOperationsDumpTimeoutDistributed(timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getLongOperationsDumpTimeout() {
+        return ctx.cache().context().tm().longOperationsDumpTimeout();
+    }
+
+    /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(TransactionsMXBeanImpl.class, this);
     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/LongOperationsDumpSettingsClosure.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/LongOperationsDumpSettingsClosure.java
new file mode 100644
index 0000000..edd6ebc
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/LongOperationsDumpSettingsClosure.java
@@ -0,0 +1,57 @@
+/*
+ * 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.cache;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+/**
+ * Closure that is sent to the node in order to change
+ * "Long operations dump timeout" parameter and also reschedule the task for
+ * dumping long operations.
+ */
+public class LongOperationsDumpSettingsClosure implements IgniteRunnable {
+    /** Serialization ID. */
+    private static final long serialVersionUID = 0L;
+
+    /** Long operations dump timeout. */
+    private final long longOpsDumpTimeout;
+
+    /** Auto-inject Ignite instance. */
+    @IgniteInstanceResource
+    private Ignite ignite;
+
+    /**
+     * Constructor.
+     *
+     * @param longOpsDumpTimeout Long operations dump timeout.
+     */
+    public LongOperationsDumpSettingsClosure(long longOpsDumpTimeout) {
+        this.longOpsDumpTimeout = longOpsDumpTimeout;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void run() {
+        
((IgniteEx)ignite).context().cache().context().tm().longOperationsDumpTimeout(longOpsDumpTimeout);
+
+        
((IgniteKernal)ignite).scheduleLongOperationsDumpTask(longOpsDumpTimeout);
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index 96381a5..ef849cd 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -32,9 +32,11 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteClientDisconnectedException;
+import org.apache.ignite.IgniteCompute;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.cluster.ClusterGroup;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.failure.FailureContext;
@@ -62,6 +64,7 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheReturnCompletableWra
 import 
org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheVersionedFuture;
 import 
org.apache.ignite.internal.processors.cache.GridDeferredAckMessageSender;
+import 
org.apache.ignite.internal.processors.cache.LongOperationsDumpSettingsClosure;
 import 
org.apache.ignite.internal.processors.cache.distributed.GridCacheMappedVersion;
 import 
org.apache.ignite.internal.processors.cache.distributed.GridCacheTxRecoveryFuture;
 import 
org.apache.ignite.internal.processors.cache.distributed.GridDistributedLockCancelledException;
@@ -96,6 +99,7 @@ import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.lang.IgniteReducer;
+import org.apache.ignite.lang.IgniteRunnable;
 import org.apache.ignite.spi.systemview.view.TransactionView;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
@@ -105,6 +109,7 @@ import org.jsr166.ConcurrentLinkedHashMap;
 
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_DEFERRED_ONE_PHASE_COMMIT_ACK_REQUEST_BUFFER_SIZE;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_DEFERRED_ONE_PHASE_COMMIT_ACK_REQUEST_TIMEOUT;
+import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_LONG_TRANSACTION_TIME_DUMP_THRESHOLD;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_MAX_COMPLETED_TX_COUNT;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_SLOW_TX_WARN_TIMEOUT;
@@ -113,12 +118,14 @@ import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_TRANSACTION_TIME_D
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_TX_DEADLOCK_DETECTION_MAX_ITERS;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_TX_OWNER_DUMP_REQUESTS_ALLOWED;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_WAL_LOG_TX_RECORDS;
+import static org.apache.ignite.IgniteSystemProperties.getLong;
 import static org.apache.ignite.events.EventType.EVT_NODE_FAILED;
 import static org.apache.ignite.events.EventType.EVT_NODE_JOINED;
 import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
 import static org.apache.ignite.events.EventType.EVT_TX_STARTED;
 import static org.apache.ignite.internal.GridTopic.TOPIC_CACHE_COORDINATOR;
 import static org.apache.ignite.internal.GridTopic.TOPIC_TX;
+import static 
org.apache.ignite.internal.IgniteFeatures.LONG_OPERATIONS_DUMP_TIMEOUT;
 import static 
org.apache.ignite.internal.IgniteKernal.DFLT_LONG_OPERATIONS_DUMP_TIMEOUT;
 import static 
org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL;
 import static 
org.apache.ignite.internal.processors.cache.GridCacheOperation.READ;
@@ -167,12 +174,6 @@ public class IgniteTxManager extends 
GridCacheSharedManagerAdapter {
     static int DEADLOCK_MAX_ITERS =
         
IgniteSystemProperties.getInteger(IGNITE_TX_DEADLOCK_DETECTION_MAX_ITERS, 1000);
 
-    /** Long operation dump timeout. */
-    private static final long LONG_OPERATIONS_DUMP_TIMEOUT = 
IgniteSystemProperties.getLong(
-            IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT,
-            DFLT_LONG_OPERATIONS_DUMP_TIMEOUT
-    );
-
     /** Committing transactions. */
     private final ThreadLocal<IgniteInternalTx> threadCtx = new 
ThreadLocal<>();
 
@@ -211,8 +212,7 @@ public class IgniteTxManager extends 
GridCacheSharedManagerAdapter {
      * commiting, etc) and user time (time when client node runs some code 
while holding transaction and not
      * waiting it). Equals 0 if not set. No transactions are dumped in log if 
this parameter is not set.
      */
-    private volatile long longTransactionTimeDumpThreshold =
-        
IgniteSystemProperties.getLong(IGNITE_LONG_TRANSACTION_TIME_DUMP_THRESHOLD, 0);
+    private volatile long longTransactionTimeDumpThreshold = 
getLong(IGNITE_LONG_TRANSACTION_TIME_DUMP_THRESHOLD, 0);
 
     /**
      * The coefficient for samples of completed transactions that will be 
dumped in log.
@@ -249,7 +249,8 @@ public class IgniteTxManager extends 
GridCacheSharedManagerAdapter {
     private int slowTxWarnTimeout = SLOW_TX_WARN_TIMEOUT;
 
     /** Long operations dump timeout. */
-    private long longOpsDumpTimeout = LONG_OPERATIONS_DUMP_TIMEOUT;
+    private volatile long longOpsDumpTimeout =
+        getLong(IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, 
DFLT_LONG_OPERATIONS_DUMP_TIMEOUT);
 
     /** */
     private TxDumpsThrottling txDumpsThrottling = new TxDumpsThrottling();
@@ -2739,6 +2740,36 @@ public class IgniteTxManager extends 
GridCacheSharedManagerAdapter {
     }
 
     /**
+     * Setting (for all nodes) a timeout (in millis) for printing long-running
+     * transactions as well as transactions that cannot receive locks for all
+     * their keys for a long time. Set less than or equal {@code 0} to disable.
+     *
+     * @param longOpsDumpTimeout Long operations dump timeout.
+     */
+    public void longOperationsDumpTimeoutDistributed(long longOpsDumpTimeout) {
+        broadcastToNodesSupportingFeature(
+            new LongOperationsDumpSettingsClosure(longOpsDumpTimeout),
+            LONG_OPERATIONS_DUMP_TIMEOUT
+        );
+    }
+
+    /**
+     * Broadcasts given job to nodes that support ignite feature.
+     *
+     * @param job Ignite job.
+     * @param feature Ignite feature.
+     */
+    private void broadcastToNodesSupportingFeature(IgniteRunnable job, 
IgniteFeatures feature) {
+        ClusterGroup grp = cctx.kernalContext().grid()
+            .cluster()
+            .forPredicate(node -> IgniteFeatures.nodeSupports(node, feature));
+
+        IgniteCompute compute = cctx.kernalContext().grid().compute(grp);
+
+        compute.broadcast(job);
+    }
+
+    /**
      * Transactions recovery initialization runnable.
      */
     private final class TxRecoveryInitRunnable implements Runnable {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/mxbean/TransactionsMXBean.java 
b/modules/core/src/main/java/org/apache/ignite/mxbean/TransactionsMXBean.java
index 4efef27..245d9c0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/mxbean/TransactionsMXBean.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/mxbean/TransactionsMXBean.java
@@ -218,4 +218,32 @@ public interface TransactionsMXBean {
     @MXBeanParametersNames("limit")
     @MXBeanParametersDescriptions("Samples per second limit.")
     public void setTransactionTimeDumpSamplesPerSecondLimit(int limit);
+
+    /**
+     * Setting a timeout (in millis) for printing long-running transactions as
+     * well as transactions that cannot receive locks for all their keys for a
+     * long time. Set less than or equal {@code 0} to disable.
+     *
+     * @param timeout Timeout.
+     */
+    @MXBeanDescription(
+        "Setting a timeout (in millis) for printing long-running transactions 
as well as transactions that cannot " +
+            "receive locks for all their keys for a long time. Set less than 
or equal {@code 0} to disable."
+    )
+    @MXBeanParametersNames("timeout")
+    @MXBeanParametersDescriptions("Long operations dump timeout.")
+    void setLongOperationsDumpTimeout(long timeout);
+
+    /**
+     * Returns a timeout (in millis) for printing long-running transactions as
+     * well as transactions that cannot receive locks for all their keys for a
+     * long time. Returns {@code 0} or less if not set.
+     *
+     * @return Timeout.
+     */
+    @MXBeanDescription(
+        "Returns a timeout (in millis) for printing long-running transactions 
as well as transactions that cannot " +
+            "receive locks for all their keys for a long time. Returns {@code 
0} or less if not set."
+    )
+    long getLongOperationsDumpTimeout();
 }
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/TransactionsMXBeanImplTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/TransactionsMXBeanImplTest.java
index 9b4a0a2..9c2fa4d 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/TransactionsMXBeanImplTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/TransactionsMXBeanImplTest.java
@@ -18,6 +18,9 @@
 package org.apache.ignite.internal;
 
 import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Predicate;
 import javax.management.MBeanServer;
 import javax.management.MBeanServerInvocationHandler;
 import javax.management.ObjectName;
@@ -25,42 +28,64 @@ import org.apache.ignite.cache.CacheRebalanceMode;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import 
org.apache.ignite.internal.processors.cache.transactions.TransactionProxyImpl;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.mxbean.TransactionsMXBean;
+import org.apache.ignite.testframework.ListeningTestLogger;
+import org.apache.ignite.testframework.LogListener;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
 import org.junit.Test;
 
+import static java.util.Collections.singletonMap;
+import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT;
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
+import static org.apache.ignite.testframework.LogListener.matches;
 
 /**
  *
  */
 public class TransactionsMXBeanImplTest extends GridCommonAbstractTest {
+    /** Listener log messages. */
+    private static ListeningTestLogger testLog;
+
+    /** Client node. */
+    private boolean clientNode;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        testLog = new ListeningTestLogger(false, log);
+    }
+
     /** {@inheritDoc} */
     @Override protected void afterTest() throws Exception {
         stopAllGrids();
 
+        testLog.clearListeners();
+
         super.afterTest();
     }
 
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String name) 
throws Exception {
-        final IgniteConfiguration cfg = super.getConfiguration(name);
-
-        cfg.setCommunicationSpi(new TestRecordingCommunicationSpi());
-
-        final CacheConfiguration cCfg = new CacheConfiguration()
-            .setName(DEFAULT_CACHE_NAME)
-            .setAffinity(new RendezvousAffinityFunction(false, 32))
-            .setBackups(1)
-            .setAtomicityMode(TRANSACTIONAL)
-            .setRebalanceMode(CacheRebalanceMode.ASYNC)
-            .setWriteSynchronizationMode(FULL_SYNC);
-
-        cfg.setCacheConfiguration(cCfg);
-
-        return cfg;
+        return super.getConfiguration(name)
+            .setCommunicationSpi(new TestRecordingCommunicationSpi())
+            .setGridLogger(testLog)
+            .setClientMode(clientNode)
+            .setCacheConfiguration(
+                new CacheConfiguration<>()
+                    .setName(DEFAULT_CACHE_NAME)
+                    .setAffinity(new RendezvousAffinityFunction(false, 32))
+                    .setBackups(1)
+                    .setAtomicityMode(TRANSACTIONAL)
+                    .setRebalanceMode(CacheRebalanceMode.ASYNC)
+                    .setWriteSynchronizationMode(FULL_SYNC)
+            );
     }
 
     /**
@@ -96,6 +121,186 @@ public class TransactionsMXBeanImplTest extends 
GridCommonAbstractTest {
     }
 
     /**
+     * Test for changing lrt timeout and their appearance before default
+     * timeout through MXBean.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = 
"60000")
+    public void testLongOperationsDumpTimeoutPositive() throws Exception {
+        checkLongOperationsDumpTimeoutViaTxMxBean(60_000, 100, 10_000, true);
+    }
+
+    /**
+     * Test to disable the LRT by setting timeout to 0.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = 
"100")
+    public void testLongOperationsDumpTimeoutZero() throws Exception {
+        checkLongOperationsDumpTimeoutViaTxMxBean(100, 0, 1_000, false);
+    }
+
+    /**
+     * Test to disable the LRT by setting timeout to -1.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = 
"100")
+    public void testLongOperationsDumpTimeoutNegative() throws Exception {
+        checkLongOperationsDumpTimeoutViaTxMxBean(100, -1, 1_000, false);
+    }
+
+    /**
+     * Test to verify the correct change of "Long operations dump timeout." in
+     * an immutable cluster.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = 
"100")
+    public void testChangeLongOperationsDumpTimeoutOnImmutableCluster() throws 
Exception {
+        Map<IgniteEx, TransactionsMXBean> allNodes = new HashMap<>();
+
+        for (int i = 0; i < 2; i++)
+            allNodes.put(startGrid(i), txMXBean(i));
+
+        clientNode = true;
+
+        for (int i = 2; i < 4; i++)
+            allNodes.put(startGrid(i), txMXBean(i));
+
+        //check for default value
+        checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, 100L);
+
+        //check update value via server node
+        long newTimeout = 200L;
+        updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> 
!node.configuration().isClientMode(), newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
+
+        //check update value via client node
+        newTimeout = 300L;
+        updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> 
node.configuration().isClientMode(), newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
+    }
+
+    /**
+     * Test to verify the correct change of "Long operations dump timeout." in
+     * an mutable cluster.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, value = 
"100")
+    public void testChangeLongOperationsDumpTimeoutOnMutableCluster() throws 
Exception {
+        Map<IgniteEx, TransactionsMXBean> node0 = singletonMap(startGrid(0), 
txMXBean(0));
+        Map<IgniteEx, TransactionsMXBean> node1 = singletonMap(startGrid(1), 
txMXBean(1));
+
+        Map<IgniteEx, TransactionsMXBean> allNodes = new HashMap<>();
+        allNodes.putAll(node0);
+        allNodes.putAll(node1);
+
+        long newTimeout = 200L;
+        updateLongOperationsDumpTimeoutViaTxMxBean(allNodes, node -> true, 
newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(allNodes, newTimeout);
+        allNodes.clear();
+
+        stopGrid(1);
+        node1 = singletonMap(startGrid(1), txMXBean(1));
+
+        //check that default value in restart node
+        long defTimeout = 100L;
+        checkLongOperationsDumpTimeoutViaTxMxBean(node0, newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(node1, defTimeout);
+
+        newTimeout = 300L;
+        updateLongOperationsDumpTimeoutViaTxMxBean(node0, node -> true, 
newTimeout);
+
+        Map<IgniteEx, TransactionsMXBean> node2 = singletonMap(startGrid(2), 
txMXBean(2));
+
+        //check that default value in new node
+        checkLongOperationsDumpTimeoutViaTxMxBean(node0, newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(node1, newTimeout);
+        checkLongOperationsDumpTimeoutViaTxMxBean(node2, defTimeout);
+    }
+
+    /**
+     * Search for the first node by the predicate and change
+     * "Long operations dump timeout." through TransactionsMXBean.
+     *
+     * @param nodes Nodes with TransactionsMXBean's.
+     * @param nodePred Predicate to search for a node.
+     * @param newTimeout New timeout.
+     */
+    private void updateLongOperationsDumpTimeoutViaTxMxBean(
+        Map<IgniteEx, TransactionsMXBean> nodes,
+        Predicate<? super IgniteEx> nodePred,
+        long newTimeout
+    ) {
+        assertNotNull(nodes);
+        assertNotNull(nodePred);
+
+        nodes.entrySet().stream()
+            .filter(e -> nodePred.test(e.getKey()))
+            
.findAny().get().getValue().setLongOperationsDumpTimeout(newTimeout);
+    }
+
+    /**
+     * Checking the value of "Long operations dump timeout." on all nodes
+     * through the TransactionsMXBean.
+     *
+     * @param nodes Nodes with TransactionsMXBean's.
+     * @param checkTimeout Checked timeout.
+     */
+    private void checkLongOperationsDumpTimeoutViaTxMxBean(Map<IgniteEx, 
TransactionsMXBean> nodes, long checkTimeout) {
+        assertNotNull(nodes);
+
+        nodes.forEach((node, txMxBean) -> assertEquals(checkTimeout, 
txMxBean.getLongOperationsDumpTimeout()));
+    }
+
+    /**
+     * Checking changes and receiving lrt through MXBean.
+     *
+     * @param defTimeout Default lrt timeout.
+     * @param newTimeout New lrt timeout.
+     * @param waitTimeTx Waiting time for a lrt.
+     * @param expectTx Expect or not a lrt to log.
+     * @throws Exception If failed.
+     */
+    private void checkLongOperationsDumpTimeoutViaTxMxBean(
+        long defTimeout,
+        long newTimeout,
+        long waitTimeTx,
+        boolean expectTx
+    ) throws Exception {
+        IgniteEx ignite = startGrid(0);
+
+        TransactionsMXBean txMXBean = txMXBean(0);
+
+        assertEquals(defTimeout, txMXBean.getLongOperationsDumpTimeout());
+
+        Transaction tx = ignite.transactions().txStart();
+
+        LogListener lrtLogLsnr = matches("First 10 long running transactions 
[total=1]").build();
+        LogListener txLogLsnr = 
matches(((TransactionProxyImpl)tx).tx().xidVersion().toString()).build();
+
+        testLog.registerListener(lrtLogLsnr);
+        testLog.registerListener(txLogLsnr);
+
+        txMXBean.setLongOperationsDumpTimeout(newTimeout);
+
+        assertEquals(newTimeout, 
ignite.context().cache().context().tm().longOperationsDumpTimeout());
+
+        if (expectTx)
+            assertTrue(waitForCondition(() -> lrtLogLsnr.check() && 
txLogLsnr.check(), waitTimeTx));
+        else
+            assertFalse(waitForCondition(() -> lrtLogLsnr.check() && 
txLogLsnr.check(), waitTimeTx));
+    }
+
+    /**
      *
      */
     private TransactionsMXBean txMXBean(int igniteInt) throws Exception {

Reply via email to