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

ptupitsyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 0d5a325  IGNITE-12427 .NET: Fix Mono issues
0d5a325 is described below

commit 0d5a325e4d2f8f7cb72025914055baedec2f0ce1
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Sun Dec 22 23:00:56 2019 +0300

    IGNITE-12427 .NET: Fix Mono issues
    
    * Fix P/Invoke in UnmanagedThread
    * Fix GetDefaultAppDomain
    * Fix build.ps1 to work on Linux under PowerShell Core
    
    This enables full development cycle on Linux with Mono, including NuGet 
package creation
---
 .../Binary/BinaryBuilderSelfTest.cs                |   4 +-
 .../Client/ClientProtocolCompatibilityTest.cs      |   4 +-
 .../Apache.Ignite.Core.Tests/Examples/Example.cs   |   3 +-
 .../Apache.Ignite.Core.Tests/Examples/PathUtil.cs  |   4 +-
 .../dotnet/Apache.Ignite.Core.Tests/TestRunner.cs  |   5 +-
 .../Apache.Ignite.Core/Impl/Common/TaskRunner.cs   |   2 +-
 .../Impl/Unmanaged/Jni/AppDomains.cs               |  10 ++
 .../Impl/Unmanaged/UnmanagedThread.cs              |  32 +++++-
 modules/platforms/dotnet/build.ps1                 | 122 +++++++++++----------
 modules/platforms/dotnet/release/verify-nuget.ps1  |   6 +-
 10 files changed, 115 insertions(+), 77 deletions(-)

diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
index 2880e7e..040d5d1 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
@@ -617,7 +617,7 @@ namespace Apache.Ignite.Core.Tests.Binary
             Assert.AreEqual(-88648479, obj1.GetHashCode());
             Assert.AreEqual(obj1.GetHashCode(), obj2.GetHashCode());
 
-            Assert.AreEqual("myType [, int=1, str=foo]", 
Regex.Replace(obj1.ToString(), "idHash=\\d+", ""));
+            Assert.AreEqual("myType [, int=1, str=foo]", 
Regex.Replace(obj1.ToString(), "idHash=[+-]?\\d+", ""));
         }
 
         /// <summary>
@@ -1892,7 +1892,7 @@ namespace Apache.Ignite.Core.Tests.Binary
             Assert.AreEqual(obj1, obj2);
             Assert.AreEqual(obj1.GetHashCode(), obj2.GetHashCode());
 
-            Assert.AreEqual("sortTest [, a=2, b=1, c=3]", 
Regex.Replace(obj1.ToString(), "idHash=\\d+", ""));
+            Assert.AreEqual("sortTest [, a=2, b=1, c=3]", 
Regex.Replace(obj1.ToString(), "idHash=[+-]?\\d+", ""));
 
             // Skip header, take 3 fields (type code + value).
             var bytes1 = obj1.Data.Skip(24).Take(6).ToArray();
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientProtocolCompatibilityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientProtocolCompatibilityTest.cs
index a6770ff..4e2b747 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientProtocolCompatibilityTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientProtocolCompatibilityTest.cs
@@ -175,12 +175,12 @@ namespace Apache.Ignite.Core.Tests.Client
         /// <summary>
         /// Gets the client with specified protocol version.
         /// </summary>
-        private IgniteClient GetClient(ClientProtocolVersion version, bool 
EnableAffinityAwareness = false)
+        private IgniteClient GetClient(ClientProtocolVersion version, bool 
enableAffinityAwareness = false)
         {
             var cfg = new IgniteClientConfiguration(GetClientConfiguration())
             {
                 ProtocolVersion = version,
-                EnableAffinityAwareness = EnableAffinityAwareness
+                EnableAffinityAwareness = enableAffinityAwareness
             };
 
             return (IgniteClient) Ignition.StartClient(cfg);
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/Example.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/Example.cs
index de43666..2859e5f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/Example.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/Example.cs
@@ -84,7 +84,8 @@ namespace Apache.Ignite.Core.Tests.Examples
 
             foreach (var type in types)
             {
-                var sourceFile = sourceFiles.Single(x => 
x.EndsWith(string.Format("\\{0}.cs", type.Name)));
+                var sourceFile = sourceFiles.Single(
+                    x => x.EndsWith(string.Format("{0}{1}.cs", 
Path.DirectorySeparatorChar, type.Name)));
 
                 var sourceCode = File.ReadAllText(sourceFile);
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/PathUtil.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/PathUtil.cs
index b265ea2..969b28b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/PathUtil.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/PathUtil.cs
@@ -34,13 +34,13 @@ namespace Apache.Ignite.Core.Tests.Examples
         /// Examples source code path.
         /// </summary>
         public static readonly string ExamplesSourcePath =
-            Path.Combine(IgniteHome, @"modules\platforms\dotnet\examples");
+            Path.Combine(IgniteHome, "modules", "platforms", "dotnet", 
"examples");
 
         /// <summary>
         /// Examples application configuration path.
         /// </summary>
         public static readonly string ExamplesAppConfigPath =
-            Path.Combine(ExamplesSourcePath, 
@"Apache.Ignite.Examples\App.config");
+            Path.Combine(ExamplesSourcePath, "Apache.Ignite.Examples", 
"App.config");
 
         /// <summary>
         /// Gets the full configuration path.
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
index ab6af60..fef321f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
@@ -24,7 +24,6 @@ namespace Apache.Ignite.Core.Tests
     using System.Reflection;
     using Apache.Ignite.Core.Tests.Binary.Serializable;
     using Apache.Ignite.Core.Tests.Cache;
-    using Apache.Ignite.Core.Tests.Cache.Query.Linq;
     using Apache.Ignite.Core.Tests.Client.Cache;
     using Apache.Ignite.Core.Tests.Compute;
     using Apache.Ignite.Core.Tests.Memory;
@@ -74,10 +73,10 @@ namespace Apache.Ignite.Core.Tests
             var basicTests = new[]
             {
                 typeof(ComputeApiTest),
-                typeof(CacheLinqTest),
                 typeof(SqlDmlTest),
                 typeof(LinqTest),
-                typeof(PersistenceTest)
+                typeof(PersistenceTest),
+                typeof(CacheTest)
             };
 
             Environment.ExitCode = TestAll(basicTests, true);
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/TaskRunner.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/TaskRunner.cs
index 13eec48..b6c8f66 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/TaskRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/TaskRunner.cs
@@ -25,7 +25,7 @@ namespace Apache.Ignite.Core.Impl.Common
     /// Extensions for <see cref="Task"/> classes.
     /// Fixes the issue with <see cref="TaskScheduler.Current"/> being used by 
default by system APIs.
     /// Current scheduler can be anything, but in most cases we just want 
thread pool when starting a task.
-    /// <see cref="TaskScheduler.Default"/> is normally <see 
cref="ThreadPoolTaskScheduler"/>.
+    /// <see cref="TaskScheduler.Default"/> is normally 
ThreadPoolTaskScheduler.
     /// </summary>
     internal static class TaskRunner
     {
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
index bb36784..e307ed0 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
@@ -58,6 +58,16 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
         /// </summary>
         public static _AppDomain GetDefaultAppDomain()
         {
+            if (Os.IsMono)
+            {
+                var prop = typeof(AppDomain).GetProperty(
+                    "DefaultDomain", System.Reflection.BindingFlags.NonPublic 
| System.Reflection.BindingFlags.Static);
+                
+                Debug.Assert(prop != null);
+                
+                return (_AppDomain) prop.GetValue(null, null);
+            }
+
             object objHost;
             int hr = NativeMethods.CLRCreateInstance(ref CLSID_CLRMetaHost, 
ref IID_CLRMetaHost, out objHost);
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedThread.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedThread.cs
index b27da51..352d22f 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedThread.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedThread.cs
@@ -68,7 +68,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             if (Os.IsLinux)
             {
                 int tlsIndex;
-                var res = NativeMethodsLinux.pthread_key_create(new 
IntPtr(&tlsIndex), callbackPtr);
+                var res = Os.IsMono
+                    ? NativeMethodsMono.pthread_key_create(new 
IntPtr(&tlsIndex), callbackPtr)
+                    : NativeMethodsLinux.pthread_key_create(new 
IntPtr(&tlsIndex), callbackPtr);
 
                 NativeMethodsLinux.CheckResult(res);
 
@@ -101,7 +103,10 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             }
             else if (Os.IsLinux)
             {
-                var res = NativeMethodsLinux.pthread_key_delete(callbackId);
+                var res = Os.IsMono 
+                    ? NativeMethodsMono.pthread_key_delete(callbackId)
+                    : NativeMethodsLinux.pthread_key_delete(callbackId);
+                
                 NativeMethodsLinux.CheckResult(res);
             }
             else
@@ -134,7 +139,10 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             }
             else if (Os.IsLinux)
             {
-                var res = NativeMethodsLinux.pthread_setspecific(callbackId, 
threadLocalValue);
+                var res = Os.IsMono 
+                    ? NativeMethodsMono.pthread_setspecific(callbackId, 
threadLocalValue)
+                    : NativeMethodsLinux.pthread_setspecific(callbackId, 
threadLocalValue);
+                
                 NativeMethodsLinux.CheckResult(res);
             }
             else
@@ -212,5 +220,23 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             [DllImport("libSystem.dylib")]
             public static extern int pthread_setspecific(int key, IntPtr 
value);
         }
+        
+        /// <summary>
+        /// Mono on Linux requires __Internal instead of libcoreclr.so.
+        /// </summary>
+        private static class NativeMethodsMono
+        {
+            [SuppressMessage("Microsoft.Design", 
"CA1060:MovePInvokesToNativeMethodsClass", Justification = "Reviewed.")]
+            [DllImport("__Internal")]
+            public static extern int pthread_key_create(IntPtr key, IntPtr 
destructorCallback);
+            
+            [SuppressMessage("Microsoft.Design", 
"CA1060:MovePInvokesToNativeMethodsClass", Justification = "Reviewed.")]
+            [DllImport("__Internal")]
+            public static extern int pthread_key_delete(int key);
+
+            [SuppressMessage("Microsoft.Design", 
"CA1060:MovePInvokesToNativeMethodsClass", Justification = "Reviewed.")]
+            [DllImport("__Internal")]
+            public static extern int pthread_setspecific(int key, IntPtr 
value);
+        }
     }
 }
diff --git a/modules/platforms/dotnet/build.ps1 
b/modules/platforms/dotnet/build.ps1
index 4db0031..3710d94 100644
--- a/modules/platforms/dotnet/build.ps1
+++ b/modules/platforms/dotnet/build.ps1
@@ -97,6 +97,22 @@ param (
        [string]$version=""
  )
 
+# 0) Functions
+function Make-Dir([string]$dirPath) {
+    New-Item -Path $dirPath -ItemType "directory" -Force
+    Remove-Item -Force $dirPath\*.*
+}
+
+function Exec([string]$command) {
+    try {
+        iex "& $command"
+    } catch {
+        echo "Command failed: $command"
+        throw
+        exit -1
+    }
+}
+
 # 1) Build Java (Maven)
 # Detect Ignite root directory
 cd $PSScriptRoot\..
@@ -126,19 +142,14 @@ if (!$skipJava) {
     }
 
     # Install Maven Wrapper
-    cmd /c "$mv -N io.takari:maven:wrapper -Dmaven=3.5.2"
-    $mv = "mvnw.cmd"
+    Exec "$mv --% -N io.takari:maven:wrapper -Dmaven=3.5.2"
+    $mv = If ($IsLinux) { "./mvnw" } else { "mvnw.cmd" }
 
     # Run Maven
     echo "Starting Java (Maven) build..."
     
     $mvnTargets = if ($clean)  { "clean package" } else { "package" }
-    cmd /c "$mv $mvnTargets -DskipTests $mavenOpts"
-
-    # Check result
-    if ($LastExitCode -ne 0) {
-        echo "Java (Maven) build failed."; exit -1
-    }
+    Exec "$mv --% $mvnTargets -DskipTests $mavenOpts"
 }
 else {
     echo "Java (Maven) build skipped."
@@ -146,12 +157,12 @@ else {
 
 # Copy (relevant) jars
 $libsDir = "$PSScriptRoot\bin\libs"
-mkdir -Force $libsDir; del -Force $libsDir\*.*
+Make-Dir($libsDir)
 
-ls $jarDirs.Split(',') *.jar -recurse `
+Get-ChildItem $jarDirs.Split(',') *.jar -recurse `
    -include 
"ignite-core*","ignite-indexing*","ignite-shmem*","ignite-spring*","lucene*","h2*","cache-api*","commons-*","spring*"
 `
    -exclude "*-sources*","*-javadoc*","*-tests*","*optional*" `
-   | % { copy -Force $_ $libsDir }
+   | % { Copy-Item -Force $_ $libsDir }
    
 # Restore directory
 cd $PSScriptRoot
@@ -167,43 +178,48 @@ if ((Get-Command $ng -ErrorAction SilentlyContinue) -eq 
$null) {
 
        if (-not (Test-Path $ng)) {
                echo "Downloading NuGet..."
-               (New-Object 
System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe";,
 "nuget.exe");    
+               (New-Object 
System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe";,
 "nuget.exe")    
        }
 }
 
 echo "Using NuGet from: $ng"
 
 if (!$skipDotNet) {
-       # Detect MSBuild 4.0+
-       for ($i=20; $i -ge 4; $i--) {
-               $regKey = "HKLM:\software\Microsoft\MSBuild\ToolsVersions\$i.0"
-               if (Test-Path $regKey) { break }
-       }
+    $msBuild = "msbuild"
 
-       if (!(Test-Path $regKey)) {
-               echo "Failed to detect MSBuild path, exiting."
-               exit -1
-       }
+    if ((Get-Command $msBuild -ErrorAction SilentlyContinue) -eq $null)
+    {
+        # Detect MSBuild 4.0+
+        for ($i = 20; $i -ge 4; $i--) {
+            $regKey = "HKLM:\software\Microsoft\MSBuild\ToolsVersions\$i.0"
+            if (Test-Path $regKey)
+            {
+                break
+            }
+        }
 
-       $msbuildExe = (join-path -path (Get-ItemProperty 
$regKey)."MSBuildToolsPath" -childpath "msbuild.exe")
-       echo "MSBuild detected at '$msbuildExe'."
+        if (!(Test-Path $regKey))
+        {
+            echo "Failed to detect MSBuild path, exiting."
+            exit -1
+        }
+
+        $msBuild = (Join-Path -path (Get-ItemProperty 
$regKey)."MSBuildToolsPath" -childpath "msbuild.exe")
+        $msBuild = "`"$msBuild`""  # Put in quotes and escape to handle 
whitespace in path
+    }
+    
+    echo "MSBuild detected at '$msBuild'."
 
        # Restore NuGet packages
        echo "Restoring NuGet..."
-       & $ng restore Apache.Ignite.sln
+       Exec "$ng restore Apache.Ignite.sln"
 
        # Build
        $targets = if ($clean) {"Clean;Rebuild"} else {"Build"}
        $codeAnalysis = if ($skipCodeAnalysis) {"/p:RunCodeAnalysis=false"} 
else {""}
-       $msBuildCommand = "`"$msBuildExe`" Apache.Ignite.sln /target:$targets 
/p:Configuration=$configuration /p:Platform=`"$platform`" $codeAnalysis 
/p:UseSharedCompilation=false"
+       $msBuildCommand = "$msBuild Apache.Ignite.sln /target:$targets 
/p:Configuration=$configuration /p:Platform=`"$platform`" $codeAnalysis 
/p:UseSharedCompilation=false"
        echo "Starting MsBuild: '$msBuildCommand'"
-       cmd /c $msBuildCommand   
-
-       # Check result
-       if ($LastExitCode -ne 0) {
-               echo ".NET build failed."
-               exit -1
-       }
+       Exec $msBuildCommand   
 }
 
 if(!$skipDotNetCore) {
@@ -213,48 +229,40 @@ if(!$skipDotNetCore) {
     if ($clean) {
         $cleanCommand = "dotnet clean $targetSolution -c $configuration"
         echo "Starting dotnet clean: '$cleanCommand'"
-        cmd /c $cleanCommand
+        Exec $cleanCommand
     }
 
     $publishCommand = "dotnet publish $targetSolution -c $configuration"
        echo "Starting dotnet publish: '$publishCommand'"
-       cmd /c $publishCommand    
-
-    # Check result
-    if ($LastExitCode -ne 0) {
-        echo ".NET Core build failed."
-        exit -1
-    }
+       Exec $publishCommand    
 }
 
 if ($asmDirs) {
-    ls $asmDirs.Split(',') | % `
+    Get-ChildItem $asmDirs.Split(',') | % `
     {
-        $projName = [System.IO.Path]::GetFileNameWithoutExtension($_.Name);
+        $projName = [System.IO.Path]::GetFileNameWithoutExtension($_.Name)
 
         if ($_.Name.EndsWith(".exe.config")) {
-            $projName = 
[System.IO.Path]::GetFileNameWithoutExtension($projName);
+            $projName = 
[System.IO.Path]::GetFileNameWithoutExtension($projName)
         }
 
         if ($projName.StartsWith("Apache.Ignite")) {
             $target = "$projName\bin\Release"
-            mkdir -Force $target
-
-            xcopy /s /y $_.FullName $target
+            Make-Dir($target)
         }
     }    
 }
 
 # Copy binaries
-mkdir -Force bin; del -Force -Recurse bin\*.*
+Make-Dir("bin")
 
-ls *.csproj -Recurse | where Name -NotLike "*Examples*" `
+Get-ChildItem *.csproj -Recurse | where Name -NotLike "*Examples*" `
                      | where Name -NotLike "*Tests*" `
                      | where Name -NotLike "*Benchmarks*" | % {
-    $binDir = if (($configuration -eq "Any CPU") -or ($_.Name -ne 
"Apache.Ignite.Core.csproj")) `
+    $binDir = if (($platform -eq "Any CPU") -or ($_.Name -ne 
"Apache.Ignite.Core.csproj") -or $IsLinux) `
                 {"bin\$configuration"} else {"bin\$platform\$configuration"}
-    $dir = join-path (split-path -parent $_) $binDir    
-    xcopy /s /y $dir\*.* bin
+    $dir = join-path (split-path -parent $_) $binDir
+    Copy-Item -Force $dir\*.* bin
 }
 
 
@@ -267,21 +275,15 @@ if (!$skipNuGet) {
     }
 
     $nupkgDir = "nupkg"
-    mkdir -Force $nupkgDir; del -Force $nupkgDir\*.*
+    Make-Dir($nupkgDir)
 
     # Detect version
     $ver = if ($version) { $version } else { (gi 
Apache.Ignite.Core\bin\Release\Apache.Ignite.Core.dll).VersionInfo.ProductVersion
 }
 
     # Find all nuspec files and run 'nuget pack' either directly, or on 
corresponding csproj files (if present)
-    ls *.nuspec -Recurse  `
+    Get-ChildItem *.nuspec -Recurse  `
         | % { 
-            & $ng pack $_ -Prop Configuration=Release -Prop Platform=AnyCPU 
-Version $ver -OutputDirectory $nupkgDir
-
-            # check result
-            if ($LastExitCode -ne 0)
-            {
-                echo "NuGet pack failed."; exit -1
-            }
+            Exec "$ng pack $_ -Prop Configuration=Release -Prop 
Platform=AnyCPU -Version $ver -OutputDirectory $nupkgDir"
         }
 
     echo "NuGet packages created in '$pwd\$nupkgDir'."
diff --git a/modules/platforms/dotnet/release/verify-nuget.ps1 
b/modules/platforms/dotnet/release/verify-nuget.ps1
index fdde984..c2885bf 100644
--- a/modules/platforms/dotnet/release/verify-nuget.ps1
+++ b/modules/platforms/dotnet/release/verify-nuget.ps1
@@ -48,7 +48,7 @@ if (!(Test-Path $dir)) {
     throw "Path does not exist: '$packageDir' (resolved to '$dir')"
 }
 
-$packages = ls $dir *.nupkg
+$packages = Get-ChildItem $dir *.nupkg
 if ($packages.Length -eq 0) {
     throw "nupkg files not found in '$dir'"
 }
@@ -59,8 +59,8 @@ echo "Verifying $($packages.Length) packages from '$dir'..."
 
 # Create test dir
 $testDir = Join-Path $PSScriptRoot "test-proj"
-mkdir -Force $testDir
-del -Force $testDir\*.*
+New-Item -Path $testDir -ItemType "directory" -Force
+Remove-Item -Force $testDir\*.*
 cd $testDir
 
 

Reply via email to