http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs new file mode 100644 index 0000000..4b87df5 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs @@ -0,0 +1,135 @@ +/* + * 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. + */ + +using System; + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Diagnostics; + using System.Runtime.InteropServices; + using Apache.Ignite.Core.Common; + + /// <summary> + /// AppDomain accessor. + /// <para /> + /// Logic is borrowed from internal .NET Framework classes. + /// See System.Deployment.Application.NativeMethods. + /// </summary> + internal static class AppDomains + { + // ReSharper disable InconsistentNaming + // ReSharper disable UnusedMember.Global + /** */ + private static Guid CLSID_CLRMetaHost = new Guid( + 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde); + + /** */ + private static Guid IID_CLRMetaHost = new Guid( + 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16); + + /** */ + private static Guid IID_CLRRuntimeInfo = new Guid( + 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91); + + /** */ + private static Guid CLSID_CorRuntimeHost = new Guid( + 0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e); + + /** */ + private static Guid IID_CorRuntimeHost = new Guid( + 0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e); + + /// <summary> + /// Gets the default application domain. + /// </summary> + public static _AppDomain GetDefaultAppDomain() + { + object objHost; + int hr = NativeMethods.CLRCreateInstance(ref CLSID_CLRMetaHost, ref IID_CLRMetaHost, out objHost); + + if (hr < 0) + { + throw new IgniteException("Failed to get default AppDomain. Cannot create meta host: " + hr); + } + + var host = (ICLRMetaHost) objHost; + var vers = Environment.Version; + var versString = string.Format("v{0}.{1}.{2}", vers.Major, vers.Minor, vers.Build); + var runtime = (ICLRRuntimeInfo) host.GetRuntime(versString, ref IID_CLRRuntimeInfo); + + bool started; + uint flags; + runtime.IsStarted(out started, out flags); + Debug.Assert(started); + + var rtHost = (ICorRuntimeHost) runtime.GetInterface(ref CLSID_CorRuntimeHost, ref IID_CorRuntimeHost); + + _AppDomain domain; + rtHost.GetDefaultDomain(out domain); + + return domain; + } + + [ComImport, Guid("D332DB9E-B9B3-4125-8207-A14884F53216"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface ICLRMetaHost + { + [return: MarshalAs(UnmanagedType.Interface)] + object GetRuntime(string version, ref Guid iid); + } + + [ComImport, Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface ICLRRuntimeInfo + { + void GetVersionString(char[] buffer, int bufferLength); + void GetRuntimeDirectory(char[] buffer, int bufferLength); + bool IsLoaded(IntPtr hProcess); + void LoadErrorString(uint id, char[] buffer, int bufferLength, int lcid); + void LoadLibrary(string path, out IntPtr hMdodule); + void GetProcAddress(string name, out IntPtr addr); + [return: MarshalAs(UnmanagedType.Interface)] + object GetInterface(ref Guid clsid, ref Guid iid); + bool IsLoadable(); + void SetDefaultStartupFlags(uint flags, string configFile); + void GetDefaultStartupFlags(out uint flags, char[] configFile, int configFileLength); + void BindAsLegacyV2Runtime(); + void IsStarted(out bool started, out uint flags); + } + + [ComImport, Guid("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface ICorRuntimeHost + { + void CreateLogicalThreadState(); + void DeleteLogicalThreadState(); + void SwitchinLogicalThreadState(IntPtr cookie); + void SwitchoutLogicalThreadState(out IntPtr cookie); + void LocksHeldByLogicalThread(out int count); + void MapFile(IntPtr hFile, out IntPtr address); + void GetConfiguration(out IntPtr config); + void Start(); + void Stop(); + void CreateDomain(string name, object identity, out _AppDomain domain); + void GetDefaultDomain(out _AppDomain domain); + } + + private static class NativeMethods + { + [DllImport("mscoree.dll")] + public static extern int CLRCreateInstance(ref Guid clsid, ref Guid iid, + [MarshalAs(UnmanagedType.Interface)] out object ptr); + } + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs new file mode 100644 index 0000000..4eb1d29 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs @@ -0,0 +1,52 @@ +/* + * 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. + */ + +using System; + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Runtime.InteropServices; + using System.Security; + + /// <summary> + /// Java -> .NET callback delegates. + /// <para /> + /// Delegates are registered once per JVM. + /// Every callback has igniteId argument to identify related Ignite instance + /// (this value is passed as EnvPtr to PlatformIgnition.start). + /// </summary> + [SuppressUnmanagedCodeSecurity] + internal static class CallbackDelegates + { + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void LoggerLog(IntPtr env, IntPtr clazz, long igniteId, int level, IntPtr message, + IntPtr category, IntPtr error, long memPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long ignteId, int level); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void ConsoleWrite(IntPtr env, IntPtr clazz, IntPtr message, bool isError); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId, int op, long arg); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz, + long igniteId, int op, long arg1, long arg2, long arg3, IntPtr arg); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs new file mode 100644 index 0000000..1e2989f --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs @@ -0,0 +1,292 @@ +/* + * 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. + */ + +using System; + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + using System.Runtime.InteropServices; + using System.Threading; + using Apache.Ignite.Core.Impl.Handle; + using Apache.Ignite.Core.Log; + + /// <summary> + /// Java -> .NET callback dispatcher. + /// Instance of this class should only exist once per process, in the default AppDomain. + /// </summary> + internal sealed class Callbacks : MarshalByRefObject + { + /** Holds delegates so that GC does not collect them. */ + // ReSharper disable once CollectionNeverQueried.Local + private readonly List<Delegate> _delegates = new List<Delegate>(); + + /** Holds Ignite instance-specific callbacks. */ + private readonly HandleRegistry _callbackRegistry = new HandleRegistry(100); + + /** Console writers. */ + private readonly ConcurrentDictionary<long, ConsoleWriter> _consoleWriters + = new ConcurrentDictionary<long, ConsoleWriter>(); + + /** Gets the JVM. */ + private readonly Jvm _jvm; + + /** Console writer id generator. */ + private long _consoleWriterId; + + /// <summary> + /// Initializes a new instance of the <see cref="Callbacks"/> class. + /// </summary> + public Callbacks(Env env, Jvm jvm) + { + Debug.Assert(env != null); + Debug.Assert(jvm != null); + + _jvm = jvm; + RegisterNatives(env); + } + + /** <inheritdoc /> */ + public override object InitializeLifetimeService() + { + // Ensure that cross-AppDomain reference lives forever. + return null; + } + + /// <summary> + /// Registers callback handlers. + /// </summary> + public long RegisterHandlers(UnmanagedCallbacks cbs) + { + Debug.Assert(cbs != null); + + return _callbackRegistry.AllocateCritical(cbs); + } + + /// <summary> + /// Releases callback handlers. + /// </summary> + public void ReleaseHandlers(long igniteId) + { + _callbackRegistry.Release(igniteId); + } + + /// <summary> + /// Registers the console writer. + /// </summary> + public long RegisterConsoleWriter(ConsoleWriter writer) + { + Debug.Assert(writer != null); + + var id = Interlocked.Increment(ref _consoleWriterId); + + var res = _consoleWriters.TryAdd(id, writer); + Debug.Assert(res); + + return id; + } + + /// <summary> + /// Registers the console writer. + /// </summary> + public void ReleaseConsoleWriter(long id) + { + ConsoleWriter writer; + var res = _consoleWriters.TryRemove(id, out writer); + Debug.Assert(res); + } + + /// <summary> + /// Registers native callbacks. + /// </summary> + private void RegisterNatives(Env env) + { + // Native callbacks are per-jvm. + // Every callback (except ConsoleWrite) includes envPtr (third arg) to identify Ignite instance. + + using (var callbackUtils = env.FindClass( + "org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils")) + { + // Any signature works, but wrong one will cause segfault eventually. + var methods = new[] + { + GetNativeMethod("loggerLog", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V", + (CallbackDelegates.LoggerLog) LoggerLog), + + GetNativeMethod("loggerIsLevelEnabled", "(JI)Z", + (CallbackDelegates.LoggerIsLevelEnabled) LoggerIsLevelEnabled), + + GetNativeMethod("consoleWrite", "(Ljava/lang/String;Z)V", + (CallbackDelegates.ConsoleWrite) ConsoleWrite), + + GetNativeMethod("inLongOutLong", "(JIJ)J", (CallbackDelegates.InLongOutLong) InLongOutLong), + + GetNativeMethod("inLongLongLongObjectOutLong", "(JIJJJLjava/lang/Object;)J", + (CallbackDelegates.InLongLongLongObjectOutLong) InLongLongLongObjectOutLong) + }; + + try + { + env.RegisterNatives(callbackUtils, methods); + } + finally + { + foreach (var nativeMethod in methods) + { + Marshal.FreeHGlobal(nativeMethod.Name); + Marshal.FreeHGlobal(nativeMethod.Signature); + } + } + } + } + + /// <summary> + /// Gets the native method. + /// </summary> + private unsafe NativeMethod GetNativeMethod(string name, string sig, Delegate d) + { + _delegates.Add(d); + + return new NativeMethod + { + Name = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(name), + Signature = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(sig), + FuncPtr = Marshal.GetFunctionPointerForDelegate(d) + }; + } + + /// <summary> + /// <see cref="ILogger.Log"/> callback. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void LoggerLog(IntPtr envPtr, IntPtr clazz, long igniteId, int level, IntPtr message, IntPtr category, + IntPtr errorInfo, long memPtr) + { + try + { + var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true); + var env = _jvm.AttachCurrentThread(); + + var message0 = env.JStringToString(message); + var category0 = env.JStringToString(category); + var errorInfo0 = env.JStringToString(errorInfo); + + cbs.LoggerLog(level, message0, category0, errorInfo0, memPtr); + } + catch (Exception e) + { + _jvm.AttachCurrentThread().ThrowToJava(e); + } + } + + /// <summary> + /// <see cref="ILogger.IsEnabled"/> callback. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long igniteId, int level) + { + try + { + var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true); + + return cbs.LoggerIsLevelEnabled(level); + } + catch (Exception e) + { + _jvm.AttachCurrentThread().ThrowToJava(e); + return false; + } + } + + /// <summary> + /// 3 longs + object -> long. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz, long igniteId, + int op, long arg1, long arg2, long arg3, IntPtr arg) + { + try + { + var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true); + + return cbs.InLongLongLongObjectOutLong(op, arg1, arg2, arg3, arg); + } + catch (Exception e) + { + _jvm.AttachCurrentThread().ThrowToJava(e); + return 0; + } + } + + /// <summary> + /// long -> long. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId, + int op, long arg) + { + try + { + var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true); + + return cbs.InLongOutLong(op, arg); + } + catch (Exception e) + { + _jvm.AttachCurrentThread().ThrowToJava(e); + + return 0; + } + } + + /// <summary> + /// System.out.println -> Console.Write. + /// <para /> + /// Java uses system output which can not be accessed with native .NET APIs. + /// For example, unit test runners won't show Java console output, and so on. + /// To fix this we delegate console output from Java to .NET APIs. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] + private void ConsoleWrite(IntPtr envPtr, IntPtr clazz, IntPtr message, bool isError) + { + try + { + if (message != IntPtr.Zero) + { + // Each domain registers it's own writer. + var writer = _consoleWriters.Select(x => x.Value).FirstOrDefault(); + + if (writer != null) + { + var env = _jvm.AttachCurrentThread(); + var msg = env.JStringToString(message); + + writer.Write(msg, isError); + } + } + } + catch (Exception e) + { + _jvm.AttachCurrentThread().ThrowToJava(e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs new file mode 100644 index 0000000..ef4be1e --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs @@ -0,0 +1,40 @@ +/* + * 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. + */ + +using System; + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Diagnostics.CodeAnalysis; + + /// <summary> + /// Console writer. + /// </summary> + internal sealed class ConsoleWriter : MarshalByRefObject + { + /// <summary> + /// Writes the specified message to console. + /// </summary> + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", + Justification = "Only instance methods can be called across AppDomain boundaries.")] + public void Write(string message, bool isError) + { + var target = isError ? Console.Error : Console.Out; + target.Write(message); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs new file mode 100644 index 0000000..da790d7 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs @@ -0,0 +1,500 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + using System.Security; + using Apache.Ignite.Core.Common; + + /// <summary> + /// JNIEnv. + /// </summary> + [SuppressUnmanagedCodeSecurity] + internal sealed unsafe class Env + { + /** JNIEnv pointer. */ + private readonly IntPtr _envPtr; + + /** JVM. */ + private readonly Jvm _jvm; + + /** */ + private readonly EnvDelegates.CallStaticVoidMethod _callStaticVoidMethod; + + /** */ + private readonly EnvDelegates.CallStaticBooleanMethod _callStaticBoolMethod; + + /** */ + private readonly EnvDelegates.FindClass _findClass; + + /** */ + private readonly EnvDelegates.GetMethodId _getMethodId; + + /** */ + private readonly EnvDelegates.GetStaticMethodId _getStaticMethodId; + + /** */ + private readonly EnvDelegates.NewStringUtf _newStringUtf; + + /** */ + private readonly EnvDelegates.ExceptionOccurred _exceptionOccurred; + + /** */ + private readonly EnvDelegates.GetObjectClass _getObjectClass; + + /** */ + private readonly EnvDelegates.CallObjectMethod _callObjectMethod; + + /** */ + private readonly EnvDelegates.CallLongMethod _callLongMethod; + + /** */ + private readonly EnvDelegates.CallVoidMethod _callVoidMethod; + + /** */ + private readonly EnvDelegates.GetStringChars _getStringChars; + + /** */ + private readonly EnvDelegates.GetStringUtfChars _getStringUtfChars; + + /** */ + private readonly EnvDelegates.GetStringUtfLength _getStringUtfLength; + + /** */ + private readonly EnvDelegates.ReleaseStringUtfChars _releaseStringUtfChars; + + /** */ + private readonly EnvDelegates.ReleaseStringChars _releaseStringChars; + + /** */ + private readonly EnvDelegates.ExceptionClear _exceptionClear; + + /** */ + private readonly EnvDelegates.ExceptionCheck _exceptionCheck; + + /** */ + private readonly EnvDelegates.CallStaticObjectMethod _callStaticObjectMethod; + + /** */ + private readonly EnvDelegates.RegisterNatives _registerNatives; + + /** */ + private readonly EnvDelegates.DeleteLocalRef _deleteLocalRef; + + /** */ + private readonly EnvDelegates.NewGlobalRef _newGlobalRef; + + /** */ + private readonly EnvDelegates.DeleteGlobalRef _deleteGlobalRef; + + /** */ + private readonly EnvDelegates.ThrowNew _throwNew; + + /// <summary> + /// Initializes a new instance of the <see cref="Env" /> class. + /// </summary> + internal Env(IntPtr envPtr, Jvm jvm) + { + Debug.Assert(envPtr != IntPtr.Zero); + Debug.Assert(jvm != null); + + _envPtr = envPtr; + _jvm = jvm; + + var funcPtr = (EnvInterface**)envPtr; + var func = **funcPtr; + + GetDelegate(func.CallStaticVoidMethod, out _callStaticVoidMethod); + GetDelegate(func.CallStaticBooleanMethod, out _callStaticBoolMethod); + GetDelegate(func.FindClass, out _findClass); + GetDelegate(func.GetMethodID, out _getMethodId); + GetDelegate(func.GetStaticMethodID, out _getStaticMethodId); + GetDelegate(func.NewStringUTF, out _newStringUtf); + GetDelegate(func.ExceptionOccurred, out _exceptionOccurred); + GetDelegate(func.ExceptionClear, out _exceptionClear); + GetDelegate(func.ExceptionCheck, out _exceptionCheck); + GetDelegate(func.GetObjectClass, out _getObjectClass); + GetDelegate(func.CallObjectMethod, out _callObjectMethod); + GetDelegate(func.CallStaticObjectMethod, out _callStaticObjectMethod); + GetDelegate(func.CallLongMethod, out _callLongMethod); + GetDelegate(func.CallVoidMethod, out _callVoidMethod); + + GetDelegate(func.GetStringChars, out _getStringChars); + GetDelegate(func.ReleaseStringChars, out _releaseStringChars); + + GetDelegate(func.GetStringUTFChars, out _getStringUtfChars); + GetDelegate(func.ReleaseStringUTFChars, out _releaseStringUtfChars); + + GetDelegate(func.GetStringUTFLength, out _getStringUtfLength); + + GetDelegate(func.RegisterNatives, out _registerNatives); + GetDelegate(func.DeleteLocalRef, out _deleteLocalRef); + GetDelegate(func.NewGlobalRef, out _newGlobalRef); + GetDelegate(func.DeleteGlobalRef, out _deleteGlobalRef); + GetDelegate(func.ThrowNew, out _throwNew); + } + + /// <summary> + /// Gets the JVM. + /// </summary> + public Jvm Jvm + { + get { return _jvm; } + } + + /// <summary> + /// Calls the static void method. + /// </summary> + public void CallStaticVoidMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null) + { + _callStaticVoidMethod(_envPtr, cls.Target, methodId, argsPtr); + + ExceptionCheck(); + } + + /// <summary> + /// Calls the static bool method. + /// </summary> + public bool CallStaticBoolMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null) + { + var res = _callStaticBoolMethod(_envPtr, cls.Target, methodId, argsPtr); + + ExceptionCheck(); + + return res > 0; + } + + /// <summary> + /// Calls the object method. + /// </summary> + public GlobalRef CallObjectMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null) + { + var lref = _callObjectMethod(_envPtr, obj.Target, methodId, argsPtr); + + ExceptionCheck(); + + return NewGlobalRef(lref); + } + + /// <summary> + /// Calls the long method. + /// </summary> + public long CallLongMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null) + { + var res = _callLongMethod(_envPtr, obj.Target, methodId, argsPtr); + + ExceptionCheck(); + + return res; + } + + /// <summary> + /// Calls the void method. + /// </summary> + public void CallVoidMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null) + { + _callVoidMethod(_envPtr, obj.Target, methodId, argsPtr); + + ExceptionCheck(); + } + + /// <summary> + /// Calls the static object method. + /// </summary> + private GlobalRef CallStaticObjectMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null) + { + var res = _callStaticObjectMethod(_envPtr, cls.Target, methodId, argsPtr); + + ExceptionCheck(); + + return NewGlobalRef(res); + } + + /// <summary> + /// Finds the class. + /// </summary> + public GlobalRef FindClass(string name) + { + var res = _findClass(_envPtr, name); + + if (res == IntPtr.Zero) + { + throw new IgniteException("Java class is not found (did you set IGNITE_HOME environment " + + "variable?): " + name); + } + + return NewGlobalRef(res); + } + + /// <summary> + /// Gets the object class. + /// </summary> + private GlobalRef GetObjectClass(GlobalRef obj) + { + var res = _getObjectClass(_envPtr, obj.Target); + + ExceptionCheck(); + + return NewGlobalRef(res); + } + + /// <summary> + /// Gets the static method identifier. + /// </summary> + public IntPtr GetStaticMethodId(GlobalRef clazz, string name, string signature) + { + var res = _getStaticMethodId(_envPtr, clazz.Target, name, signature); + + if (res == IntPtr.Zero) + { + throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " + + "variable?): " + name + " " + signature); + } + + return res; + } + + /// <summary> + /// Gets the method identifier. + /// </summary> + public IntPtr GetMethodId(GlobalRef clazz, string name, string signature) + { + var res = _getMethodId(_envPtr, clazz.Target, name, signature); + + if (res == IntPtr.Zero) + { + throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " + + "variable?): " + name + " " + signature); + } + + return res; + } + + /// <summary> + /// Creates new jstring from UTF chars. + /// </summary> + private GlobalRef NewStringUtf(sbyte* utf) + { + if (utf == null) + { + return null; + } + + var res = _newStringUtf(_envPtr, new IntPtr(utf)); + + ExceptionCheck(); + + return NewGlobalRef(res); + } + + /// <summary> + /// Creates new jstring from string. + /// </summary> + public GlobalRef NewStringUtf(string str) + { + if (str == null) + { + return null; + } + + var chars = IgniteUtils.StringToUtf8Unmanaged(str); + + try + { + return NewStringUtf(chars); + } + finally + { + Marshal.FreeHGlobal(new IntPtr(chars)); + } + } + + /// <summary> + /// Gets the utf chars from jstring. + /// </summary> + private IntPtr GetStringUtfChars(IntPtr jstring) + { + Debug.Assert(jstring != IntPtr.Zero); + + byte isCopy; + return _getStringUtfChars(_envPtr, jstring, &isCopy); + } + + /// <summary> + /// Releases the string utf chars allocated by <see cref="GetStringUtfChars"/>. + /// </summary> + private void ReleaseStringUtfChars(IntPtr jstring, IntPtr chars) + { + _releaseStringUtfChars(_envPtr, jstring, chars); + } + + /// <summary> + /// Gets the length of the jstring. + /// </summary> + private int GetStringUtfLength(IntPtr jstring) + { + Debug.Assert(jstring != IntPtr.Zero); + + return _getStringUtfLength(_envPtr, jstring); + } + + /// <summary> + /// Registers the native callbacks. + /// </summary> + public void RegisterNatives(GlobalRef clazz, NativeMethod[] methods) + { + Debug.Assert(methods != null); + + fixed (NativeMethod* m = &methods[0]) + { + var res = _registerNatives(_envPtr, clazz.Target, m, methods.Length); + + if (res != JniResult.Success) + { + throw new IgniteException("Failed to register natives: " + res); + } + } + } + + /// <summary> + /// Converts jstring to string. + /// </summary> + private string JStringToString(GlobalRef jstring) + { + if (jstring == null) + { + return null; + } + + return JStringToString(jstring.Target); + } + + /// <summary> + /// Converts jstring to string. + /// </summary> + public string JStringToString(IntPtr jstring) + { + if (jstring == IntPtr.Zero) + { + return null; + } + + var chars = GetStringUtfChars(jstring); + var len = GetStringUtfLength(jstring); + + try + { + return IgniteUtils.Utf8UnmanagedToString((sbyte*) chars, len); + } + finally + { + ReleaseStringUtfChars(jstring, chars); + } + } + + /// <summary> + /// Creates a new global reference from a local reference pointer. + /// </summary> + public GlobalRef NewGlobalRef(IntPtr lref) + { + if (lref == IntPtr.Zero) + { + return null; + } + + var res = new GlobalRef(_newGlobalRef(_envPtr, lref), _jvm); + + _deleteLocalRef(_envPtr, lref); + + return res; + } + + /// <summary> + /// Deletes the global reference. + /// </summary> + public void DeleteGlobalRef(IntPtr gref) + { + _deleteGlobalRef(_envPtr, gref); + } + + /// <summary> + /// Throws an exception to java. + /// </summary> + public void ThrowToJava(Exception e) + { + Debug.Assert(e != null); + var msgChars = IgniteUtils.StringToUtf8Unmanaged(e.Message); + + try + { + using (var cls = FindClass("org/apache/ignite/IgniteException")) + { + _throwNew(_envPtr, cls.Target, new IntPtr(msgChars)); + } + } + finally + { + Marshal.FreeHGlobal(new IntPtr(msgChars)); + } + } + + /// <summary> + /// Checks for the JNI exception and throws. + /// </summary> + private void ExceptionCheck() + { + if (!_exceptionCheck(_envPtr)) + { + return; + } + + var err = _exceptionOccurred(_envPtr); + Debug.Assert(err != IntPtr.Zero); + + _exceptionClear(_envPtr); + + using (var errRef = NewGlobalRef(err)) + { + var errRef0 = (long) errRef.Target; + var methodId = _jvm.MethodId; + + using (var cls = GetObjectClass(errRef)) + using (var clsName = CallObjectMethod(cls, methodId.ClassGetName)) + using (var msg = CallObjectMethod(errRef, methodId.ThrowableGetMessage)) + using (var trace = CallStaticObjectMethod(methodId.PlatformUtils, + methodId.PlatformUtilsGetStackTrace, &errRef0)) + { + throw new JavaException( + JStringToString(clsName), + JStringToString(msg), + JStringToString(trace)); + } + } + } + + /// <summary> + /// Gets the delegate. + /// </summary> + private static void GetDelegate<T>(IntPtr ptr, out T del) + { + del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs new file mode 100644 index 0000000..a2ad499 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs @@ -0,0 +1,109 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Runtime.InteropServices; + + /// <summary> + /// Delegates for JNI Env entity. + /// </summary> + internal static unsafe class EnvDelegates + { + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate JniResult CallStaticVoidMethod( + IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate byte CallStaticBooleanMethod( + IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr NewGlobalRef(IntPtr env, IntPtr lobj); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void DeleteLocalRef(IntPtr env, IntPtr lref); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void DeleteGlobalRef(IntPtr env, IntPtr gref); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr FindClass(IntPtr env, [MarshalAs(UnmanagedType.LPStr)] string name); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr GetStaticMethodId(IntPtr env, IntPtr clazz, + [MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string sig); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr GetMethodId(IntPtr env, IntPtr clazz, [MarshalAs(UnmanagedType.LPStr)] string name, + [MarshalAs(UnmanagedType.LPStr)] string sig); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr NewStringUtf(IntPtr env, IntPtr utf); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr ExceptionOccurred(IntPtr env); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void ExceptionClear(IntPtr env); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool ExceptionCheck(IntPtr env); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr GetObjectClass(IntPtr env, IntPtr obj); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr CallObjectMethod( + IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate long CallLongMethod( + IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void CallVoidMethod( + IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr CallStaticObjectMethod( + IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr GetStringChars(IntPtr env, IntPtr jstring, byte* isCopy); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void ReleaseStringChars(IntPtr env, IntPtr jstring, IntPtr chars); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate IntPtr GetStringUtfChars(IntPtr env, IntPtr jstring, byte* isCopy); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void ReleaseStringUtfChars(IntPtr env, IntPtr jstring, IntPtr chars); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate int GetStringUtfLength(IntPtr env, IntPtr jstring); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate JniResult RegisterNatives(IntPtr env, IntPtr clazz, + NativeMethod* methods, int nMethods); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate JniResult ThrowNew(IntPtr env, IntPtr clazz, IntPtr msg); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs new file mode 100644 index 0000000..01f8634 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs @@ -0,0 +1,263 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Runtime.InteropServices; + + /// <summary> + /// JNIEnv interface. + /// </summary> + [StructLayout(LayoutKind.Sequential)] + internal struct EnvInterface + { + // ReSharper disable MemberCanBePrivate.Global + public IntPtr reserved0; + public IntPtr reserved1; + public IntPtr reserved2; + public IntPtr reserved3; + public IntPtr GetVersion; + public IntPtr DefineClass; + public IntPtr FindClass; + public IntPtr FromReflectedMethod; + public IntPtr FromReflectedField; + public IntPtr ToReflectedMethod; + public IntPtr GetSuperclass; + public IntPtr IsAssignableFrom; + public IntPtr ToReflectedField; + public IntPtr Throw; + public IntPtr ThrowNew; + public IntPtr ExceptionOccurred; + public IntPtr ExceptionDescribe; + public IntPtr ExceptionClear; + public IntPtr FatalError; + public IntPtr PushLocalFrame; + public IntPtr PopLocalFrame; + public IntPtr NewGlobalRef; + public IntPtr DeleteGlobalRef; + public IntPtr DeleteLocalRef; + public IntPtr IsSameObject; + public IntPtr NewLocalRef; + public IntPtr EnsureLocalCapacity; + public IntPtr AllocObject; + public IntPtr __NewObject; + public IntPtr __NewObjectV; + public IntPtr NewObject; + public IntPtr GetObjectClass; + public IntPtr IsInstanceOf; + public IntPtr GetMethodID; + public IntPtr __CallObjectMethod; + public IntPtr __CallObjectMethodV; + public IntPtr CallObjectMethod; + public IntPtr __CallBooleanMethod; + public IntPtr __CallBooleanMethodV; + public IntPtr CallBooleanMethod; + public IntPtr __CallByteMethod; + public IntPtr __CallByteMethodV; + public IntPtr CallByteMethod; + public IntPtr __CallCharMethod; + public IntPtr __CallCharMethodV; + public IntPtr CallCharMethod; + public IntPtr __CallShortMethod; + public IntPtr __CallShortMethodV; + public IntPtr CallShortMethod; + public IntPtr __CallIntMethod; + public IntPtr __CallIntMethodV; + public IntPtr CallIntMethod; + public IntPtr __CallLongMethod; + public IntPtr __CallLongMethodV; + public IntPtr CallLongMethod; + public IntPtr __CallFloatMethod; + public IntPtr __CallFloatMethodV; + public IntPtr CallFloatMethod; + public IntPtr __CallDoubleMethod; + public IntPtr __CallDoubleMethodV; + public IntPtr CallDoubleMethod; + public IntPtr __CallVoidMethod; + public IntPtr __CallVoidMethodV; + public IntPtr CallVoidMethod; + public IntPtr __CallNonvirtualObjectMethod; + public IntPtr __CallNonvirtualObjectMethodV; + public IntPtr CallNonvirtualObjectMethod; + public IntPtr __CallNonvirtualBooleanMethod; + public IntPtr __CallNonvirtualBooleanMethodV; + public IntPtr CallNonvirtualBooleanMethod; + public IntPtr __CallNonvirtualByteMethod; + public IntPtr __CallNonvirtualByteMethodV; + public IntPtr CallNonvirtualByteMethod; + public IntPtr __CallNonvirtualCharMethod; + public IntPtr __CallNonvirtualCharMethodV; + public IntPtr CallNonvirtualCharMethod; + public IntPtr __CallNonvirtualShortMethod; + public IntPtr __CallNonvirtualShortMethodV; + public IntPtr CallNonvirtualShortMethod; + public IntPtr __CallNonvirtualIntMethod; + public IntPtr __CallNonvirtualIntMethodV; + public IntPtr CallNonvirtualIntMethod; + public IntPtr __CallNonvirtualLongMethod; + public IntPtr __CallNonvirtualLongMethodV; + public IntPtr CallNonvirtualLongMethod; + public IntPtr __CallNonvirtualFloatMethod; + public IntPtr __CallNonvirtualFloatMethodV; + public IntPtr CallNonvirtualFloatMethod; + public IntPtr __CallNonvirtualDoubleMethod; + public IntPtr __CallNonvirtualDoubleMethodV; + public IntPtr CallNonvirtualDoubleMethod; + public IntPtr __CallNonvirtualVoidMethod; + public IntPtr __CallNonvirtualVoidMethodV; + public IntPtr CallNonvirtualVoidMethod; + public IntPtr GetFieldID; + public IntPtr GetObjectField; + public IntPtr GetBooleanField; + public IntPtr GetByteField; + public IntPtr GetCharField; + public IntPtr GetShortField; + public IntPtr GetIntField; + public IntPtr GetLongField; + public IntPtr GetFloatField; + public IntPtr GetDoubleField; + public IntPtr SetObjectField; + public IntPtr SetBooleanField; + public IntPtr SetByteField; + public IntPtr SetCharField; + public IntPtr SetShortField; + public IntPtr SetIntField; + public IntPtr SetLongField; + public IntPtr SetFloatField; + public IntPtr SetDoubleField; + public IntPtr GetStaticMethodID; + public IntPtr __CallStaticObjectMethod; + public IntPtr __CallStaticObjectMethodV; + public IntPtr CallStaticObjectMethod; + public IntPtr __CallStaticBooleanMethod; + public IntPtr __CallStaticBooleanMethodV; + public IntPtr CallStaticBooleanMethod; + public IntPtr __CallStaticByteMethod; + public IntPtr __CallStaticByteMethodV; + public IntPtr CallStaticByteMethod; + public IntPtr __CallStaticCharMethod; + public IntPtr __CallStaticCharMethodV; + public IntPtr CallStaticCharMethod; + public IntPtr __CallStaticShortMethod; + public IntPtr __CallStaticShortMethodV; + public IntPtr CallStaticShortMethod; + public IntPtr __CallStaticIntMethod; + public IntPtr __CallStaticIntMethodV; + public IntPtr CallStaticIntMethod; + public IntPtr __CallStaticLongMethod; + public IntPtr __CallStaticLongMethodV; + public IntPtr CallStaticLongMethod; + public IntPtr __CallStaticFloatMethod; + public IntPtr __CallStaticFloatMethodV; + public IntPtr CallStaticFloatMethod; + public IntPtr __CallStaticDoubleMethod; + public IntPtr __CallStaticDoubleMethodV; + public IntPtr CallStaticDoubleMethod; + public IntPtr __CallStaticVoidMethod; + public IntPtr __CallStaticVoidMethodV; + public IntPtr CallStaticVoidMethod; + public IntPtr GetStaticFieldID; + public IntPtr GetStaticObjectField; + public IntPtr GetStaticBooleanField; + public IntPtr GetStaticByteField; + public IntPtr GetStaticCharField; + public IntPtr GetStaticShortField; + public IntPtr GetStaticIntField; + public IntPtr GetStaticLongField; + public IntPtr GetStaticFloatField; + public IntPtr GetStaticDoubleField; + public IntPtr SetStaticObjectField; + public IntPtr SetStaticBooleanField; + public IntPtr SetStaticByteField; + public IntPtr SetStaticCharField; + public IntPtr SetStaticShortField; + public IntPtr SetStaticIntField; + public IntPtr SetStaticLongField; + public IntPtr SetStaticFloatField; + public IntPtr SetStaticDoubleField; + public IntPtr NewString; + public IntPtr GetStringLength; + public IntPtr GetStringChars; + public IntPtr ReleaseStringChars; + public IntPtr NewStringUTF; + public IntPtr GetStringUTFLength; + public IntPtr GetStringUTFChars; + public IntPtr ReleaseStringUTFChars; + public IntPtr GetArrayLength; + public IntPtr NewObjectArray; + public IntPtr GetObjectArrayElement; + public IntPtr SetObjectArrayElement; + public IntPtr NewBooleanArray; + public IntPtr NewByteArray; + public IntPtr NewCharArray; + public IntPtr NewShortArray; + public IntPtr NewIntArray; + public IntPtr NewLongArray; + public IntPtr NewFloatArray; + public IntPtr NewDoubleArray; + public IntPtr GetBooleanArrayElements; + public IntPtr GetByteArrayElements; + public IntPtr GetCharArrayElements; + public IntPtr GetShortArrayElements; + public IntPtr GetIntArrayElements; + public IntPtr GetLongArrayElements; + public IntPtr GetFloatArrayElements; + public IntPtr GetDoubleArrayElements; + public IntPtr ReleaseBooleanArrayElements; + public IntPtr ReleaseByteArrayElements; + public IntPtr ReleaseCharArrayElements; + public IntPtr ReleaseShortArrayElements; + public IntPtr ReleaseIntArrayElements; + public IntPtr ReleaseLongArrayElements; + public IntPtr ReleaseFloatArrayElements; + public IntPtr ReleaseDoubleArrayElements; + public IntPtr GetBooleanArrayRegion; + public IntPtr GetByteArrayRegion; + public IntPtr GetCharArrayRegion; + public IntPtr GetShortArrayRegion; + public IntPtr GetIntArrayRegion; + public IntPtr GetLongArrayRegion; + public IntPtr GetFloatArrayRegion; + public IntPtr GetDoubleArrayRegion; + public IntPtr SetBooleanArrayRegion; + public IntPtr SetByteArrayRegion; + public IntPtr SetCharArrayRegion; + public IntPtr SetShortArrayRegion; + public IntPtr SetIntArrayRegion; + public IntPtr SetLongArrayRegion; + public IntPtr SetFloatArrayRegion; + public IntPtr SetDoubleArrayRegion; + public IntPtr RegisterNatives; + public IntPtr UnregisterNatives; + public IntPtr MonitorEnter; + public IntPtr MonitorExit; + public IntPtr GetJavaVM; + public IntPtr GetStringRegion; + public IntPtr GetStringUTFRegion; + public IntPtr GetPrimitiveArrayCritical; + public IntPtr ReleasePrimitiveArrayCritical; + public IntPtr GetStringCritical; + public IntPtr ReleaseStringCritical; + public IntPtr NewWeakGlobalRef; + public IntPtr DeleteWeakGlobalRef; + public IntPtr ExceptionCheck; + public IntPtr NewDirectByteBuffer; + public IntPtr GetDirectBufferAddress; + public IntPtr GetDirectBufferCapacity; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs new file mode 100644 index 0000000..c33a53b --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs @@ -0,0 +1,87 @@ +/* + * 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. + */ + +using System; + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Diagnostics; + + /// <summary> + /// JNI Global Reference. + /// <para /> + /// We should always convert local reference to global and delete local one immediately, + /// otherwise these local references may cause memory leaks (false GC roots). + /// </summary> + internal sealed class GlobalRef : IDisposable + { + /** Reference. */ + private readonly IntPtr _target; + + /** JVM. */ + private readonly Jvm _jvm; + + /// <summary> + /// Initializes a new instance of the <see cref="GlobalRef"/> class. + /// </summary> + public GlobalRef(IntPtr target, Jvm jvm) + { + Debug.Assert(target != IntPtr.Zero); + Debug.Assert(jvm != null); + + _target = target; + _jvm = jvm; + } + + /// <summary> + /// Gets the target. + /// </summary> + public IntPtr Target + { + get { return _target; } + } + + /// <summary> + /// Gets the JVM. + /// </summary> + public Jvm Jvm + { + get { return _jvm; } + } + + /// <summary> + /// Releases the unmanaged resources. + /// </summary> + private void ReleaseUnmanagedResources() + { + _jvm.AttachCurrentThread().DeleteGlobalRef(_target); + } + + /** <inheritdoc /> */ + public void Dispose() + { + ReleaseUnmanagedResources(); + GC.SuppressFinalize(this); + } + + /** <inheritdoc /> */ + ~GlobalRef() + { + ReleaseUnmanagedResources(); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs new file mode 100644 index 0000000..0370d5c --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs @@ -0,0 +1,35 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + /// <summary> + /// JNI call result. + /// </summary> + internal enum JniResult + { + Success = 0, + // ReSharper disable UnusedMember.Global + // Some statuses are not used directly, but will be displayed as part of error message. + Error = -1, + ThreadDetached = -2, + VersionError = -3, + NotEnoughMemory = -4, + AlreadyExists = -5, + InvalidArguments = -6 + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs new file mode 100644 index 0000000..10c7468 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs @@ -0,0 +1,335 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Security; + using System.Threading; + using Apache.Ignite.Core.Common; + + /// <summary> + /// JVM holder. Should exist once per domain. + /// </summary> + [SuppressUnmanagedCodeSecurity] + internal sealed unsafe class Jvm + { + /** */ + // ReSharper disable once InconsistentNaming + private const int JNI_VERSION_1_6 = 0x00010006; + + /** */ + private readonly IntPtr _jvmPtr; + + /** */ + private readonly JvmDelegates.AttachCurrentThread _attachCurrentThread; + + /** */ + private readonly MethodId _methodId; + + /** Callbacks. */ + private readonly Callbacks _callbacks; + + /** Static instamce */ + private static volatile Jvm _instance; + + /** Sync. */ + private static readonly object SyncRoot = new object(); + + /** Console writer. */ + private static readonly ConsoleWriter ConsoleWriter = new ConsoleWriter(); + + /** Env for current thread. */ + [ThreadStatic] private static Env _env; + + /** Console writer flag. */ + private int _isConsoleWriterEnabled; + + /// <summary> + /// Initializes a new instance of the <see cref="_instance"/> class. + /// </summary> + private Jvm(IntPtr jvmPtr) + { + Debug.Assert(jvmPtr != IntPtr.Zero); + + _jvmPtr = jvmPtr; + + var funcPtr = (JvmInterface**)jvmPtr; + var func = **funcPtr; + GetDelegate(func.AttachCurrentThread, out _attachCurrentThread); + + var env = AttachCurrentThread(); + _methodId = new MethodId(env); + _callbacks = GetCallbacks(env, this); + } + + /// <summary> + /// Gets the callbacks. + /// </summary> + private static Callbacks GetCallbacks(Env env, Jvm jvm) + { + if (AppDomain.CurrentDomain.IsDefaultAppDomain()) + { + return new Callbacks(env, jvm); + } + + // JVM exists once per process, and JVM callbacks exist once per process. + // We should register callbacks ONLY from the default AppDomain (which can't be unloaded). + // Non-default appDomains should delegate this logic to the default one. + var defDomain = AppDomains.GetDefaultAppDomain(); + + // In some cases default AppDomain is not able to locate Apache.Ignite.Core assembly. + // First, use CreateInstanceFrom to set up the AssemblyResolve handler. + var resHelpType = typeof(AssemblyResolver); + var resHelp = (AssemblyResolver)defDomain.CreateInstanceFrom(resHelpType.Assembly.Location, resHelpType.FullName) + .Unwrap(); + resHelp.TrackResolve(resHelpType.Assembly.FullName, resHelpType.Assembly.Location); + + // Now use CreateInstance to get the domain helper of a properly loaded class. + var type = typeof(CallbackAccessor); + var helper = (CallbackAccessor)defDomain.CreateInstance(type.Assembly.FullName, type.FullName).Unwrap(); + + return helper.GetCallbacks(); + } + + /// <summary> + /// Gets or creates the JVM. + /// </summary> + /// <param name="options">JVM options.</param> + public static Jvm GetOrCreate(IList<string> options) + { + lock (SyncRoot) + { + return _instance ?? (_instance = new Jvm(GetJvmPtr(options))); + } + } + + /// <summary> + /// Gets the JVM. + /// </summary> + public static Jvm Get() + { + var res = _instance; + + if (res == null) + { + throw new IgniteException("JVM has not been created."); + } + + return res; + } + + /// <summary> + /// Gets the method IDs. + /// </summary> + public MethodId MethodId + { + get { return _methodId; } + } + + /// <summary> + /// Attaches current thread to the JVM and returns JNIEnv. + /// </summary> + public Env AttachCurrentThread() + { + if (_env == null) + { + IntPtr envPtr; + var res = _attachCurrentThread(_jvmPtr, out envPtr, IntPtr.Zero); + + if (res != JniResult.Success) + { + throw new IgniteException("AttachCurrentThread failed: " + res); + } + + _env = new Env(envPtr, this); + } + + return _env; + } + + /// <summary> + /// Registers the callbacks. + /// </summary> + public void RegisterCallbacks(UnmanagedCallbacks cbs) + { + var id = _callbacks.RegisterHandlers(cbs); + cbs.SetContext(id); + } + + /// <summary> + /// Releases the callbacks. + /// </summary> + public void ReleaseCallbacks(long igniteId) + { + _callbacks.ReleaseHandlers(igniteId); + } + + /// <summary> + /// Enables the Java console output propagation. + /// </summary> + public void EnableJavaConsoleWriter() + { + if (Interlocked.CompareExchange(ref _isConsoleWriterEnabled, 1, 0) == 0) + { + var writerId = _callbacks.RegisterConsoleWriter(ConsoleWriter); + AppDomain.CurrentDomain.DomainUnload += (s, a) => _callbacks.ReleaseConsoleWriter(writerId); + } + } + + /// <summary> + /// Gets the JVM pointer. + /// </summary> + private static IntPtr GetJvmPtr(IList<string> options) + { + IntPtr jvm; + int existingJvmCount; + + // Use existing JVM if present. + var res = JniNativeMethods.JNI_GetCreatedJavaVMs(out jvm, 1, out existingJvmCount); + if (res != JniResult.Success) + { + throw new IgniteException("JNI_GetCreatedJavaVMs failed: " + res); + } + + if (existingJvmCount > 0) + { + return jvm; + } + + var args = new JvmInitArgs + { + version = JNI_VERSION_1_6 + }; + + if (options != null && options.Count > 0) + { + args.nOptions = options.Count; + var opt = new JvmOption[options.Count]; + + for (int i = 0; i < options.Count; i++) + { + opt[i].optionString = Marshal.StringToHGlobalAnsi(options[i]); + } + + fixed (JvmOption* a = &opt[0]) + { + args.options = a; + } + } + + IntPtr env; + res = JniNativeMethods.JNI_CreateJavaVM(out jvm, out env, &args); + if (res != JniResult.Success) + { + throw new IgniteException("JNI_CreateJavaVM failed: " + res); + } + + return jvm; + } + + /// <summary> + /// Gets the delegate. + /// </summary> + private static void GetDelegate<T>(IntPtr ptr, out T del) + { + del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)); + } + + /// <summary> + /// JavaVMOption. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] + [StructLayout(LayoutKind.Sequential, Pack = 0)] + private struct JvmOption + { + public IntPtr optionString; + private readonly IntPtr extraInfo; + } + + /// <summary> + /// JavaVMInitArgs. + /// </summary> + [StructLayout(LayoutKind.Sequential, Pack = 0)] + private struct JvmInitArgs + { + public int version; + public int nOptions; + public JvmOption* options; + private readonly byte ignoreUnrecognized; + } + + /// <summary> + /// DLL imports. + /// </summary> + private static class JniNativeMethods + { + [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)] + internal static extern JniResult JNI_CreateJavaVM(out IntPtr pvm, out IntPtr penv, + JvmInitArgs* args); + + [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)] + internal static extern JniResult JNI_GetCreatedJavaVMs(out IntPtr pvm, int size, + [Out] out int size2); + } + + /// <summary> + /// Provides access to <see cref="Callbacks"/> instance in the default AppDomain. + /// </summary> + private class CallbackAccessor : MarshalByRefObject + { + /// <summary> + /// Gets the callbacks. + /// </summary> + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", + Justification = "Only instance methods can be called across AppDomain boundaries.")] + public Callbacks GetCallbacks() + { + return GetOrCreate(null)._callbacks; + } + } + + /// <summary> + /// Resolves Apache.Ignite.Core assembly in the default AppDomain when needed. + /// </summary> + private class AssemblyResolver : MarshalByRefObject + { + /// <summary> + /// Tracks the AssemblyResolve event. + /// </summary> + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", + Justification = "Only instance methods can be called across AppDomain boundaries.")] + public void TrackResolve(string name, string path) + { + AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => + { + if (args.Name == name) + { + return Assembly.LoadFrom(path); + } + + return null; + }; + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs new file mode 100644 index 0000000..9686888 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs @@ -0,0 +1,31 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Runtime.InteropServices; + + /// <summary> + /// Delegates for JavaVM JNI entity. + /// </summary> + internal static class JvmDelegates + { + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate JniResult AttachCurrentThread(IntPtr jvm, out IntPtr env, IntPtr args); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs new file mode 100644 index 0000000..74d5ba1 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs @@ -0,0 +1,40 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Runtime.InteropServices; + + /// <summary> + /// JavaVM interface. + /// </summary> + [StructLayout(LayoutKind.Sequential)] + internal struct JvmInterface + { + // ReSharper disable MemberCanBePrivate.Global + public IntPtr reserved0; + public IntPtr reserved1; + public IntPtr reserved2; + + public IntPtr DestroyJavaVM; + public IntPtr AttachCurrentThread; + public IntPtr DetachCurrentThread; + public IntPtr GetEnv; + public IntPtr AttachCurrentThreadAsDaemon; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs new file mode 100644 index 0000000..12a4dff --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs @@ -0,0 +1,157 @@ +/* + * 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.Impl.Unmanaged.Jni +{ + using System; + using System.Diagnostics; + + /// <summary> + /// Cached JNI method ids: initialized once on JVM start. + /// </summary> + internal sealed class MethodId + { + /// <summary> + /// Class.getName(). + /// </summary> + public IntPtr ClassGetName { get; private set; } + + /// <summary> + /// Throwable.getMessage(). + /// </summary> + public IntPtr ThrowableGetMessage { get; private set; } + + /// <summary> + /// PlatformIgnition. + /// </summary> + public GlobalRef PlatformIgnition { get; private set; } + + /// <summary> + /// PlatformIgnition.start(). + /// </summary> + public IntPtr PlatformIgnitionStart { get; private set; } + + /// <summary> + /// PlatformIgnition.stop(). + /// </summary> + public IntPtr PlatformIgnitionStop { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inStreamOutObjectAsync(). + /// </summary> + public IntPtr TargetInStreamOutObjectAsync { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inStreamAsync(). + /// </summary> + public IntPtr TargetInStreamAsync { get; private set; } + + /// <summary> + /// PlatformTargetProxy.outObject (). + /// </summary> + public IntPtr TargetOutObject { get; private set; } + + /// <summary> + /// PlatformTargetProxy.outStream(). + /// </summary> + public IntPtr TargetOutStream { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inStreamOutStream(). + /// </summary> + public IntPtr TargetInStreamOutStream { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inObjectStreamOutObjectStream(). + /// </summary> + public IntPtr TargetInObjectStreamOutObjectStream { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inStreamOutObject(). + /// </summary> + public IntPtr TargetInStreamOutObject { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inStreamOutLong(). + /// </summary> + public IntPtr TargetInStreamOutLong { get; private set; } + + /// <summary> + /// PlatformTargetProxy.inLongOutLong(). + /// </summary> + public IntPtr TargetInLongOutLong { get; private set; } + + /// <summary> + /// PlatformUtils class. + /// </summary> + public GlobalRef PlatformUtils { get; private set; } + + /// <summary> + /// PlatformUtils.getFullStackTrace. + /// </summary> + public IntPtr PlatformUtilsGetStackTrace { get; private set; } + + /// <summary> + /// PlatformUtils.reallocate. + /// </summary> + public IntPtr PlatformUtilsReallocate { get; private set; } + + /// <summary> + /// Initializes a new instance of the <see cref="MethodId"/> class. + /// </summary> + public MethodId(Env env) + { + Debug.Assert(env != null); + + using (var classCls = env.FindClass("java/lang/Class")) + { + ClassGetName = env.GetMethodId(classCls, "getName", "()Ljava/lang/String;"); + } + + using (var throwableCls = env.FindClass("java/lang/Throwable")) + { + ThrowableGetMessage = env.GetMethodId(throwableCls, "getMessage", "()Ljava/lang/String;"); + } + + PlatformIgnition = env.FindClass( + "org/apache/ignite/internal/processors/platform/PlatformIgnition"); + PlatformIgnitionStart = env.GetStaticMethodId(PlatformIgnition, + "start", "(Ljava/lang/String;Ljava/lang/String;IJJ)V"); + PlatformIgnitionStop = env.GetStaticMethodId(PlatformIgnition, "stop", "(Ljava/lang/String;Z)Z"); + + using (var target = env.FindClass("org/apache/ignite/internal/processors/platform/PlatformTargetProxy")) + { + TargetInLongOutLong = env.GetMethodId(target, "inLongOutLong", "(IJ)J"); + TargetInStreamOutLong = env.GetMethodId(target, "inStreamOutLong", "(IJ)J"); + TargetInStreamOutObject = env.GetMethodId(target, "inStreamOutObject", "(IJ)Ljava/lang/Object;"); + TargetInStreamOutStream = env.GetMethodId(target, "inStreamOutStream", "(IJJ)V"); + TargetInObjectStreamOutObjectStream = env.GetMethodId(target, "inObjectStreamOutObjectStream", + "(ILjava/lang/Object;JJ)Ljava/lang/Object;"); + TargetOutStream = env.GetMethodId(target, "outStream", "(IJ)V"); + TargetOutObject = env.GetMethodId(target, "outObject", "(I)Ljava/lang/Object;"); + TargetInStreamAsync = env.GetMethodId(target, "inStreamAsync", "(IJ)V"); + TargetInStreamOutObjectAsync = + env.GetMethodId(target, "inStreamOutObjectAsync", "(IJ)Ljava/lang/Object;"); + } + + PlatformUtils = env.FindClass("org/apache/ignite/internal/processors/platform/utils/PlatformUtils"); + PlatformUtilsGetStackTrace = env.GetStaticMethodId(PlatformUtils, "getFullStackTrace", + "(Ljava/lang/Throwable;)Ljava/lang/String;"); + PlatformUtilsReallocate = env.GetStaticMethodId(PlatformUtils, "reallocate", "(JI)V"); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs new file mode 100644 index 0000000..b8a8f89 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs @@ -0,0 +1,48 @@ +/* + * 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. + */ + +using System; + +#pragma warning disable 414 // Unused FuncPtr + +namespace Apache.Ignite.Core.Impl.Unmanaged.Jni +{ + using System.Diagnostics.CodeAnalysis; + using System.Runtime.InteropServices; + + /// <summary> + /// JNINativeMethod structure for registering Java -> .NET callbacks. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] + internal struct NativeMethod + { + /// <summary> + /// Method name, char*. + /// </summary> + public IntPtr Name; + + /// <summary> + /// Method signature, char*. + /// </summary> + public IntPtr Signature; + + /// <summary> + /// Function pointer (from <see cref="Marshal.GetFunctionPointerForDelegate"/>). + /// </summary> + public IntPtr FuncPtr; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs deleted file mode 100644 index 32e0a29..0000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.Impl.Unmanaged -{ - using System.Runtime.InteropServices; - - /// <summary> - /// Unmanaged callback handler function pointers. - /// </summary> - [StructLayout(LayoutKind.Sequential, Pack = 0)] - internal unsafe struct UnmanagedCallbackHandlers - { - internal void* target; - - internal void* error; - - internal void* loggerLog; - internal void* loggerIsLevelEnabled; - - internal void* inLongOutLong; - internal void* inLongLongObjectOutLong; - } -}