Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id BFDA1200B4A for ; Wed, 20 Jul 2016 14:34:39 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id BE47F160A73; Wed, 20 Jul 2016 12:34:39 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 1C946160A64 for ; Wed, 20 Jul 2016 14:34:37 +0200 (CEST) Received: (qmail 94271 invoked by uid 500); 20 Jul 2016 12:34:37 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 94258 invoked by uid 99); 20 Jul 2016 12:34:37 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 20 Jul 2016 12:34:37 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 22AB0E04BA; Wed, 20 Jul 2016 12:34:37 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: ptupitsyn@apache.org To: commits@ignite.apache.org Message-Id: <75ec63524b5e477f9666e60a013c34e2@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ignite git commit: IGNITE-1433 .NET: Add Java stack trace to IgniteException Date: Wed, 20 Jul 2016 12:34:37 +0000 (UTC) archived-at: Wed, 20 Jul 2016 12:34:39 -0000 Repository: ignite Updated Branches: refs/heads/master 0a5085060 -> 1f4e51eaa IGNITE-1433 .NET: Add Java stack trace to IgniteException This closes #874 Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1f4e51ea Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1f4e51ea Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1f4e51ea Branch: refs/heads/master Commit: 1f4e51eaa79120eb7f370fc65fe0d170527b85b7 Parents: 0a50850 Author: Pavel Tupitsyn Authored: Wed Jul 20 15:34:25 2016 +0300 Committer: Pavel Tupitsyn Committed: Wed Jul 20 15:34:25 2016 +0300 ---------------------------------------------------------------------- .../platform/cache/PlatformCache.java | 2 + .../platform/compute/PlatformAbstractTask.java | 1 + .../platform/utils/PlatformFutureUtils.java | 2 + .../platform/utils/PlatformUtils.java | 12 +++ .../platforms/cpp/jni/include/ignite/jni/java.h | 8 +- modules/platforms/cpp/jni/src/java.cpp | 47 ++++++++++-- .../Apache.Ignite.Core.Tests/ExceptionsTest.cs | 81 +++++++++++--------- .../Apache.Ignite.Core.Tests/ReconnectTest.cs | 4 + .../Services/ServiceProxyTest.cs | 6 +- .../Services/ServicesTest.cs | 1 + .../Apache.Ignite.Core.Tests/TestUtils.cs | 2 +- .../Apache.Ignite.Core.csproj | 1 + .../Apache.Ignite.Core/Common/JavaException.cs | 65 ++++++++++++++++ .../Impl/Binary/BinaryUtils.cs | 3 +- .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 3 +- .../Impl/Compute/ComputeTaskHolder.cs | 3 +- .../Apache.Ignite.Core/Impl/ExceptionUtils.cs | 31 +++++--- .../Impl/Unmanaged/UnmanagedCallbacks.cs | 15 ++-- 18 files changed, 218 insertions(+), 69 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java index 75683a8..9bf330c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java @@ -50,6 +50,7 @@ import org.apache.ignite.internal.util.GridConcurrentFactory; import org.apache.ignite.internal.util.future.IgniteFutureImpl; import org.apache.ignite.internal.util.typedef.C1; import org.apache.ignite.lang.IgniteBiInClosure; +import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.lang.IgniteFuture; import org.jetbrains.annotations.Nullable; @@ -714,6 +715,7 @@ public class PlatformCache extends PlatformAbstractTarget { else { writer.writeObjectDetached(ex.getClass().getName()); writer.writeObjectDetached(ex.getMessage()); + writer.writeObjectDetached(X.getFullStackTrace(ex)); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/compute/PlatformAbstractTask.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/compute/PlatformAbstractTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/compute/PlatformAbstractTask.java index a8a51d4..fe1e316 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/compute/PlatformAbstractTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/compute/PlatformAbstractTask.java @@ -157,6 +157,7 @@ public abstract class PlatformAbstractTask implements ComputeTask writer.writeBoolean(false); writer.writeString(e.getClass().getName()); writer.writeString(e.getMessage()); + writer.writeString(X.getFullStackTrace(e)); } else { writer.writeBoolean(true); http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformFutureUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformFutureUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformFutureUtils.java index 8fad7d7..6692a23 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformFutureUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformFutureUtils.java @@ -25,6 +25,7 @@ import org.apache.ignite.internal.processors.platform.PlatformContext; import org.apache.ignite.internal.processors.platform.callback.PlatformCallbackGateway; import org.apache.ignite.internal.processors.platform.memory.PlatformMemory; import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream; +import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.lang.IgniteBiInClosure; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.lang.IgniteInClosure; @@ -294,6 +295,7 @@ public class PlatformFutureUtils { outWriter.writeString(err.getClass().getName()); outWriter.writeString(err.getMessage()); + outWriter.writeString(X.getFullStackTrace(err)); PlatformUtils.writeErrorData(err, outWriter); http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java index b31bbd3..dd90fda 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java @@ -42,6 +42,7 @@ import org.apache.ignite.internal.processors.platform.memory.PlatformInputStream import org.apache.ignite.internal.processors.platform.memory.PlatformMemory; import org.apache.ignite.internal.processors.platform.memory.PlatformMemoryUtils; import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream; +import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteBiTuple; @@ -731,6 +732,7 @@ public class PlatformUtils { writer.writeBoolean(false); writer.writeString(err.getClass().getName()); writer.writeString(err.getMessage()); + writer.writeString(X.getFullStackTrace(err)); } else { writer.writeBoolean(true); @@ -989,6 +991,16 @@ public class PlatformUtils { } /** + * Gets the entire nested stack-trace of an throwable. + * + * @param throwable The {@code Throwable} to be examined. + * @return The nested stack trace, with the root cause first. + */ + public static String getFullStackTrace(Throwable throwable) { + return X.getFullStackTrace(throwable); + } + + /** * Private constructor. */ private PlatformUtils() { http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/cpp/jni/include/ignite/jni/java.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/jni/include/ignite/jni/java.h b/modules/platforms/cpp/jni/include/ignite/jni/java.h index e862f93..8d79a7d 100644 --- a/modules/platforms/cpp/jni/include/ignite/jni/java.h +++ b/modules/platforms/cpp/jni/include/ignite/jni/java.h @@ -92,7 +92,7 @@ namespace ignite typedef void(JNICALL *OnStartHandler)(void* target, void* proc, long long memPtr); typedef void(JNICALL *OnStopHandler)(void* target); - typedef void(JNICALL *ErrorHandler)(void* target, int errCode, const char* errClsChars, int errClsCharsLen, const char* errMsgChars, int errMsgCharsLen, void* errData, int errDataLen); + typedef void(JNICALL *ErrorHandler)(void* target, int errCode, const char* errClsChars, int errClsCharsLen, const char* errMsgChars, int errMsgCharsLen, const char* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen); typedef long long(JNICALL *ExtensionCallbackInLongOutLongHandler)(void* target, int typ, long long arg1); typedef long long(JNICALL *ExtensionCallbackInLongLongOutLongHandler)(void* target, int typ, long long arg1, long long arg2); @@ -203,6 +203,9 @@ namespace ignite jclass c_Throwable; jmethodID m_Throwable_getMessage; jmethodID m_Throwable_printStackTrace; + + jclass c_PlatformUtils; + jmethodID m_PlatformUtils_getFullStackTrace; /** * Constructor. @@ -217,7 +220,8 @@ namespace ignite /** * Write error information. */ - bool WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, int* errMsgLen); + bool WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, int* errMsgLen, + char** stackTrace, int* stackTraceLen); }; /** http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/cpp/jni/src/java.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/jni/src/java.cpp b/modules/platforms/cpp/jni/src/java.cpp index 5730263..7bd6287 100644 --- a/modules/platforms/cpp/jni/src/java.cpp +++ b/modules/platforms/cpp/jni/src/java.cpp @@ -377,6 +377,7 @@ namespace ignite const char* C_PLATFORM_UTILS = "org/apache/ignite/internal/processors/platform/utils/PlatformUtils"; JniMethod M_PLATFORM_UTILS_REALLOC = JniMethod("reallocate", "(JI)V", true); JniMethod M_PLATFORM_UTILS_ERR_DATA = JniMethod("errorData", "(Ljava/lang/Throwable;)[B", true); + JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true); const char* C_PLATFORM_IGNITION = "org/apache/ignite/internal/processors/platform/PlatformIgnition"; JniMethod M_PLATFORM_IGNITION_START = JniMethod("start", "(Ljava/lang/String;Ljava/lang/String;IJJ)Lorg/apache/ignite/internal/processors/platform/PlatformProcessor;", true); @@ -551,14 +552,19 @@ namespace ignite c_Throwable = FindClass(env, C_THROWABLE); m_Throwable_getMessage = FindMethod(env, c_Throwable, M_THROWABLE_GET_MESSAGE); m_Throwable_printStackTrace = FindMethod(env, c_Throwable, M_THROWABLE_PRINT_STACK_TRACE); + + c_PlatformUtils = FindClass(env, C_PLATFORM_UTILS); + m_PlatformUtils_getFullStackTrace = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_GET_FULL_STACK_TRACE); } void JniJavaMembers::Destroy(JNIEnv* env) { DeleteClass(env, c_Class); DeleteClass(env, c_Throwable); + DeleteClass(env, c_PlatformUtils); } - bool JniJavaMembers::WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, int* errMsgLen) { + bool JniJavaMembers::WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, + int* errMsgLen, char** stackTrace, int* stackTraceLen) { if (env && env->ExceptionCheck()) { if (m_Class_getName && m_Throwable_getMessage) { jthrowable err = env->ExceptionOccurred(); @@ -573,6 +579,13 @@ namespace ignite jstring msg = static_cast(env->CallObjectMethod(err, m_Throwable_getMessage)); *errMsg = StringToChars(env, msg, errMsgLen); + jstring trace = NULL; + + if (c_PlatformUtils && m_PlatformUtils_getFullStackTrace) { + trace = static_cast(env->CallStaticObjectMethod(c_PlatformUtils, m_PlatformUtils_getFullStackTrace, err)); + *stackTrace = StringToChars(env, trace, stackTraceLen); + } + if (errCls) env->DeleteLocalRef(errCls); @@ -582,6 +595,9 @@ namespace ignite if (msg) env->DeleteLocalRef(msg); + if (trace) + env->DeleteLocalRef(trace); + return true; } else { @@ -989,6 +1005,8 @@ namespace ignite int errClsNameLen = 0; std::string errMsg; int errMsgLen = 0; + std::string stackTrace; + int stackTraceLen = 0; try { if (!JVM.GetJvm()) @@ -1026,9 +1044,11 @@ namespace ignite { char* errClsNameChars = NULL; char* errMsgChars = NULL; + char* stackTraceChars = NULL; // Read error info if possible. - javaMembers.WriteErrorInfo(env, &errClsNameChars, &errClsNameLen, &errMsgChars, &errMsgLen); + javaMembers.WriteErrorInfo(env, &errClsNameChars, &errClsNameLen, &errMsgChars, &errMsgLen, + &stackTraceChars, &stackTraceLen); if (errClsNameChars) { errClsName = errClsNameChars; @@ -1043,6 +1063,13 @@ namespace ignite delete[] errMsgChars; } + if (stackTraceChars) + { + stackTrace = stackTraceChars; + + delete[] stackTraceChars; + } + // Destroy mmebers. if (env) { members.Destroy(env); @@ -1067,7 +1094,7 @@ namespace ignite if (hnds.error) hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errClsNameLen, - errMsg.c_str(), errMsgLen, NULL, 0); + errMsg.c_str(), errMsgLen, stackTrace.c_str(), stackTraceLen, NULL, 0); } return ctx; @@ -2560,7 +2587,7 @@ namespace ignite AttachHelper::OnThreadAttach(); else { if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_ATTACH, NULL, 0, NULL, 0, NULL, 0); + hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_ATTACH, NULL, 0, NULL, 0, NULL, 0, NULL, 0); } return env; @@ -2585,6 +2612,7 @@ namespace ignite jstring clsName = static_cast(env->CallObjectMethod(cls, jvm->GetJavaMembers().m_Class_getName)); jstring msg = static_cast(env->CallObjectMethod(err, jvm->GetJavaMembers().m_Throwable_getMessage)); + jstring trace = static_cast(env->CallStaticObjectMethod(jvm->GetJavaMembers().c_PlatformUtils, jvm->GetJavaMembers().m_PlatformUtils_getFullStackTrace, err)); env->DeleteLocalRef(cls); @@ -2594,6 +2622,9 @@ namespace ignite int msgLen; std::string msg0 = JavaStringToCString(env, msg, &msgLen); + int traceLen; + std::string trace0 = JavaStringToCString(env, trace, &traceLen); + if (errInfo) { JniErrorInfo errInfo0(IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), msg0.c_str()); @@ -2612,16 +2643,16 @@ namespace ignite int errBytesLen = env->GetArrayLength(errData); if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), msgLen, - errBytesNative, errBytesLen); + hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), + msgLen, trace0.c_str(), traceLen, errBytesNative, errBytesLen); env->ReleaseByteArrayElements(errData, errBytesNative, JNI_ABORT); } else { if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), msgLen, - NULL, 0); + hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), + msgLen, trace0.c_str(), traceLen, NULL, 0); } env->DeleteLocalRef(err); http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExceptionsTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExceptionsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExceptionsTest.cs index 0ecd9fe..a324191 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExceptionsTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExceptionsTest.cs @@ -15,6 +15,7 @@ * limitations under the License. */ +#pragma warning disable 618 namespace Apache.Ignite.Core.Tests { using System; @@ -27,7 +28,6 @@ namespace Apache.Ignite.Core.Tests using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Cluster; using Apache.Ignite.Core.Common; - using Apache.Ignite.Core.Impl; using NUnit.Framework; /// @@ -43,7 +43,7 @@ namespace Apache.Ignite.Core.Tests { TestUtils.KillProcesses(); } - + /// /// After test. /// @@ -61,40 +61,16 @@ namespace Apache.Ignite.Core.Tests { var grid = StartGrid(); - try - { - grid.GetCache("invalidCacheName"); - - Assert.Fail(); - } - catch (Exception e) - { - Assert.IsTrue(e is ArgumentException); - } + Assert.Throws(() => grid.GetCache("invalidCacheName")); - try - { - grid.GetCluster().ForRemotes().GetMetrics(); + var e = Assert.Throws(() => grid.GetCluster().ForRemotes().GetMetrics()); - Assert.Fail(); - } - catch (Exception e) - { - Assert.IsTrue(e is ClusterGroupEmptyException); - } + Assert.IsTrue(e.InnerException.Message.StartsWith( + "class org.apache.ignite.cluster.ClusterGroupEmptyException: Cluster group is empty.")); grid.Dispose(); - try - { - grid.GetCache("cache1"); - - Assert.Fail(); - } - catch (Exception e) - { - Assert.IsTrue(e is InvalidOperationException); - } + Assert.Throws(() => grid.GetCache("cache1")); } /// @@ -139,7 +115,7 @@ namespace Apache.Ignite.Core.Tests TestPartialUpdateExceptionSerialization(new CachePartialUpdateException("Msg", new object[] { - new SerializableEntry(1), + new SerializableEntry(1), new SerializableEntry(2), new SerializableEntry(3) })); @@ -159,17 +135,17 @@ namespace Apache.Ignite.Core.Tests stream.Seek(0, SeekOrigin.Begin); var ex0 = (Exception) formatter.Deserialize(stream); - + var updateEx = ((CachePartialUpdateException) ex); try { Assert.AreEqual(updateEx.GetFailedKeys(), - ((CachePartialUpdateException)ex0).GetFailedKeys()); + ((CachePartialUpdateException) ex0).GetFailedKeys()); } catch (Exception e) { - if (typeof (IgniteException) != e.GetType()) + if (typeof(IgniteException) != e.GetType()) throw; } @@ -210,6 +186,39 @@ namespace Apache.Ignite.Core.Tests } /// + /// Tests that invalid spring URL results in a meaningful exception. + /// + [Test] + public void TestInvalidSpringUrl() + { + var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + SpringConfigUrl = "z:\\invalid.xml" + }; + + var ex = Assert.Throws(() => Ignition.Start(cfg)); + Assert.IsTrue(ex.ToString().Contains("Spring XML configuration path is invalid: z:\\invalid.xml")); + } + + /// + /// Tests that invalid configuration parameter results in a meaningful exception. + /// + [Test] + public void TestInvalidConfig() + { + var disco = TestUtils.GetStaticDiscovery(); + disco.SocketTimeout = TimeSpan.FromSeconds(-1); // set invalid timeout + + var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + DiscoverySpi = disco + }; + + var ex = Assert.Throws(() => Ignition.Start(cfg)); + Assert.IsTrue(ex.ToString().Contains("SPI parameter failed condition check: sockTimeout > 0")); + } + + /// /// Tests CachePartialUpdateException keys propagation. /// private static void TestPartialUpdateException(bool async, Func keyFunc) @@ -229,6 +238,8 @@ namespace Apache.Ignite.Core.Tests // Do a lot of puts so that one fails during Ignite stop for (var i = 0; i < 1000000; i++) { + // ReSharper disable once AccessToDisposedClosure + // ReSharper disable once AccessToModifiedClosure var dict = Enumerable.Range(1, 100).ToDictionary(k => keyFunc(k, grid), k => i); if (async) http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs index 6032ef3..35bbca5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ReconnectTest.cs @@ -63,6 +63,10 @@ namespace Apache.Ignite.Core.Tests var ex = Assert.Throws(() => cache.Get(1)); + Assert.IsTrue(ex.ToString().Contains( + "javax.cache.CacheException: class org.apache.ignite.IgniteClientDisconnectedException: " + + "Operation has been cancelled (client node disconnected)")); + var inner = (ClientDisconnectedException) ex.InnerException; var clientReconnectTask = inner.ClientReconnectTask; http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs index 5110b29..dcb5393 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs @@ -285,8 +285,10 @@ namespace Apache.Ignite.Core.Tests.Services var result = ServiceProxyInvoker.InvokeServiceMethod(_svc, mthdName, mthdArgs); ServiceProxySerializer.WriteInvocationResult(outStream, _marsh, result.Key, result.Value); - - _marsh.StartMarshal(outStream).WriteString("unused"); // fake Java exception details + + var writer = _marsh.StartMarshal(outStream); + writer.WriteString("unused"); // fake Java exception details + writer.WriteString("unused"); // fake Java exception details outStream.SynchronizeOutput(); http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs index c6af077..4f6fb77 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs @@ -436,6 +436,7 @@ namespace Apache.Ignite.Core.Tests.Services var ex = Assert.Throws(() => Services.DeployMultiple(SvcName, svc, Grids.Length, 1)); Assert.AreEqual("Expected exception", ex.Message); + Assert.IsTrue(ex.InnerException.Message.Contains("PlatformCallbackUtils.serviceInit(Native Method)")); var svc0 = Services.GetService(SvcName); http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs index 529b320..c0b8599 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs @@ -312,7 +312,7 @@ namespace Apache.Ignite.Core.Tests /// /// Gets the static discovery. /// - public static IDiscoverySpi GetStaticDiscovery() + public static TcpDiscoverySpi GetStaticDiscovery() { return new TcpDiscoverySpi { http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index b0adf61..2e374e5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -84,6 +84,7 @@ + http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Common/JavaException.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Common/JavaException.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Common/JavaException.cs new file mode 100644 index 0000000..a634010 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Common/JavaException.cs @@ -0,0 +1,65 @@ +/* + * 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. + */ + +namespace Apache.Ignite.Core.Common +{ + using System; + using System.Runtime.Serialization; + + /// + /// Indicates an error on Java side and contains full Java stack trace. + /// + public class JavaException : IgniteException + { + /// + /// Initializes a new instance of the class. + /// + public JavaException() + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public JavaException(string message) : base(message) + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The cause. + public JavaException(string message, Exception cause) : base(message, cause) + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + /// Serialization information. + /// Streaming context. + protected JavaException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) + { + // No-op. + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs index 65c714d..860fd9e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs @@ -1846,7 +1846,8 @@ namespace Apache.Ignite.Core.Impl.Binary err = reader.ReadBoolean() ? reader.ReadObject() - : ExceptionUtils.GetException(reader.Marshaller.Ignite, reader.ReadString(), reader.ReadString()); + : ExceptionUtils.GetException(reader.Marshaller.Ignite, reader.ReadString(), reader.ReadString(), + reader.ReadString()); return null; } http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs index 8a25a2c..6afbc67 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs @@ -1215,8 +1215,9 @@ namespace Apache.Ignite.Core.Impl.Cache return new CacheEntryProcessorException((Exception) item); var msg = Unmarshal(inStream); + var trace = Unmarshal(inStream); - return new CacheEntryProcessorException(ExceptionUtils.GetException(_ignite, clsName, msg)); + return new CacheEntryProcessorException(ExceptionUtils.GetException(_ignite, clsName, msg, trace)); } /// http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs index a7988c5..bb8289b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs @@ -391,7 +391,8 @@ namespace Apache.Ignite.Core.Impl.Compute { err = reader.ReadBoolean() ? reader.ReadObject().Deserialize() - : ExceptionUtils.GetException(_compute.Marshaller.Ignite, reader.ReadString(), reader.ReadString()); + : ExceptionUtils.GetException(_compute.Marshaller.Ignite, reader.ReadString(), reader.ReadString(), + reader.ReadString()); } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs index c7c36e0..22881c6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs @@ -113,10 +113,13 @@ namespace Apache.Ignite.Core.Impl /// The ignite. /// Exception class name. /// Exception message. + /// Native stack trace. /// Error data reader. /// Exception. - public static Exception GetException(IIgnite ignite, string clsName, string msg, BinaryReader reader = null) + public static Exception GetException(IIgnite ignite, string clsName, string msg, string stackTrace, BinaryReader reader = null) { + Exception innerException = string.IsNullOrEmpty(stackTrace) ? null : new JavaException(stackTrace); + ExceptionFactoryDelegate ctor; if (Exs.TryGetValue(clsName, out ctor)) @@ -126,23 +129,24 @@ namespace Apache.Ignite.Core.Impl ExceptionFactoryDelegate innerCtor; if (match.Success && Exs.TryGetValue(match.Groups[1].Value, out innerCtor)) - return ctor(ignite, msg, innerCtor(ignite, match.Groups[2].Value, null)); + return ctor(ignite, msg, innerCtor(ignite, match.Groups[2].Value, innerException)); - return ctor(ignite, msg, null); + return ctor(ignite, msg, innerException); } if (ClsNoClsDefFoundErr.Equals(clsName, StringComparison.OrdinalIgnoreCase)) return new IgniteException("Java class is not found (did you set IGNITE_HOME environment " + - "variable?): " + msg); + "variable?): " + msg, innerException); if (ClsNoSuchMthdErr.Equals(clsName, StringComparison.OrdinalIgnoreCase)) return new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " + - "variable?): " + msg); + "variable?): " + msg, innerException); if (ClsCachePartialUpdateErr.Equals(clsName, StringComparison.OrdinalIgnoreCase)) - return ProcessCachePartialUpdateException(ignite, msg, reader); + return ProcessCachePartialUpdateException(ignite, msg, stackTrace, reader); - return new IgniteException("Java exception occurred [class=" + clsName + ", message=" + msg + ']'); + return new IgniteException(string.Format("Java exception occurred [class={0}, message={1}]", clsName, msg), + innerException); } /// @@ -150,10 +154,12 @@ namespace Apache.Ignite.Core.Impl /// /// The ignite. /// Message. + /// Stack trace. /// Reader. /// CachePartialUpdateException. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] - private static Exception ProcessCachePartialUpdateException(IIgnite ignite, string msg, BinaryReader reader) + private static Exception ProcessCachePartialUpdateException(IIgnite ignite, string msg, string stackTrace, + BinaryReader reader) { if (reader == null) return new CachePartialUpdateException(msg, new IgniteException("Failed keys are not available.")); @@ -183,7 +189,7 @@ namespace Apache.Ignite.Core.Impl string innerErrCls = reader.ReadString(); string innerErrMsg = reader.ReadString(); - Exception innerErr = GetException(ignite, innerErrCls, innerErrMsg); + Exception innerErr = GetException(ignite, innerErrCls, innerErrMsg, stackTrace); return new CachePartialUpdateException(msg, innerErr); } @@ -193,14 +199,15 @@ namespace Apache.Ignite.Core.Impl /// /// Class name. /// Message. + /// Stack trace. /// Exception. - public static Exception GetJvmInitializeException(string clsName, string msg) + public static Exception GetJvmInitializeException(string clsName, string msg, string stackTrace) { if (clsName != null) - return new IgniteException("Failed to initialize JVM.", GetException(null, clsName, msg)); + return new IgniteException("Failed to initialize JVM.", GetException(null, clsName, msg, stackTrace)); if (msg != null) - return new IgniteException("Failed to initialize JVM: " + msg); + return new IgniteException("Failed to initialize JVM: " + msg + "\n" + stackTrace); return new IgniteException("Failed to initialize JVM."); } http://git-wip-us.apache.org/repos/asf/ignite/blob/1f4e51ea/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs index ad8c8aa..d101fc3 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs @@ -166,7 +166,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged private delegate void OnStartCallbackDelegate(void* target, void* proc, long memPtr); private delegate void OnStopCallbackDelegate(void* target); - private delegate void ErrorCallbackDelegate(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars, int errMsgCharsLen, void* errData, int errDataLen); + private delegate void ErrorCallbackDelegate(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars, int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen); private delegate long ExtensionCallbackInLongOutLongDelegate(void* target, int typ, long arg1); private delegate long ExtensionCallbackInLongLongOutLongDelegate(void* target, int typ, long arg1, long arg2); @@ -756,8 +756,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged string errCls = reader.ReadString(); string errMsg = reader.ReadString(); + string stackTrace = reader.ReadString(); - Exception err = ExceptionUtils.GetException(_ignite, errCls, errMsg, reader); + Exception err = ExceptionUtils.GetException(_ignite, errCls, errMsg, stackTrace, reader); ProcessFuture(futPtr, fut => { fut.OnError(err); }); } @@ -1070,10 +1071,11 @@ namespace Apache.Ignite.Core.Impl.Unmanaged } private void Error(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars, - int errMsgCharsLen, void* errData, int errDataLen) + int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen) { string errCls = IgniteUtils.Utf8UnmanagedToString(errClsChars, errClsCharsLen); string errMsg = IgniteUtils.Utf8UnmanagedToString(errMsgChars, errMsgCharsLen); + string stackTrace = IgniteUtils.Utf8UnmanagedToString(stackTraceChars, stackTraceCharsLen); switch (errType) { @@ -1083,13 +1085,14 @@ namespace Apache.Ignite.Core.Impl.Unmanaged // Stream disposal intentionally omitted: IGNITE-1598 var stream = new PlatformRawMemory(errData, errDataLen).GetStream(); - throw ExceptionUtils.GetException(_ignite, errCls, errMsg, _ignite.Marshaller.StartUnmarshal(stream)); + throw ExceptionUtils.GetException(_ignite, errCls, errMsg, stackTrace, + _ignite.Marshaller.StartUnmarshal(stream)); } - throw ExceptionUtils.GetException(_ignite, errCls, errMsg); + throw ExceptionUtils.GetException(_ignite, errCls, errMsg, stackTrace); case ErrJvmInit: - throw ExceptionUtils.GetJvmInitializeException(errCls, errMsg); + throw ExceptionUtils.GetJvmInitializeException(errCls, errMsg, stackTrace); case ErrJvmAttach: throw new IgniteException("Failed to attach to JVM.");