ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ptupit...@apache.org
Subject ignite git commit: IGNITE-1433 .NET: Add Java stack trace to IgniteException
Date Wed, 20 Jul 2016 12:34:37 GMT
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 <ptupitsyn@apache.org>
Authored: Wed Jul 20 15:34:25 2016 +0300
Committer: Pavel Tupitsyn <ptupitsyn@apache.org>
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<Object,
Void>
                         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<jstring>(env->CallObjectMethod(err,
m_Throwable_getMessage));
                         *errMsg = StringToChars(env, msg, errMsgLen);
 
+                        jstring trace = NULL;
+
+                        if (c_PlatformUtils && m_PlatformUtils_getFullStackTrace)
{
+                            trace = static_cast<jstring>(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<jstring>(env->CallObjectMethod(cls,
jvm->GetJavaMembers().m_Class_getName));
                     jstring msg = static_cast<jstring>(env->CallObjectMethod(err,
jvm->GetJavaMembers().m_Throwable_getMessage));
+                    jstring trace = static_cast<jstring>(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;
 
     /// <summary>
@@ -43,7 +43,7 @@ namespace Apache.Ignite.Core.Tests
         {
             TestUtils.KillProcesses();
         }
-        
+
         /// <summary>
         /// After test.
         /// </summary>
@@ -61,40 +61,16 @@ namespace Apache.Ignite.Core.Tests
         {
             var grid = StartGrid();
 
-            try
-            {
-                grid.GetCache<object, object>("invalidCacheName");
-
-                Assert.Fail();
-            }
-            catch (Exception e)
-            {
-                Assert.IsTrue(e is ArgumentException);
-            }
+            Assert.Throws<ArgumentException>(() => grid.GetCache<object, object>("invalidCacheName"));
 
-            try
-            {
-                grid.GetCluster().ForRemotes().GetMetrics();
+            var e = Assert.Throws<ClusterGroupEmptyException>(() => 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<object, object>("cache1");
-
-                Assert.Fail();
-            }
-            catch (Exception e)
-            {
-                Assert.IsTrue(e is InvalidOperationException);
-            }
+            Assert.Throws<InvalidOperationException>(() => grid.GetCache<object,
object>("cache1"));
         }
 
         /// <summary>
@@ -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<object>(),
-                    ((CachePartialUpdateException)ex0).GetFailedKeys<object>());
+                    ((CachePartialUpdateException) ex0).GetFailedKeys<object>());
             }
             catch (Exception e)
             {
-                if (typeof (IgniteException) != e.GetType())
+                if (typeof(IgniteException) != e.GetType())
                     throw;
             }
 
@@ -210,6 +186,39 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
+        /// Tests that invalid spring URL results in a meaningful exception.
+        /// </summary>
+        [Test]
+        public void TestInvalidSpringUrl()
+        {
+            var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                SpringConfigUrl = "z:\\invalid.xml"
+            };
+
+            var ex = Assert.Throws<IgniteException>(() => Ignition.Start(cfg));
+            Assert.IsTrue(ex.ToString().Contains("Spring XML configuration path is invalid:
z:\\invalid.xml"));
+        }
+
+        /// <summary>
+        /// Tests that invalid configuration parameter results in a meaningful exception.
+        /// </summary>
+        [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<IgniteException>(() => Ignition.Start(cfg));
+            Assert.IsTrue(ex.ToString().Contains("SPI parameter failed condition check: sockTimeout
> 0"));
+        }
+
+        /// <summary>
         /// Tests CachePartialUpdateException keys propagation.
         /// </summary>
         private static void TestPartialUpdateException<TK>(bool async, Func<int,
IIgnite, TK> 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<CacheException>(() => 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<IgniteException>(() => 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<TestIgniteServiceSerializable>(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
         /// <summary>
         /// Gets the static discovery.
         /// </summary>
-        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 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Binary\BinaryReflectiveSerializer.cs" />
+    <Compile Include="Common\JavaException.cs" />
     <Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
     <Compile Include="Impl\Binary\IBinarySerializerInternal.cs" />
     <Compile Include="Binary\Package-Info.cs" />

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;
+
+    /// <summary>
+    /// Indicates an error on Java side and contains full Java stack trace.
+    /// </summary>
+    public class JavaException : IgniteException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JavaException"/> class.
+        /// </summary>
+        public JavaException()
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JavaException"/> class.
+        /// </summary>
+        /// <param name="message">The message that describes the error.</param>
+        public JavaException(string message) : base(message)
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JavaException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="cause">The cause.</param>
+        public JavaException(string message, Exception cause) : base(message, cause)
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JavaException"/> class.
+        /// </summary>
+        /// <param name="info">Serialization information.</param>
+        /// <param name="ctx">Streaming context.</param>
+        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<object>()
-                : 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<string>(inStream);
+            var trace = Unmarshal<string>(inStream);
                 
-            return new CacheEntryProcessorException(ExceptionUtils.GetException(_ignite,
clsName, msg));
+            return new CacheEntryProcessorException(ExceptionUtils.GetException(_ignite,
clsName, msg, trace));
         }
 
         /// <summary>

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<BinaryObject>().Deserialize<Exception>()
-                    : 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
         /// <param name="ignite">The ignite.</param>
         /// <param name="clsName">Exception class name.</param>
         /// <param name="msg">Exception message.</param>
+        /// <param name="stackTrace">Native stack trace.</param>
         /// <param name="reader">Error data reader.</param>
         /// <returns>Exception.</returns>
-        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);
         }
 
         /// <summary>
@@ -150,10 +154,12 @@ namespace Apache.Ignite.Core.Impl
         /// </summary>
         /// <param name="ignite">The ignite.</param>
         /// <param name="msg">Message.</param>
+        /// <param name="stackTrace">Stack trace.</param>
         /// <param name="reader">Reader.</param>
         /// <returns>CachePartialUpdateException.</returns>
         [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
         /// </summary>
         /// <param name="clsName">Class name.</param>
         /// <param name="msg">Message.</param>
+        /// <param name="stackTrace">Stack trace.</param>
         /// <returns>Exception.</returns>
-        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.");


Mime
View raw message