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 71b1f54 IGNITE-12516 Dump active transaction from near node does not
work if transaction not follow first - Fixes #7221.
71b1f54 is described below
commit 71b1f54557293faaea703cb38f2e6c8eeb57402d
Author: denis-chudov <[email protected]>
AuthorDate: Wed Jan 29 19:43:38 2020 +0300
IGNITE-12516 Dump active transaction from near node does not work if
transaction not follow first - Fixes #7221.
Signed-off-by: Ivan Rakov <[email protected]>
---
.../cache/FetchActiveTxOwnerTraceClosure.java | 37 ++-----
.../cache/GridCachePartitionExchangeManager.java | 121 +++++++++++----------
...CacheLongRunningTransactionDiagnosticsTest.java | 35 +++---
3 files changed, 90 insertions(+), 103 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/FetchActiveTxOwnerTraceClosure.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/FetchActiveTxOwnerTraceClosure.java
index 0c51c83..4020f84 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/FetchActiveTxOwnerTraceClosure.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/FetchActiveTxOwnerTraceClosure.java
@@ -16,12 +16,10 @@
*/
package org.apache.ignite.internal.processors.cache;
+import org.apache.ignite.internal.util.GridStringBuilder;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteCallable;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
/**
* Closure that is computed on near node to get the stack trace of active
transaction owner thread.
*/
@@ -30,9 +28,6 @@ public class FetchActiveTxOwnerTraceClosure implements
IgniteCallable<String> {
private static final long serialVersionUID = 0L;
/** */
- private static final StackTraceElement[] STACK_TRACE_ELEMENT_EMPTY = new
StackTraceElement[0];
-
- /** */
private final long txOwnerThreadId;
/** */
@@ -47,33 +42,15 @@ public class FetchActiveTxOwnerTraceClosure implements
IgniteCallable<String> {
* @throws Exception If failed
*/
@Override public String call() throws Exception {
- StringBuilder traceDump = new StringBuilder("Stack trace of the
transaction owner thread:\n");
-
- for (StackTraceElement stackTraceElement : getStackTrace()) {
- traceDump.append(stackTraceElement.toString());
- traceDump.append("\n");
- }
-
- return traceDump.toString();
- }
-
- /**
- * Gets the stack trace of the transaction owner thread
- *
- * @return stack trace elements
- */
- private StackTraceElement[] getStackTrace() {
- ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
-
- ThreadInfo threadInfo;
+ GridStringBuilder traceDump = new GridStringBuilder("Stack trace of
the transaction owner thread:\n");
try {
- threadInfo = threadMXBean.getThreadInfo(txOwnerThreadId,
Integer.MAX_VALUE);
+ U.printStackTrace(txOwnerThreadId, traceDump);
}
- catch (SecurityException | IllegalArgumentException ignored) {
- threadInfo = null;
+ catch (SecurityException | IllegalArgumentException e) {
+ traceDump = new GridStringBuilder("Could not get stack trace of
the transaction owner thread: " + e.getMessage());
}
- return threadInfo == null ? STACK_TRACE_ELEMENT_EMPTY :
threadInfo.getStackTrace();
+ return traceDump.toString();
}
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
index 9d9917a..308e6a4 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
@@ -2151,7 +2152,11 @@ public class GridCachePartitionExchangeManager<K, V>
extends GridCacheSharedMana
if (warnings.canAddMessage()) {
warnings.add(longRunningTransactionWarning(tx,
curTime));
- if (ltrDumpLimiter.allowAction(tx))
+ if (cctx.tm().txOwnerDumpRequestsAllowed()
+ &&
!Optional.ofNullable(cctx.kernalContext().config().isClientMode()).orElse(false)
+ && tx.local()
+ && tx.state() == TransactionState.ACTIVE
+ && ltrDumpLimiter.allowAction(tx))
dumpLongRunningTransaction(tx);
}
else
@@ -2232,77 +2237,75 @@ public class GridCachePartitionExchangeManager<K, V>
extends GridCacheSharedMana
* @param tx Transaction.
*/
private void dumpLongRunningTransaction(IgniteInternalTx tx) {
- if (cctx.tm().txOwnerDumpRequestsAllowed() && tx.local() && tx.state()
== TransactionState.ACTIVE) {
- Collection<UUID> masterNodeIds = tx.masterNodeIds();
+ Collection<UUID> masterNodeIds = tx.masterNodeIds();
- if (masterNodeIds.size() == 1) {
- UUID nearNodeId = masterNodeIds.iterator().next();
+ if (masterNodeIds.size() == 1) {
+ UUID nearNodeId = masterNodeIds.iterator().next();
- long txOwnerThreadId = tx.threadId();
+ long txOwnerThreadId = tx.threadId();
- Ignite ignite = cctx.kernalContext().grid();
+ Ignite ignite = cctx.kernalContext().grid();
- ClusterGroup nearNode = ignite.cluster().forNodeId(nearNodeId);
+ ClusterGroup nearNode = ignite.cluster().forNodeId(nearNodeId);
- String txRequestInfo = String.format(
- "[xidVer=%s, nodeId=%s]",
- tx.xidVersion().toString(),
- nearNodeId.toString()
- );
+ String txRequestInfo = String.format(
+ "[xidVer=%s, nodeId=%s]",
+ tx.xidVersion().toString(),
+ nearNodeId.toString()
+ );
- if (allNodesSupports(nearNode.nodes(),
TRANSACTION_OWNER_THREAD_DUMP_PROVIDING)) {
- IgniteCompute compute =
ignite.compute(ignite.cluster().forNodeId(nearNodeId));
+ if (allNodesSupports(nearNode.nodes(),
TRANSACTION_OWNER_THREAD_DUMP_PROVIDING)) {
+ IgniteCompute compute =
ignite.compute(ignite.cluster().forNodeId(nearNodeId));
- try {
- compute
- .callAsync(new
FetchActiveTxOwnerTraceClosure(txOwnerThreadId))
- .listen(new
IgniteInClosure<IgniteFuture<String>>() {
- @Override public void
apply(IgniteFuture<String> strIgniteFut) {
- String traceDump = null;
+ try {
+ compute
+ .callAsync(new
FetchActiveTxOwnerTraceClosure(txOwnerThreadId))
+ .listen(new IgniteInClosure<IgniteFuture<String>>() {
+ @Override public void apply(IgniteFuture<String>
strIgniteFut) {
+ String traceDump = null;
- try {
- traceDump = strIgniteFut.get();
- }
- catch (ClusterGroupEmptyException e) {
- U.error(
- diagnosticLog,
- "Could not get thread dump from
transaction owner because near node " +
- "is now out of topology. "
+ txRequestInfo
- );
- }
- catch (Exception e) {
- U.error(
- diagnosticLog,
- "Could not get thread dump from
transaction owner near node " + txRequestInfo,
- e
- );
- }
+ try {
+ traceDump = strIgniteFut.get();
+ }
+ catch (ClusterGroupEmptyException e) {
+ U.error(
+ diagnosticLog,
+ "Could not get thread dump from
transaction owner because near node " +
+ "is out of topology now. " +
txRequestInfo
+ );
+ }
+ catch (Exception e) {
+ U.error(
+ diagnosticLog,
+ "Could not get thread dump from
transaction owner near node " + txRequestInfo,
+ e
+ );
+ }
- if (traceDump != null) {
- U.warn(
- diagnosticLog,
- String.format(
- "Dumping the near node thread
that started transaction %s\n%s",
- txRequestInfo,
- traceDump
- )
- );
- }
+ if (traceDump != null) {
+ U.warn(
+ diagnosticLog,
+ String.format(
+ "Dumping the near node thread that
started transaction %s\n%s",
+ txRequestInfo,
+ traceDump
+ )
+ );
}
- });
- }
- catch (Exception e) {
- U.error(diagnosticLog, "Could not send dump request to
transaction owner near node " + txRequestInfo, e);
- }
+ }
+ });
}
- else {
- U.warn(
- diagnosticLog,
- "Could not send dump request to transaction owner near
node: node does not support this feature. " +
- txRequestInfo
- );
+ catch (Exception e) {
+ U.error(diagnosticLog, "Could not send dump request to
transaction owner near node " + txRequestInfo, e);
}
}
+ else {
+ U.warn(
+ diagnosticLog,
+ "Could not send dump request to transaction owner near
node: node does not support this feature. " +
+ txRequestInfo
+ );
+ }
}
}
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheLongRunningTransactionDiagnosticsTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheLongRunningTransactionDiagnosticsTest.java
index 00ac8b5..196a6ad 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheLongRunningTransactionDiagnosticsTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheLongRunningTransactionDiagnosticsTest.java
@@ -16,10 +16,6 @@
*/
package org.apache.ignite.internal.processors.cache;
-import java.lang.management.ManagementFactory;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.GridJobExecuteRequest;
@@ -27,8 +23,9 @@ import org.apache.ignite.internal.GridTopic;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.TestRecordingCommunicationSpi;
import org.apache.ignite.internal.TransactionsMXBeanImpl;
-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.common.GridCommonAbstractTest;
import org.apache.ignite.transactions.Transaction;
import org.junit.Test;
@@ -55,6 +52,9 @@ public class GridCacheLongRunningTransactionDiagnosticsTest
extends GridCommonAb
/** */
private static String longOpTimeoutCommon;
+ /** */
+ private final LogListener dumpLsnr = LogListener.matches("Dumping the near
node thread that started transaction").build();
+
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
@@ -77,6 +77,12 @@ public class GridCacheLongRunningTransactionDiagnosticsTest
extends GridCommonAb
cfg.setCacheConfiguration(ccfg);
}
+ ListeningTestLogger testLog = new ListeningTestLogger(false, log);
+
+ testLog.registerListener(dumpLsnr);
+
+ cfg.setGridLogger(testLog);
+
return cfg;
}
@@ -154,6 +160,8 @@ public class GridCacheLongRunningTransactionDiagnosticsTest
extends GridCommonAb
* @throws Exception if failed.
*/
private void imitateLongTransaction(boolean shouldRcvThreadDumpReq) throws
Exception {
+ dumpLsnr.reset();
+
final int val = 0;
final IgniteEx client = startGrid("client");
@@ -181,20 +189,19 @@ public class
GridCacheLongRunningTransactionDiagnosticsTest extends GridCommonAb
shouldRcvThreadDumpReq,
FetchActiveTxOwnerTraceClosure.class.getName().equals(taskNameContainer.toString())
);
+
+ assertEquals(shouldRcvThreadDumpReq, dumpLsnr.check());
}
/**
*
*/
private TransactionsMXBean txMXBean(int igniteInt) throws Exception {
- ObjectName mbeanName =
U.makeMBeanName(getTestIgniteInstanceName(igniteInt), "Transactions",
- TransactionsMXBeanImpl.class.getSimpleName());
-
- MBeanServer mbeanSrv = ManagementFactory.getPlatformMBeanServer();
-
- if (!mbeanSrv.isRegistered(mbeanName))
- fail("MBean is not registered: " + mbeanName.getCanonicalName());
-
- return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv,
mbeanName, TransactionsMXBean.class, true);
+ return getMxBean(
+ getTestIgniteInstanceName(igniteInt),
+ "Transactions",
+ TransactionsMXBean.class,
+ TransactionsMXBeanImpl.class
+ );
}
}