From db4346aae0e4f6cb3f76f5be683c26f8a79adaca Mon Sep 17 00:00:00 2001 From: AurelienMIMT <73344115+AurelienMIMT@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:30:09 +0100 Subject: [PATCH 01/21] save --- Psi.sln | 9 ++++++ .../Microsoft.Psi.Media.Native.x64.vcxproj | 6 ++-- ...soft.Psi.Media_Interop.Windows.x64.vcxproj | 6 ++-- .../HoloLensCaptureApp.csproj | 5 +++- .../HoloLensCaptureApp/Package.appxmanifest | 4 +-- ....Psi.RealSense_Interop.Windows.x64.vcxproj | 6 ++-- .../Common/TypeResolutionHelper.cs | 8 +++-- .../Microsoft.Psi/Remoting/RemoteExporter.cs | 16 ++++++++-- TestConnection/Program.cs | 30 +++++++++++++++++++ TestConnection/TestConnection.csproj | 14 +++++++++ 10 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 TestConnection/Program.cs create mode 100644 TestConnection/TestConnection.csproj diff --git a/Psi.sln b/Psi.sln index 55b8270ae..b8aa79742 100644 --- a/Psi.sln +++ b/Psi.sln @@ -231,6 +231,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HoloLensCaptureInterop", "S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Calibration", "Sources\Calibration\Test.Psi.Calibration\Test.Psi.Calibration.csproj", "{41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConnection", "TestConnection\TestConnection.csproj", "{E4D7E21F-8469-456F-828D-DE1D2590E4EA}" + ProjectSection(ProjectDependencies) = postProject + {04147400-0AB0-4F07-9975-D4B7E58150DB} = {04147400-0AB0-4F07-9975-D4B7E58150DB} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -519,6 +524,10 @@ Global {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.Build.0 = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sources/Media/Microsoft.Psi.Media.Native.x64/Microsoft.Psi.Media.Native.x64.vcxproj b/Sources/Media/Microsoft.Psi.Media.Native.x64/Microsoft.Psi.Media.Native.x64.vcxproj index 8d8ce72d4..cd31eadb1 100644 --- a/Sources/Media/Microsoft.Psi.Media.Native.x64/Microsoft.Psi.Media.Native.x64.vcxproj +++ b/Sources/Media/Microsoft.Psi.Media.Native.x64/Microsoft.Psi.Media.Native.x64.vcxproj @@ -15,7 +15,7 @@ {C50F7F21-BEB0-4366-B73F-859EEBC3ED42} Win32Proj MicrosoftPsiMediaNativex64 - 10.0.19041.0 + 10.0 4.7.2 @@ -32,14 +32,14 @@ DynamicLibrary true - v142 + v143 Unicode Spectre DynamicLibrary false - v142 + v143 true Unicode Spectre diff --git a/Sources/Media/Microsoft.Psi.Media_Interop.Windows.x64/Microsoft.Psi.Media_Interop.Windows.x64.vcxproj b/Sources/Media/Microsoft.Psi.Media_Interop.Windows.x64/Microsoft.Psi.Media_Interop.Windows.x64.vcxproj index 6d917eb5f..77e6684ab 100644 --- a/Sources/Media/Microsoft.Psi.Media_Interop.Windows.x64/Microsoft.Psi.Media_Interop.Windows.x64.vcxproj +++ b/Sources/Media/Microsoft.Psi.Media_Interop.Windows.x64/Microsoft.Psi.Media_Interop.Windows.x64.vcxproj @@ -16,7 +16,7 @@ ManagedCProj VideoCapture Microsoft.Psi.Media_Interop.Windows.x64 - 10.0.19041.0 + 10.0 $(FFMPEGDir)\lib\avdevice.lib;$(FFMPEGDir)\lib\avfilter.lib;$(FFMPEGDir)\lib\postproc.lib;$(FFMPEGDir)\lib\swresample.lib;$(FFMPEGDir)\lib\avcodec.lib;$(FFMPEGDir)\lib\avformat.lib;$(FFMPEGDir)\lib\avutil.lib;$(FFMPEGDir)\lib\swscale.lib @@ -34,7 +34,7 @@ true true Unicode - v142 + v143 Spectre @@ -42,7 +42,7 @@ false true Unicode - v142 + v143 Spectre diff --git a/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/HoloLensCaptureApp.csproj b/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/HoloLensCaptureApp.csproj index 839801c5b..82bb340bb 100644 --- a/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/HoloLensCaptureApp.csproj +++ b/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/HoloLensCaptureApp.csproj @@ -17,7 +17,7 @@ 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} true - false + True Language=en ..\..\..\..\Build\Microsoft.Psi.ruleset true @@ -27,6 +27,8 @@ arm True True + 225DDDE2A5679E6037540DA0ECCE5C3BE1EBB290 + SHA256 ARM @@ -143,6 +145,7 @@ + diff --git a/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/Package.appxmanifest b/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/Package.appxmanifest index 3779d06d2..d51836e87 100644 --- a/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/Package.appxmanifest +++ b/Sources/MixedReality/HoloLensCapture/HoloLensCaptureApp/Package.appxmanifest @@ -9,8 +9,8 @@ + Publisher="CN=AurélienM" + Version="1.0.2.0" /> diff --git a/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/Microsoft.Psi.RealSense_Interop.Windows.x64.vcxproj b/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/Microsoft.Psi.RealSense_Interop.Windows.x64.vcxproj index 4c4e5a8b2..08e17298c 100644 --- a/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/Microsoft.Psi.RealSense_Interop.Windows.x64.vcxproj +++ b/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/Microsoft.Psi.RealSense_Interop.Windows.x64.vcxproj @@ -16,14 +16,14 @@ v4.7.2 ManagedCProj MicrosoftPsiRealSenseWindows_InteropWindowsx64 - 10.0.19041.0 + 10.0 Microsoft.Psi.RealSense_Interop.Windows.x64 DynamicLibrary true - v142 + v143 true Unicode Spectre @@ -31,7 +31,7 @@ DynamicLibrary false - v142 + v143 true Unicode Spectre diff --git a/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs b/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs index 14cda5590..ef3126779 100644 --- a/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs +++ b/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs @@ -21,8 +21,8 @@ public static class TypeResolutionHelper /// The requested type, or null if the type was not found. public static Type GetVerifiedType(string typeName) { - var type = Type.GetType(typeName, AssemblyResolver, null); - + // var type = Type.GetType(typeName, AssemblyResolver, null); + var type = Type.GetType(typeName); if (type == null) { // Unable to resolve type. Attempt to resolve base class library types @@ -30,7 +30,9 @@ public static Type GetVerifiedType(string typeName) // Type.GetType will attempt to resolve types without assembly names from // mscorlib/System.Private.CoreLib or the currently executing assembly. typeName = RemoveCoreAssemblyName(typeName); - type = Type.GetType(typeName, AssemblyResolver, null); + + // type = Type.GetType(typeName, AssemblyResolver, null); + type = Type.GetType(typeName); } return type; diff --git a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs index 0935318d6..a9e67db7a 100644 --- a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs +++ b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs @@ -10,6 +10,7 @@ namespace Microsoft.Psi.Remoting using System.IO; using System.Net; using System.Net.Sockets; + using System.Numerics; using System.Threading; using Microsoft.Psi.Common; using Microsoft.Psi.Data; @@ -217,9 +218,9 @@ private void AcceptDataClientsBackground() { try { - this.dataTransport.StartListening(); while (!this.disposed) { + this.dataTransport.StartListening(); var client = this.dataTransport.AcceptClient(); var guid = Guid.Empty; try @@ -229,7 +230,7 @@ private void AcceptDataClientsBackground() if (this.connections.TryGetValue(guid, out Connection connection)) { - connection.JoinBackground(client); + connection.JoinBackgroundThread(client); } else { @@ -265,6 +266,7 @@ private sealed class Connection : IDisposable private Stream stream; private PsiStoreReader storeReader; private TimeInterval interval; + private Thread connectionThread; public Connection(TcpClient client, ITransport dataTransport, string name, string path, Action onDisconnect, Exporter exporter, long maxBytesPerSecond, double bytesPerSecondSmoothingWindowSeconds) { @@ -278,6 +280,7 @@ public Connection(TcpClient client, ITransport dataTransport, string name, strin this.exporter = exporter; this.maxBytesPerSecond = maxBytesPerSecond; this.bytesPerSecondSmoothingWindowSeconds = bytesPerSecondSmoothingWindowSeconds; + this.connectionThread = null; } public Guid Id => this.id; @@ -332,6 +335,12 @@ public void Connect() } } + public void JoinBackgroundThread(ITransportClient client) + { + this.connectionThread = new Thread(() => this.JoinBackground(client)); + this.connectionThread.Start(); + } + public void JoinBackground(ITransportClient client) { double avgBytesPerSec = 0; @@ -393,11 +402,14 @@ public void Dispose() this.client = null; this.stream.Dispose(); this.stream = null; + this.connectionThread.Abort(); + this.connectionThread = null; } private void Disconnect() { this.onDisconnect(this.id); + this.connectionThread.Abort(); this.Dispose(); } diff --git a/TestConnection/Program.cs b/TestConnection/Program.cs new file mode 100644 index 000000000..65fe44b72 --- /dev/null +++ b/TestConnection/Program.cs @@ -0,0 +1,30 @@ +using Microsoft.Psi; +using Microsoft.Psi.Remoting; + +namespace TestConnection +{ + internal class Program + { + static void Main(string[] args) + { + // Create the \psi pipeline + Pipeline pipeline = Pipeline.Create("TestConnection"); + + RemoteExporter exporter = new RemoteExporter(pipeline, 11411, TransportKind.Tcp); + // Create a timer component that produces a message every second + var timer = Timers.Timer(pipeline, TimeSpan.FromSeconds(1)); + + // For each message created by the timer + exporter.Exporter.Write(timer.Out, "Test"); + + // Start the pipeline running + pipeline.RunAsync(); + + // Wainting for an out key + Console.WriteLine("Press any key to stop the application."); + Console.ReadLine(); + // Stop correctly the pipeline. + pipeline.Dispose(); + } + } +} diff --git a/TestConnection/TestConnection.csproj b/TestConnection/TestConnection.csproj new file mode 100644 index 000000000..84d39688d --- /dev/null +++ b/TestConnection/TestConnection.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + From 2cde08b379006831ee8a94e75bf8b3ab9abb83d7 Mon Sep 17 00:00:00 2001 From: AurelienMIMT <73344115+AurelienMIMT@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:55:26 +0100 Subject: [PATCH 02/21] last version --- Psi.sln | 293 +++++++++++++++++- .../Common/TypeResolutionHelper.cs | 6 +- 2 files changed, 291 insertions(+), 8 deletions(-) diff --git a/Psi.sln b/Psi.sln index b8aa79742..4cc65e651 100644 --- a/Psi.sln +++ b/Psi.sln @@ -53,7 +53,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Speech.Windows", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Audio", "Sources\Audio\Test.Psi.Audio\Test.Psi.Audio.csproj", "{7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Psi.Imaging.Windows", "Sources\Imaging\Test.Psi.Imaging.Windows\Test.Psi.Imaging.Windows.csproj", "{191DF615-3D8F-45A3-B763-DD4A604A712A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Imaging.Windows", "Sources\Imaging\Test.Psi.Imaging.Windows\Test.Psi.Imaging.Windows.csproj", "{191DF615-3D8F-45A3-B763-DD4A604A712A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Toolkits", "Toolkits", "{B592009C-5137-4D7F-8B50-C7D8500230D6}" EndProject @@ -232,302 +232,587 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Calibration", "Sources\Calibration\Test.Psi.Calibration\Test.Psi.Calibration.csproj", "{41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConnection", "TestConnection\TestConnection.csproj", "{E4D7E21F-8469-456F-828D-DE1D2590E4EA}" - ProjectSection(ProjectDependencies) = postProject - {04147400-0AB0-4F07-9975-D4B7E58150DB} = {04147400-0AB0-4F07-9975-D4B7E58150DB} - EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|x64.ActiveCfg = Debug|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|x64.Build.0 = Debug|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|Any CPU.ActiveCfg = Release|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|Any CPU.Build.0 = Release|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|x64.ActiveCfg = Release|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|x64.Build.0 = Release|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|x64.ActiveCfg = Debug|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|x64.Build.0 = Debug|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|Any CPU.Build.0 = Release|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|x64.ActiveCfg = Release|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|x64.Build.0 = Release|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|Any CPU.Build.0 = Debug|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|x64.ActiveCfg = Debug|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|x64.Build.0 = Debug|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|Any CPU.ActiveCfg = Release|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|Any CPU.Build.0 = Release|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|x64.ActiveCfg = Release|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|x64.Build.0 = Release|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|x64.ActiveCfg = Debug|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|x64.Build.0 = Debug|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|Any CPU.ActiveCfg = Release|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|Any CPU.Build.0 = Release|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|x64.ActiveCfg = Release|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|x64.Build.0 = Release|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|x64.ActiveCfg = Debug|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|x64.Build.0 = Debug|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|Any CPU.ActiveCfg = Release|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|Any CPU.Build.0 = Release|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|x64.ActiveCfg = Release|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|x64.Build.0 = Release|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|x64.ActiveCfg = Debug|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|x64.Build.0 = Debug|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|Any CPU.Build.0 = Release|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|x64.ActiveCfg = Release|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|x64.Build.0 = Release|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|x64.ActiveCfg = Debug|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|x64.Build.0 = Debug|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Release|Any CPU.ActiveCfg = Release|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Release|Any CPU.Build.0 = Release|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Release|x64.ActiveCfg = Release|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Release|x64.Build.0 = Release|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|x64.ActiveCfg = Debug|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|x64.Build.0 = Debug|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|Any CPU.Build.0 = Release|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|x64.ActiveCfg = Release|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|x64.Build.0 = Release|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|x64.ActiveCfg = Debug|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|x64.Build.0 = Debug|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|Any CPU.ActiveCfg = Release|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|Any CPU.Build.0 = Release|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|x64.ActiveCfg = Release|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|x64.Build.0 = Release|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|x64.ActiveCfg = Debug|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|x64.Build.0 = Debug|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|Any CPU.ActiveCfg = Release|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|Any CPU.Build.0 = Release|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|x64.ActiveCfg = Release|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|x64.Build.0 = Release|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|x64.ActiveCfg = Debug|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|x64.Build.0 = Debug|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|Any CPU.Build.0 = Release|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|x64.ActiveCfg = Release|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|x64.Build.0 = Release|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|x64.ActiveCfg = Debug|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|x64.Build.0 = Debug|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|Any CPU.ActiveCfg = Release|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|Any CPU.Build.0 = Release|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|x64.ActiveCfg = Release|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|x64.Build.0 = Release|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|x64.ActiveCfg = Debug|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|x64.Build.0 = Debug|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|Any CPU.ActiveCfg = Release|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|Any CPU.Build.0 = Release|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|x64.ActiveCfg = Release|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|x64.Build.0 = Release|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|x64.ActiveCfg = Debug|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|x64.Build.0 = Debug|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|Any CPU.Build.0 = Release|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|x64.ActiveCfg = Release|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|x64.Build.0 = Release|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|x64.ActiveCfg = Debug|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|x64.Build.0 = Debug|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|Any CPU.Build.0 = Release|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|x64.ActiveCfg = Release|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|x64.Build.0 = Release|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|x64.ActiveCfg = Debug|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|x64.Build.0 = Debug|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|Any CPU.Build.0 = Release|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|x64.ActiveCfg = Release|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|x64.Build.0 = Release|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|x64.ActiveCfg = Debug|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|x64.Build.0 = Debug|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|Any CPU.Build.0 = Release|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|x64.ActiveCfg = Release|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|x64.Build.0 = Release|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|x64.Build.0 = Debug|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|Any CPU.Build.0 = Release|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|x64.ActiveCfg = Release|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|x64.Build.0 = Release|Any CPU {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|Any CPU.ActiveCfg = Debug|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|Any CPU.Build.0 = Debug|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|x64.ActiveCfg = Debug|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|x64.Build.0 = Debug|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|Any CPU.ActiveCfg = Release|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|Any CPU.Build.0 = Release|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|x64.ActiveCfg = Release|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|x64.Build.0 = Release|x64 {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|x64.ActiveCfg = Debug|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|x64.Build.0 = Debug|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|Any CPU.ActiveCfg = Release|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|Any CPU.Build.0 = Release|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|x64.ActiveCfg = Release|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|x64.Build.0 = Release|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|x64.ActiveCfg = Debug|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|x64.Build.0 = Debug|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|Any CPU.ActiveCfg = Release|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|Any CPU.Build.0 = Release|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|x64.ActiveCfg = Release|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|x64.Build.0 = Release|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|Any CPU.Build.0 = Debug|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|x64.ActiveCfg = Debug|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|x64.Build.0 = Debug|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|Any CPU.ActiveCfg = Release|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|Any CPU.Build.0 = Release|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|x64.ActiveCfg = Release|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|x64.Build.0 = Release|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|x64.ActiveCfg = Debug|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|x64.Build.0 = Debug|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|Any CPU.Build.0 = Release|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|x64.ActiveCfg = Release|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|x64.Build.0 = Release|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|x64.ActiveCfg = Debug|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|x64.Build.0 = Debug|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|Any CPU.Build.0 = Release|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|x64.ActiveCfg = Release|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|x64.Build.0 = Release|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|x64.ActiveCfg = Debug|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|x64.Build.0 = Debug|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|Any CPU.Build.0 = Release|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|x64.ActiveCfg = Release|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|x64.Build.0 = Release|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|x64.ActiveCfg = Debug|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|x64.Build.0 = Debug|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|Any CPU.ActiveCfg = Release|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|Any CPU.Build.0 = Release|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|x64.ActiveCfg = Release|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|x64.Build.0 = Release|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|x64.Build.0 = Debug|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|Any CPU.Build.0 = Release|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|x64.ActiveCfg = Release|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|x64.Build.0 = Release|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|x64.ActiveCfg = Debug|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|x64.Build.0 = Debug|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|Any CPU.Build.0 = Release|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|x64.ActiveCfg = Release|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|x64.Build.0 = Release|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|x64.Build.0 = Debug|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|Any CPU.Build.0 = Release|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|x64.ActiveCfg = Release|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|x64.Build.0 = Release|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|x64.ActiveCfg = Debug|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|x64.Build.0 = Debug|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|Any CPU.ActiveCfg = Release|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|Any CPU.Build.0 = Release|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|x64.ActiveCfg = Release|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|x64.Build.0 = Release|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|x64.ActiveCfg = Debug|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|x64.Build.0 = Debug|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|Any CPU.ActiveCfg = Release|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|Any CPU.Build.0 = Release|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|x64.ActiveCfg = Release|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|x64.Build.0 = Release|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|x64.Build.0 = Debug|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|Any CPU.Build.0 = Release|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|x64.ActiveCfg = Release|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|x64.Build.0 = Release|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|x64.ActiveCfg = Debug|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|x64.Build.0 = Debug|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|Any CPU.ActiveCfg = Release|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|Any CPU.Build.0 = Release|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|x64.ActiveCfg = Release|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|x64.Build.0 = Release|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|x64.ActiveCfg = Debug|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|x64.Build.0 = Debug|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|Any CPU.Build.0 = Release|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|x64.ActiveCfg = Release|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|x64.Build.0 = Release|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|x64.ActiveCfg = Debug|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|x64.Build.0 = Debug|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|Any CPU.Build.0 = Release|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|x64.ActiveCfg = Release|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|x64.Build.0 = Release|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|x64.Build.0 = Debug|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|Any CPU.Build.0 = Release|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|x64.ActiveCfg = Release|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|x64.Build.0 = Release|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|x64.Build.0 = Debug|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|Any CPU.Build.0 = Release|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|x64.ActiveCfg = Release|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|x64.Build.0 = Release|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|x64.Build.0 = Debug|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|Any CPU.Build.0 = Release|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|x64.ActiveCfg = Release|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|x64.Build.0 = Release|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|x64.Build.0 = Debug|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.Build.0 = Release|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|x64.ActiveCfg = Release|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|x64.Build.0 = Release|Any CPU {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|Any CPU.ActiveCfg = Debug|x64 {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|Any CPU.Build.0 = Debug|x64 + {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|x64.ActiveCfg = Debug|x64 + {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|x64.Build.0 = Debug|x64 {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|Any CPU.ActiveCfg = Release|x64 {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|Any CPU.Build.0 = Release|x64 + {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|x64.ActiveCfg = Release|x64 + {C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|x64.Build.0 = Release|x64 {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|x64.Build.0 = Debug|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|Any CPU.Build.0 = Release|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|x64.ActiveCfg = Release|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|x64.Build.0 = Release|Any CPU {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|Any CPU.ActiveCfg = Debug|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|Any CPU.Build.0 = Debug|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|x64.ActiveCfg = Debug|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|x64.Build.0 = Debug|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|Any CPU.ActiveCfg = Release|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|Any CPU.Build.0 = Release|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|x64.ActiveCfg = Release|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|x64.Build.0 = Release|x64 {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|x64.ActiveCfg = Debug|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|x64.Build.0 = Debug|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|Any CPU.ActiveCfg = Release|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|Any CPU.Build.0 = Release|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|x64.ActiveCfg = Release|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|x64.Build.0 = Release|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|x64.ActiveCfg = Debug|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|x64.Build.0 = Debug|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|Any CPU.ActiveCfg = Release|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|Any CPU.Build.0 = Release|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|x64.ActiveCfg = Release|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|x64.Build.0 = Release|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|x64.Build.0 = Debug|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|Any CPU.Build.0 = Release|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|x64.ActiveCfg = Release|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|x64.Build.0 = Release|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|x64.ActiveCfg = Debug|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|x64.Build.0 = Debug|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|Any CPU.Build.0 = Release|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|x64.ActiveCfg = Release|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|x64.Build.0 = Release|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|x64.ActiveCfg = Debug|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|x64.Build.0 = Debug|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|Any CPU.Build.0 = Release|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|x64.ActiveCfg = Release|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|x64.Build.0 = Release|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|x64.ActiveCfg = Debug|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|x64.Build.0 = Debug|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|Any CPU.ActiveCfg = Release|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|Any CPU.Build.0 = Release|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|x64.ActiveCfg = Release|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|x64.Build.0 = Release|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|x64.Build.0 = Debug|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Release|Any CPU.Build.0 = Release|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Release|x64.ActiveCfg = Release|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Release|x64.Build.0 = Release|Any CPU {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|Any CPU.ActiveCfg = Debug|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|Any CPU.Build.0 = Debug|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|x64.ActiveCfg = Debug|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|x64.Build.0 = Debug|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|Any CPU.ActiveCfg = Release|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|Any CPU.Build.0 = Release|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|x64.ActiveCfg = Release|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|x64.Build.0 = Release|x64 {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|x64.ActiveCfg = Debug|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|x64.Build.0 = Debug|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|Any CPU.Build.0 = Release|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|x64.ActiveCfg = Release|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|x64.Build.0 = Release|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|x64.ActiveCfg = Debug|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|x64.Build.0 = Debug|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|Any CPU.Build.0 = Release|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|x64.ActiveCfg = Release|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|x64.Build.0 = Release|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|x64.ActiveCfg = Debug|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|x64.Build.0 = Debug|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|Any CPU.ActiveCfg = Release|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|Any CPU.Build.0 = Release|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|x64.ActiveCfg = Release|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|x64.Build.0 = Release|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|x64.ActiveCfg = Debug|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|x64.Build.0 = Debug|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|Any CPU.ActiveCfg = Release|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|Any CPU.Build.0 = Release|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|x64.ActiveCfg = Release|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|x64.Build.0 = Release|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|x64.ActiveCfg = Debug|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|x64.Build.0 = Debug|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Release|Any CPU.ActiveCfg = Release|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Release|Any CPU.Build.0 = Release|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Release|x64.ActiveCfg = Release|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Release|x64.Build.0 = Release|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|x64.ActiveCfg = Debug|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|x64.Build.0 = Debug|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|Any CPU.Build.0 = Release|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|x64.ActiveCfg = Release|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|x64.Build.0 = Release|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|x64.ActiveCfg = Debug|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|x64.Build.0 = Debug|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|Any CPU.Build.0 = Release|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|x64.ActiveCfg = Release|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|x64.Build.0 = Release|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|x64.ActiveCfg = Debug|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|x64.Build.0 = Debug|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|Any CPU.ActiveCfg = Release|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|Any CPU.Build.0 = Release|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|x64.ActiveCfg = Release|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|x64.Build.0 = Release|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|x64.ActiveCfg = Debug|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|x64.Build.0 = Debug|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|Any CPU.Build.0 = Release|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|x64.ActiveCfg = Release|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|x64.Build.0 = Release|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|x64.ActiveCfg = Debug|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|x64.Build.0 = Debug|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|Any CPU.ActiveCfg = Release|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|Any CPU.Build.0 = Release|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|x64.ActiveCfg = Release|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|x64.Build.0 = Release|Any CPU {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|Any CPU.ActiveCfg = Debug|ARM {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|Any CPU.Build.0 = Debug|ARM + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|x64.ActiveCfg = Debug|x64 + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|x64.Build.0 = Debug|x64 {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|Any CPU.ActiveCfg = Release|ARM {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|Any CPU.Build.0 = Release|ARM + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|x64.ActiveCfg = Release|x64 + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|x64.Build.0 = Release|x64 {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|x64.ActiveCfg = Debug|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|x64.Build.0 = Debug|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|Any CPU.ActiveCfg = Release|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|Any CPU.Build.0 = Release|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|x64.ActiveCfg = Release|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|x64.Build.0 = Release|Any CPU {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|Any CPU.ActiveCfg = Debug|ARM {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|Any CPU.Build.0 = Debug|ARM + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|x64.ActiveCfg = Debug|Win32 + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|x64.Build.0 = Debug|Win32 {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|Any CPU.ActiveCfg = Release|ARM {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|Any CPU.Build.0 = Release|ARM + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|x64.ActiveCfg = Release|Win32 + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|x64.Build.0 = Release|Win32 {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|x64.Build.0 = Debug|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|Any CPU.Build.0 = Release|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|x64.ActiveCfg = Release|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|x64.Build.0 = Release|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|x64.ActiveCfg = Debug|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|x64.Build.0 = Debug|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|Any CPU.Build.0 = Release|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|x64.ActiveCfg = Release|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|x64.Build.0 = Release|Any CPU {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.ActiveCfg = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.Build.0 = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.Deploy.0 = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.ActiveCfg = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.Build.0 = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.Deploy.0 = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.ActiveCfg = Release|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.Build.0 = Release|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.Deploy.0 = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.ActiveCfg = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.Build.0 = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.Deploy.0 = Release|ARM {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|x64.ActiveCfg = Debug|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|x64.Build.0 = Debug|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|Any CPU.ActiveCfg = Release|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|Any CPU.Build.0 = Release|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|x64.ActiveCfg = Release|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|x64.Build.0 = Release|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|x64.ActiveCfg = Debug|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|x64.Build.0 = Debug|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|Any CPU.Build.0 = Release|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|x64.ActiveCfg = Release|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|x64.Build.0 = Release|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|x64.ActiveCfg = Debug|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|x64.Build.0 = Debug|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|Any CPU.ActiveCfg = Release|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|Any CPU.Build.0 = Release|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|x64.ActiveCfg = Release|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|x64.Build.0 = Release|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|x64.ActiveCfg = Debug|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|x64.Build.0 = Debug|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.Build.0 = Release|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|x64.ActiveCfg = Release|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|x64.Build.0 = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|x64.Build.0 = Debug|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.Build.0 = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.ActiveCfg = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs b/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs index ef3126779..8d54e1c8a 100644 --- a/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs +++ b/Sources/Runtime/Microsoft.Psi/Common/TypeResolutionHelper.cs @@ -21,8 +21,7 @@ public static class TypeResolutionHelper /// The requested type, or null if the type was not found. public static Type GetVerifiedType(string typeName) { - // var type = Type.GetType(typeName, AssemblyResolver, null); - var type = Type.GetType(typeName); + var type = Type.GetType(typeName, AssemblyResolver, null); if (type == null) { // Unable to resolve type. Attempt to resolve base class library types @@ -31,8 +30,7 @@ public static Type GetVerifiedType(string typeName) // mscorlib/System.Private.CoreLib or the currently executing assembly. typeName = RemoveCoreAssemblyName(typeName); - // type = Type.GetType(typeName, AssemblyResolver, null); - type = Type.GetType(typeName); + type = Type.GetType(typeName, AssemblyResolver, null); } return type; From 5385949d651f464f5d6d4948d66a16fbda144545 Mon Sep 17 00:00:00 2001 From: AuMilliat Date: Tue, 29 Aug 2023 17:31:09 +0200 Subject: [PATCH 03/21] Allowing Subpipline to stop. Unregestering from parentPipeline. --- .../Microsoft.Psi/Executive/Pipeline.cs | 49 ++++++++++++--- .../Microsoft.Psi/Executive/Subpipeline.cs | 12 ++++ .../Microsoft.Psi/Microsoft.Psi.csproj | 2 + .../Microsoft.Psi/Remoting/RemoteExporter.cs | 59 +++++++++++-------- TestConnection/Program.cs | 52 +++++++++++++--- 5 files changed, 133 insertions(+), 41 deletions(-) diff --git a/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs b/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs index 73d1c0513..eb855a492 100644 --- a/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs +++ b/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs @@ -4,6 +4,7 @@ namespace Microsoft.Psi { using System; + using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -888,6 +889,33 @@ internal virtual void Stop(DateTime finalOriginatingTime, bool abandonPendingWor this.completed.Set(); } + internal bool RemoveSubpipline(Subpipeline subpipeline) + { + PipelineElement node = this.components.FirstOrDefault(c => c.StateObject == subpipeline); + if (node == null) + { + return false; + } + + if (!subpipeline.IsCompleted) + { + throw new InvalidOperationException($"Subpipeline is still running, it can't be removed from parent pipeline."); + } + + List list = subpipeline.Components.ToList(); + list.Add(node); + SynchronizationLock locker = new SynchronizationLock(this, true); + this.scheduler.Freeze(locker); + this.components = new ConcurrentQueue(this.components.Where(x => !list.Contains(x))); + foreach (PipelineElement child in list) + { + this.DiagnosticsCollector?.PipelineElementDisposed(this, child); + } + + locker.Release(); + return true; + } + /// /// Run pipeline (asynchronously). /// @@ -964,6 +992,18 @@ protected virtual IDisposable RunAsync(ReplayDescriptor descriptor, Clock clock, return this; } + /// + /// Dispose components within pipeline and recursively within subpipelines. + /// + protected void DisposeComponents() + { + foreach (var component in this.components) + { + this.DiagnosticsCollector?.PipelineElementDisposed(this, component); + component.Dispose(); + } + } + /// /// Gather all nodes within this pipeline and recursively within subpipelines. /// @@ -1389,15 +1429,6 @@ private void NotifyPipelineFinalizing(DateTime finalOriginatingTime) } } - private void DisposeComponents() - { - foreach (var component in this.components) - { - this.DiagnosticsCollector?.PipelineElementDisposed(this, component); - component.Dispose(); - } - } - private void ThrowIfError() { if (this.PipelineExceptionNotHandled != null) diff --git a/Sources/Runtime/Microsoft.Psi/Executive/Subpipeline.cs b/Sources/Runtime/Microsoft.Psi/Executive/Subpipeline.cs index aaa5c0a92..c78c863d7 100644 --- a/Sources/Runtime/Microsoft.Psi/Executive/Subpipeline.cs +++ b/Sources/Runtime/Microsoft.Psi/Executive/Subpipeline.cs @@ -4,6 +4,7 @@ namespace Microsoft.Psi { using System; + using System.Collections.Concurrent; using System.Linq; using Microsoft.Psi.Components; using Microsoft.Psi.Executive; @@ -102,6 +103,17 @@ public void Stop(DateTime finalOriginatingTime, Action notifyCompleted) } } + /// + /// Remove subpipline from parent. + /// + public override void Dispose() + { + this.Stop(this.parentPipeline.GetCurrentTime(), true); + this.DisposeComponents(); + this.parentPipeline.RemoveSubpipline(this); + this.SchedulerContext.Dispose(); + } + /// public override void ProposeReplayTime(TimeInterval originatingTimeInterval) { diff --git a/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj b/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj index f6627c071..4fc078b71 100644 --- a/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj +++ b/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj @@ -5,6 +5,8 @@ true Microsoft.Psi.Runtime Provides the core APIs and components for Platform for Situated Intelligence. + 0.18.72.1 + $(AssemblyVersion)-modifiedPipeTest3 diff --git a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs index 8e3ec132f..8742d5a7d 100644 --- a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs +++ b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteExporter.cs @@ -8,6 +8,7 @@ namespace Microsoft.Psi.Remoting using System.Collections.Generic; using System.Diagnostics; using System.IO; + using System.Linq.Expressions; using System.Net; using System.Net.Sockets; using System.Numerics; @@ -261,6 +262,7 @@ private sealed class Connection : IDisposable private readonly string storeName; private readonly string storePath; + private bool threadRunning; private TcpClient client; private Stream stream; @@ -337,6 +339,7 @@ public void Connect() public void JoinBackgroundThread(ITransportClient client) { + this.threadRunning = true; this.connectionThread = new Thread(() => this.JoinBackground(client)); this.connectionThread.Start(); } @@ -354,48 +357,56 @@ public void JoinBackground(ITransportClient client) this.storeReader.Seek(this.interval); - while (true) + while (this.threadRunning) { - if (this.storeReader.MoveNext(out Envelope envelope)) + try { - var length = this.storeReader.Read(ref buffer); - this.exporter.Throttle.Reset(); - try + if (this.storeReader.MoveNext(out Envelope envelope)) { - client.WriteMessage(envelope, buffer); - if (lastTime > DateTime.MinValue /* at least second message */) + var length = this.storeReader.Read(ref buffer); + this.exporter.Throttle.Reset(); + try { - if (this.maxBytesPerSecond < long.MaxValue) + client.WriteMessage(envelope, buffer); + if (lastTime > DateTime.MinValue /* at least second message */) { - // throttle to arbitrary max BPS - var elapsed = (envelope.OriginatingTime - lastTime).TotalSeconds; - var bytesPerSec = (envelopeSize + length) / elapsed; - double smoothingFactor = 1.0 / (this.bytesPerSecondSmoothingWindowSeconds / elapsed); - avgBytesPerSec = (bytesPerSec * smoothingFactor) + (avgBytesPerSec * (1.0 - smoothingFactor)); - if (bytesPerSec > this.maxBytesPerSecond) + if (this.maxBytesPerSecond < long.MaxValue) { - var wait = (int)(((avgBytesPerSec / this.maxBytesPerSecond) - elapsed) * 1000.0); - if (wait > 0) + // throttle to arbitrary max BPS + var elapsed = (envelope.OriginatingTime - lastTime).TotalSeconds; + var bytesPerSec = (envelopeSize + length) / elapsed; + double smoothingFactor = 1.0 / (this.bytesPerSecondSmoothingWindowSeconds / elapsed); + avgBytesPerSec = (bytesPerSec * smoothingFactor) + (avgBytesPerSec * (1.0 - smoothingFactor)); + if (bytesPerSec > this.maxBytesPerSecond) { - Thread.Sleep(wait); + var wait = (int)(((avgBytesPerSec / this.maxBytesPerSecond) - elapsed) * 1000.0); + if (wait > 0) + { + Thread.Sleep(wait); + } } } } - } - lastTime = envelope.OriginatingTime; - } - finally - { - // writers continue upon failure - meanwhile, remote client may reconnect and resume based on replay interval - this.exporter.Throttle.Set(); + lastTime = envelope.OriginatingTime; + } + finally + { + // writers continue upon failure - meanwhile, remote client may reconnect and resume based on replay interval + this.exporter.Throttle.Set(); + } } } + catch (Exception) + { + this.threadRunning = false; + } } } public void Dispose() { + this.threadRunning = false; this.storeReader.Dispose(); this.storeReader = null; this.client.Dispose(); diff --git a/TestConnection/Program.cs b/TestConnection/Program.cs index 65fe44b72..948f46d11 100644 --- a/TestConnection/Program.cs +++ b/TestConnection/Program.cs @@ -8,18 +8,54 @@ internal class Program static void Main(string[] args) { // Create the \psi pipeline - Pipeline pipeline = Pipeline.Create("TestConnection"); - - RemoteExporter exporter = new RemoteExporter(pipeline, 11411, TransportKind.Tcp); - // Create a timer component that produces a message every second + Pipeline pipeline = Pipeline.Create("Subpipline Removal"); var timer = Timers.Timer(pipeline, TimeSpan.FromSeconds(1)); - - // For each message created by the timer - exporter.Exporter.Write(timer.Out, "Test"); - + timer.Out.Do(t => + { + Console.WriteLine($"\tPipeline timer."); + }); // Start the pipeline running pipeline.RunAsync(); + Console.WriteLine("Pipeline Run Asynch."); + Subpipeline sub1 = new Subpipeline(pipeline); + var subtimer1 = Timers.Timer(sub1, TimeSpan.FromSeconds(1)); + subtimer1.Out.Do(t => + { + Console.WriteLine($"\tSubpipeline 1 timer."); + }); + RemoteExporter exporter1 = new RemoteExporter(sub1, 11511, TransportKind.Tcp); + exporter1.Exporter.Write(subtimer1.Out, "SubExporter1"); + sub1.RunAsync(); + Console.WriteLine("Subpipeline 1 Run Asynch."); + Thread.Sleep(3000); + Subpipeline sub2 = new Subpipeline(pipeline); + var subtimer2 = Timers.Timer(sub2, TimeSpan.FromSeconds(1)); + subtimer2.Out.Do(t => + { + Console.WriteLine($"\tSubpipeline 2 timer."); + }); + RemoteExporter exporter2 = new RemoteExporter(sub2, 11512, TransportKind.Tcp); + exporter2.Exporter.Write(subtimer2.Out, "SubExporter2"); + sub2.RunAsync(); + Console.WriteLine("Subpipeline 2 Run Asynch."); + Thread.Sleep(5000); + Console.WriteLine("Dispose Subpipeline 1."); + sub1.Dispose(); + Thread.Sleep(5000); + Console.WriteLine("Dispose Subpipeline 2."); + sub2.Dispose(); + Thread.Sleep(5000); + Subpipeline sub3 = new Subpipeline(pipeline); + var subtimer3 = Timers.Timer(sub3, TimeSpan.FromSeconds(1)); + subtimer3.Out.Do(t => + { + Console.WriteLine($"\tSubpipeline 3 timer."); + }); + RemoteExporter exporter3 = new RemoteExporter(sub3, 11513, TransportKind.Tcp); + exporter3.Exporter.Write(subtimer3.Out, "SubExporter3"); + sub3.RunAsync(); + Console.WriteLine("Subpipeline 3 Run Asynch."); // Wainting for an out key Console.WriteLine("Press any key to stop the application."); Console.ReadLine(); From 2bd8c07f85fc826e942f850dc17c736566aa0d36 Mon Sep 17 00:00:00 2001 From: AuMilliat Date: Wed, 6 Dec 2023 08:33:43 +0100 Subject: [PATCH 04/21] packages update --- .../Microsoft.Psi.Audio.Windows.csproj | 4 ++-- .../Microsoft.Psi.Audio.csproj | 4 ++-- .../Microsoft.Psi.Calibration.csproj | 6 ++--- .../Test.Psi.Common/Test.Psi.Common.csproj | 6 ++--- .../Microsoft.Psi.Data.csproj | 6 ++--- .../Microsoft.Psi.Imaging.Windows.csproj | 4 ++-- .../Microsoft.Psi.Imaging.csproj | 6 ++--- .../HoloLens2ResearchMode.vcxproj | 8 +++---- .../HoloLens2ResearchMode/packages.config | 2 +- .../packages.config | 3 ++- .../Microsoft.Psi/Executive/Pipeline.cs | 23 +++++++++++++++++++ .../Microsoft.Psi/Microsoft.Psi.csproj | 8 +++---- .../Microsoft.Psi.Speech.csproj | 4 ++-- .../Microsoft.Psi.PsiStudio.csproj | 4 ++-- .../Test.Psi.PsiStudio.csproj | 4 ++-- .../Microsoft.Msagl.WpfGraphControl.csproj | 6 ++--- ...si.LiveCharts.Visualization.Windows.csproj | 4 ++-- ...Microsoft.Psi.Visualization.Windows.csproj | 14 +++++------ .../Test.Psi.Visualization.csproj | 8 +++---- 19 files changed, 74 insertions(+), 50 deletions(-) diff --git a/Sources/Audio/Microsoft.Psi.Audio.Windows/Microsoft.Psi.Audio.Windows.csproj b/Sources/Audio/Microsoft.Psi.Audio.Windows/Microsoft.Psi.Audio.Windows.csproj index c0c73b894..0f4dd95bc 100644 --- a/Sources/Audio/Microsoft.Psi.Audio.Windows/Microsoft.Psi.Audio.Windows.csproj +++ b/Sources/Audio/Microsoft.Psi.Audio.Windows/Microsoft.Psi.Audio.Windows.csproj @@ -30,10 +30,10 @@ - + all runtime; build; native; contentfiles; analyzers - + \ No newline at end of file diff --git a/Sources/Audio/Microsoft.Psi.Audio/Microsoft.Psi.Audio.csproj b/Sources/Audio/Microsoft.Psi.Audio/Microsoft.Psi.Audio.csproj index 2ff943680..e4a072ad1 100644 --- a/Sources/Audio/Microsoft.Psi.Audio/Microsoft.Psi.Audio.csproj +++ b/Sources/Audio/Microsoft.Psi.Audio/Microsoft.Psi.Audio.csproj @@ -36,11 +36,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/Sources/Calibration/Microsoft.Psi.Calibration/Microsoft.Psi.Calibration.csproj b/Sources/Calibration/Microsoft.Psi.Calibration/Microsoft.Psi.Calibration.csproj index 6137dab33..1850480d1 100644 --- a/Sources/Calibration/Microsoft.Psi.Calibration/Microsoft.Psi.Calibration.csproj +++ b/Sources/Calibration/Microsoft.Psi.Calibration/Microsoft.Psi.Calibration.csproj @@ -25,12 +25,12 @@ - + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/Sources/Common/Test.Psi.Common/Test.Psi.Common.csproj b/Sources/Common/Test.Psi.Common/Test.Psi.Common.csproj index e33166bcf..c3d73966d 100644 --- a/Sources/Common/Test.Psi.Common/Test.Psi.Common.csproj +++ b/Sources/Common/Test.Psi.Common/Test.Psi.Common.csproj @@ -29,12 +29,12 @@ - + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/Sources/Data/Microsoft.Psi.Data/Microsoft.Psi.Data.csproj b/Sources/Data/Microsoft.Psi.Data/Microsoft.Psi.Data.csproj index 680e691cf..9c61595bf 100644 --- a/Sources/Data/Microsoft.Psi.Data/Microsoft.Psi.Data.csproj +++ b/Sources/Data/Microsoft.Psi.Data/Microsoft.Psi.Data.csproj @@ -29,12 +29,12 @@ - + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/Sources/Imaging/Microsoft.Psi.Imaging.Windows/Microsoft.Psi.Imaging.Windows.csproj b/Sources/Imaging/Microsoft.Psi.Imaging.Windows/Microsoft.Psi.Imaging.Windows.csproj index 43258eb31..4c12e4fb5 100644 --- a/Sources/Imaging/Microsoft.Psi.Imaging.Windows/Microsoft.Psi.Imaging.Windows.csproj +++ b/Sources/Imaging/Microsoft.Psi.Imaging.Windows/Microsoft.Psi.Imaging.Windows.csproj @@ -26,11 +26,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/Sources/Imaging/Microsoft.Psi.Imaging/Microsoft.Psi.Imaging.csproj b/Sources/Imaging/Microsoft.Psi.Imaging/Microsoft.Psi.Imaging.csproj index 03d8e1111..f8d13b91e 100644 --- a/Sources/Imaging/Microsoft.Psi.Imaging/Microsoft.Psi.Imaging.csproj +++ b/Sources/Imaging/Microsoft.Psi.Imaging/Microsoft.Psi.Imaging.csproj @@ -31,13 +31,13 @@ - + all runtime; build; native; contentfiles; analyzers - + - + diff --git a/Sources/MixedReality/HoloLens2ResearchMode/HoloLens2ResearchMode.vcxproj b/Sources/MixedReality/HoloLens2ResearchMode/HoloLens2ResearchMode.vcxproj index 0a92bd96e..6ef6be832 100644 --- a/Sources/MixedReality/HoloLens2ResearchMode/HoloLens2ResearchMode.vcxproj +++ b/Sources/MixedReality/HoloLens2ResearchMode/HoloLens2ResearchMode.vcxproj @@ -1,6 +1,6 @@ - + true true @@ -161,13 +161,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + \ No newline at end of file diff --git a/Sources/MixedReality/HoloLens2ResearchMode/packages.config b/Sources/MixedReality/HoloLens2ResearchMode/packages.config index 70bf1926d..1b8cfbd96 100644 --- a/Sources/MixedReality/HoloLens2ResearchMode/packages.config +++ b/Sources/MixedReality/HoloLens2ResearchMode/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/packages.config b/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/packages.config index 0f77b525b..750d2262e 100644 --- a/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/packages.config +++ b/Sources/RealSense/Microsoft.Psi.RealSense_Interop.Windows.x64/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs b/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs index eb855a492..423b84393 100644 --- a/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs +++ b/Sources/Runtime/Microsoft.Psi/Executive/Pipeline.cs @@ -307,6 +307,29 @@ public static Pipeline Create( return new Pipeline(name, deliveryPolicy, threadCount, allowSchedulingOnExternalThreads, enableDiagnostics, diagnosticsConfiguration); } + /// + /// Create new pipeline setting time offset and diagnostics collector from given pipeline. + /// + /// Pipeline to retrieve time offset and diagonistic configuration. + /// Pipeline name. + /// Number of threads. + /// Whether to allow scheduling on external threads. + /// Indicates whether to enable collecting and publishing diagnostics information on the Pipeline.Diagnostics stream. + /// Created pipeline. + public static Pipeline CreateSynchedPipeline( + Pipeline pipeline, + string name = null, + int threadCount = 0, + bool allowSchedulingOnExternalThreads = false, + bool enableDiagnostics = false) + { + Pipeline newPipeline = new Pipeline(name == null ? $"Synched|{pipeline.Name}" : name, pipeline.defaultDeliveryPolicy, threadCount, allowSchedulingOnExternalThreads); + newPipeline.VirtualTimeOffset = pipeline.VirtualTimeOffset; + newPipeline.DiagnosticsCollector = enableDiagnostics ? pipeline.DiagnosticsCollector : null; + newPipeline.DiagnosticsConfiguration = pipeline.DiagnosticsConfiguration; + return newPipeline; + } + /// /// Propose replay time. /// diff --git a/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj b/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj index 4fc078b71..6fae60e9f 100644 --- a/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj +++ b/Sources/Runtime/Microsoft.Psi/Microsoft.Psi.csproj @@ -6,7 +6,7 @@ Microsoft.Psi.Runtime Provides the core APIs and components for Platform for Situated Intelligence. 0.18.72.1 - $(AssemblyVersion)-modifiedPipeTest3 + $(AssemblyVersion)-modifiedPipeTest5 @@ -52,14 +52,14 @@ - + all runtime; build; native; contentfiles; analyzers - + - 1.7.0 + 8.0.0 diff --git a/Sources/Speech/Microsoft.Psi.Speech/Microsoft.Psi.Speech.csproj b/Sources/Speech/Microsoft.Psi.Speech/Microsoft.Psi.Speech.csproj index 8b96f796c..5a2d9cf26 100644 --- a/Sources/Speech/Microsoft.Psi.Speech/Microsoft.Psi.Speech.csproj +++ b/Sources/Speech/Microsoft.Psi.Speech/Microsoft.Psi.Speech.csproj @@ -33,11 +33,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/Sources/Tools/PsiStudio/Microsoft.Psi.PsiStudio/Microsoft.Psi.PsiStudio.csproj b/Sources/Tools/PsiStudio/Microsoft.Psi.PsiStudio/Microsoft.Psi.PsiStudio.csproj index 82e5aa62a..0c4ed2c3a 100644 --- a/Sources/Tools/PsiStudio/Microsoft.Psi.PsiStudio/Microsoft.Psi.PsiStudio.csproj +++ b/Sources/Tools/PsiStudio/Microsoft.Psi.PsiStudio/Microsoft.Psi.PsiStudio.csproj @@ -57,11 +57,11 @@ - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Sources/Tools/PsiStudio/Test.Psi.PsiStudio/Test.Psi.PsiStudio.csproj b/Sources/Tools/PsiStudio/Test.Psi.PsiStudio/Test.Psi.PsiStudio.csproj index ddb860122..17740c65e 100644 --- a/Sources/Tools/PsiStudio/Test.Psi.PsiStudio/Test.Psi.PsiStudio.csproj +++ b/Sources/Tools/PsiStudio/Test.Psi.PsiStudio/Test.Psi.PsiStudio.csproj @@ -26,11 +26,11 @@ - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Sources/Visualization/Microsoft.Msagl.WpfGraphControl/Microsoft.Msagl.WpfGraphControl.csproj b/Sources/Visualization/Microsoft.Msagl.WpfGraphControl/Microsoft.Msagl.WpfGraphControl.csproj index 3b5f61845..98cd2689f 100644 --- a/Sources/Visualization/Microsoft.Msagl.WpfGraphControl/Microsoft.Msagl.WpfGraphControl.csproj +++ b/Sources/Visualization/Microsoft.Msagl.WpfGraphControl/Microsoft.Msagl.WpfGraphControl.csproj @@ -21,13 +21,13 @@ - + all runtime; build; native; contentfiles; analyzers - + - 1.1.3 + 1.1.6 diff --git a/Sources/Visualization/Microsoft.Psi.LiveCharts.Visualization.Windows/Microsoft.Psi.LiveCharts.Visualization.Windows.csproj b/Sources/Visualization/Microsoft.Psi.LiveCharts.Visualization.Windows/Microsoft.Psi.LiveCharts.Visualization.Windows.csproj index 18ec1331d..33df3b4fe 100644 --- a/Sources/Visualization/Microsoft.Psi.LiveCharts.Visualization.Windows/Microsoft.Psi.LiveCharts.Visualization.Windows.csproj +++ b/Sources/Visualization/Microsoft.Psi.LiveCharts.Visualization.Windows/Microsoft.Psi.LiveCharts.Visualization.Windows.csproj @@ -30,11 +30,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/Sources/Visualization/Microsoft.Psi.Visualization.Windows/Microsoft.Psi.Visualization.Windows.csproj b/Sources/Visualization/Microsoft.Psi.Visualization.Windows/Microsoft.Psi.Visualization.Windows.csproj index f302bc3cd..eb7bf4752 100644 --- a/Sources/Visualization/Microsoft.Psi.Visualization.Windows/Microsoft.Psi.Visualization.Windows.csproj +++ b/Sources/Visualization/Microsoft.Psi.Visualization.Windows/Microsoft.Psi.Visualization.Windows.csproj @@ -248,17 +248,17 @@ - - - + + + all runtime; build; native; contentfiles; analyzers - - - - + + + + diff --git a/Sources/Visualization/Test.Psi.Visualization/Test.Psi.Visualization.csproj b/Sources/Visualization/Test.Psi.Visualization/Test.Psi.Visualization.csproj index dd0a7de75..194e935dd 100644 --- a/Sources/Visualization/Test.Psi.Visualization/Test.Psi.Visualization.csproj +++ b/Sources/Visualization/Test.Psi.Visualization/Test.Psi.Visualization.csproj @@ -74,18 +74,18 @@ - 2.9.8 + 3.3.2 runtime; build; native; contentfiles; analyzers all - 2.1.1 + 3.1.1 - 2.1.1 + 3.1.1 - 1.1.118 + 1.2.0-beta.507 runtime; build; native; contentfiles; analyzers all From 446a0fa7f3d1f4b43b2d0f763e0e879ac7f48ca5 Mon Sep 17 00:00:00 2001 From: AuMilliat Date: Tue, 13 Feb 2024 09:56:21 +0100 Subject: [PATCH 05/21] \psi + unity in quest progress --- .../Rendezvous/Operators.cs | 12 ++++++++++ .../Runtime/Microsoft.Psi/Data/PsiImporter.cs | 17 +++++++++++++- .../Runtime/Microsoft.Psi/Data/PsiStore.cs | 23 +++++++++++++++++++ .../Data/PsiStoreStreamReader.cs | 12 ++++++++++ .../Persistence/InfiniteFileReader.cs | 9 +++++--- .../Persistence/InfiniteFileWriter.cs | 23 +++++++++++-------- .../Microsoft.Psi/Remoting/RemoteImporter.cs | 15 ++++++++++++ 7 files changed, 97 insertions(+), 14 deletions(-) diff --git a/Sources/Runtime/Microsoft.Psi.Interop/Rendezvous/Operators.cs b/Sources/Runtime/Microsoft.Psi.Interop/Rendezvous/Operators.cs index 7a1608399..7d73d900a 100644 --- a/Sources/Runtime/Microsoft.Psi.Interop/Rendezvous/Operators.cs +++ b/Sources/Runtime/Microsoft.Psi.Interop/Rendezvous/Operators.cs @@ -7,6 +7,7 @@ namespace Microsoft.Psi.Interop.Rendezvous using Microsoft.Psi.Interop.Serialization; using Microsoft.Psi.Interop.Transport; using Microsoft.Psi.Remoting; + using Microsoft.Psi.Serialization; /// /// Rendezvous related operators. @@ -101,6 +102,17 @@ public static Rendezvous.Endpoint ToRendezvousEndpoint(this RemoteExporter expor return endpoint; } + /// + /// Create a from a . + /// + /// from which to create . + /// The pipeline to add the component to. + /// Path for PsiStore. + /// Custom known serializers. + /// . + public static RemoteImporter ToRemoteImporter(this Rendezvous.RemoteExporterEndpoint endpoint, Pipeline pipeline, string storePath, KnownSerializers knownSerializers) + => new (pipeline, storePath, endpoint.Host, endpoint.Port, knownSerializers); + /// /// Create a from a . /// diff --git a/Sources/Runtime/Microsoft.Psi/Data/PsiImporter.cs b/Sources/Runtime/Microsoft.Psi/Data/PsiImporter.cs index 33677089c..bd01d996f 100644 --- a/Sources/Runtime/Microsoft.Psi/Data/PsiImporter.cs +++ b/Sources/Runtime/Microsoft.Psi/Data/PsiImporter.cs @@ -4,7 +4,8 @@ namespace Microsoft.Psi.Data { using Microsoft.Psi; - + using Microsoft.Psi.Serialization; +#pragma warning disable CS0419 // Ambiguous reference in cref attribute /// /// Component that reads messages from a \psi store and publishes them on streams. /// @@ -14,6 +15,7 @@ namespace Microsoft.Psi.Data /// method. The store metadata is available immediately after open /// (before the pipeline is running) via the property. /// +#pragma warning restore CS0419 // Ambiguous reference in cref attribute public sealed class PsiImporter : Importer { /// @@ -27,5 +29,18 @@ public PsiImporter(Pipeline pipeline, string name, string path, bool usePerStrea : base(pipeline, new PsiStoreStreamReader(name, path), usePerStreamReaders) { } + + /// + /// Initializes a new instance of the class. + /// + /// The pipeline to add the component to. + /// Custom known serializers. + /// The name of the application that generated the persisted files, or the root name of the files. + /// The directory in which the main persisted file resides or will reside, or null to open a volatile data store. + /// Flag indicating whether to use per-stream readers. + public PsiImporter(Pipeline pipeline, KnownSerializers serializers, string name, string path, bool usePerStreamReaders) + : base(pipeline, new PsiStoreStreamReader(name, path, serializers), usePerStreamReaders) + { + } } } diff --git a/Sources/Runtime/Microsoft.Psi/Data/PsiStore.cs b/Sources/Runtime/Microsoft.Psi/Data/PsiStore.cs index c91e30985..8d7979206 100644 --- a/Sources/Runtime/Microsoft.Psi/Data/PsiStore.cs +++ b/Sources/Runtime/Microsoft.Psi/Data/PsiStore.cs @@ -90,6 +90,29 @@ public static PsiImporter Open(Pipeline pipeline, string name, string rootPath, return new PsiImporter(pipeline, name, rootPath, usePerStreamReaders); } + /// + /// Opens a \psi store for read and returns a instance + /// which can be used to inspect the store and open the streams. + /// The store metadata is available immediately after this call (before the pipeline is running) via the property. + /// + /// The pipeline to add the component to. + /// Custom known serializers. + /// The name of the store to open (the same as the catalog file name). + /// + /// The path to the store. + /// This can be one of: + /// - a full path to a directory containing the store + /// - a root path containing one or more versions of the store, each in its own subdirectory, + /// in which case the latest store is opened. + /// - a null string, in which case an in-memory store is opened. + /// + /// Optional flag indicating whether to use per-stream readers (see remarks). + /// A instance that can be used to open streams and read messages. + public static PsiImporter Open(Pipeline pipeline, KnownSerializers serializers, string name, string rootPath, bool usePerStreamReaders = true) + { + return new PsiImporter(pipeline, serializers, name, rootPath, usePerStreamReaders); + } + /// /// Writes the specified stream to a multi-stream \psi store. /// diff --git a/Sources/Runtime/Microsoft.Psi/Data/PsiStoreStreamReader.cs b/Sources/Runtime/Microsoft.Psi/Data/PsiStoreStreamReader.cs index 882c909fb..27558a538 100644 --- a/Sources/Runtime/Microsoft.Psi/Data/PsiStoreStreamReader.cs +++ b/Sources/Runtime/Microsoft.Psi/Data/PsiStoreStreamReader.cs @@ -35,6 +35,18 @@ public PsiStoreStreamReader(string name, string path) this.PsiStoreReader = new PsiStoreReader(name, path, this.LoadMetadata); } + /// + /// Initializes a new instance of the class. + /// + /// The name of the application that generated the persisted files, or the root name of the files. + /// The directory in which the main persisted file resides or will reside, or null to create a volatile data store. + /// Custom known serializers. + public PsiStoreStreamReader(string name, string path, KnownSerializers serializers) + { + this.PsiStoreReader = new PsiStoreReader(name, path, this.LoadMetadata); + this.context = new SerializationContext(serializers); + } + /// /// Initializes a new instance of the class. /// diff --git a/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileReader.cs b/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileReader.cs index c8d5ee7da..a2a58f6bc 100644 --- a/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileReader.cs +++ b/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileReader.cs @@ -28,9 +28,12 @@ public InfiniteFileReader(string path, string fileName, int fileId = 0) this.path = path; this.fileName = fileName; this.fileId = fileId; - Mutex pulse; - Mutex.TryOpenExisting(InfiniteFileWriter.PulseEventName(path, fileName), out pulse); - this.writePulse = pulse ?? new Mutex(false); + + // Mutex pulse; + // Mutex.TryOpenExisting(InfiniteFileWriter.PulseEventName(path, fileName), out pulse); + // this.writePulse = pulse ?? new Mutex(false); + InfiniteFileWriter.PulseEventName(path, fileName); + this.writePulse = new Mutex(false); } public InfiniteFileReader(string name, int fileId = 0) diff --git a/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileWriter.cs b/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileWriter.cs index 3d6d35668..0c967c67c 100644 --- a/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileWriter.cs +++ b/Sources/Runtime/Microsoft.Psi/Persistence/InfiniteFileWriter.cs @@ -52,7 +52,8 @@ public InfiniteFileWriter(string path, string fileName, int extentSize) { try { - this.globalWritePulse = new Mutex(true, PulseEventName(path, fileName)); + // this.globalWritePulse = new Mutex(true, PulseEventName(path, fileName)); + this.globalWritePulse = new Mutex(true); } catch (UnauthorizedAccessException) { @@ -64,9 +65,9 @@ public InfiniteFileWriter(string path, string fileName, int extentSize) { while (!this.disposed) { - this.localWritePulse?.WaitOne(); - this.globalWritePulse?.ReleaseMutex(); - this.globalWritePulse?.WaitOne(); + this.localWritePulse.WaitOne(); + this.globalWritePulse.ReleaseMutex(); + this.globalWritePulse.WaitOne(); } } catch (ObjectDisposedException) @@ -109,7 +110,7 @@ public void Dispose() this.localWritePulse.Set(); this.localWritePulse.Dispose(); this.localWritePulse = null; - this.globalWritePulse?.Dispose(); + this.globalWritePulse.Dispose(); this.globalWritePulse = null; // may have already been disposed in CloseCurrent @@ -218,11 +219,11 @@ internal static string PulseEventName(string path, string fileName) private static string MakeHandleName(string format, string path, string fileName) { - var name = string.Format(format, path?.ToLower().GetDeterministicHashCode(), fileName.ToLower()); + var name = string.Format(format, path.ToLower().GetDeterministicHashCode(), fileName.ToLower()); if (name.Length > 260) { // exceeded the name length limit - return string.Format(format, path?.ToLower().GetDeterministicHashCode(), fileName.ToLower().GetDeterministicHashCode()); + return string.Format(format, path.ToLower().GetDeterministicHashCode(), fileName.ToLower().GetDeterministicHashCode()); } return name; @@ -239,14 +240,16 @@ private void CreateNewExtent() if (!this.IsVolatile) { this.extentName = System.IO.Path.Combine(this.Path, this.extentName); - var file = File.Open(this.extentName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); + + // var file = File.Open(this.extentName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); try { - newMMF = MemoryMappedFile.CreateFromFile(file, null, this.extentSize, MemoryMappedFileAccess.ReadWrite, HandleInheritability.Inheritable, false); + // newMMF = MemoryMappedFile.CreateFromFile(file, null, this.extentSize, MemoryMappedFileAccess.ReadWrite, HandleInheritability.Inheritable, false); + newMMF = MemoryMappedFile.CreateFromFile(this.extentName, FileMode.Create, null, this.extentSize); } catch (IOException) { - file.Dispose(); + // file.Dispose(); throw; } } diff --git a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteImporter.cs b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteImporter.cs index b452d693f..6d406a31e 100644 --- a/Sources/Runtime/Microsoft.Psi/Remoting/RemoteImporter.cs +++ b/Sources/Runtime/Microsoft.Psi/Remoting/RemoteImporter.cs @@ -72,6 +72,21 @@ public RemoteImporter(Pipeline pipeline, string host, int port = RemoteExporter. { } + /// + /// Initializes a new instance of the class. + /// + /// The pipeline to add the component to. + /// Path for PsiStore. + /// Remote host name. + /// TCP port on which to connect (default 11411). + /// Custom known serializers. + /// Whether to allow sequence ID restarts upon connection loss/reacquire. + /// In this case the start is a special behavior that is `DateTime.UtcNow` _at the sending `RemoteExporter`_. + public RemoteImporter(Pipeline pipeline, string storePath, string host, int port = RemoteExporter.DefaultPort, KnownSerializers serializers = null, bool allowSequenceRestart = true) + : this(name => PsiStore.Open(pipeline, serializers, name, storePath), new TimeInterval(DateTime.MinValue, DateTime.MaxValue), true, host, port, $"RemoteImporter_{Guid.NewGuid()}", storePath, allowSequenceRestart) + { + } + /// /// Initializes a new instance of the class. /// From 1c596c2782d8186804dea82d499396734c09ea0e Mon Sep 17 00:00:00 2001 From: AuMilliat Date: Mon, 4 Mar 2024 16:35:31 +0100 Subject: [PATCH 06/21] Unity work for Quest --- Psi.sln | 288 +++++++++++++++++- .../Microsoft.Psi/Common/PsiStreamMetadata.cs | 2 +- .../Runtime/Microsoft.Psi/Data/Importer.cs | 2 +- .../Serialization/KnownSerializers.cs | 35 ++- .../Serialization/SerializationContext.cs | 4 +- .../Microsoft.Psi/Serialization/Serializer.cs | 2 +- .../Serialization/StructHandler.cs | 14 +- .../Microsoft.Psi/Streams/Receiver{T}.cs | 2 +- 8 files changed, 324 insertions(+), 25 deletions(-) diff --git a/Psi.sln b/Psi.sln index 97e27cad4..8f804972d 100644 --- a/Psi.sln +++ b/Psi.sln @@ -53,7 +53,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Speech.Windows", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Audio", "Sources\Audio\Test.Psi.Audio\Test.Psi.Audio.csproj", "{7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Psi.Imaging.Windows", "Sources\Imaging\Test.Psi.Imaging.Windows\Test.Psi.Imaging.Windows.csproj", "{191DF615-3D8F-45A3-B763-DD4A604A712A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Imaging.Windows", "Sources\Imaging\Test.Psi.Imaging.Windows\Test.Psi.Imaging.Windows.csproj", "{191DF615-3D8F-45A3-B763-DD4A604A712A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Toolkits", "Toolkits", "{B592009C-5137-4D7F-8B50-C7D8500230D6}" EndProject @@ -229,7 +229,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HoloLensCaptureInterop", "S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Psi.Calibration", "Sources\Calibration\Test.Psi.Calibration\Test.Psi.Calibration.csproj", "{41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConnection", "TestConnection\TestConnection.csproj", "{E4D7E21F-8469-456F-828D-DE1D2590E4EA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestConnection", "TestConnection\TestConnection.csproj", "{E4D7E21F-8469-456F-828D-DE1D2590E4EA}" ProjectSection(ProjectDependencies) = postProject {04147400-0AB0-4F07-9975-D4B7E58150DB} = {04147400-0AB0-4F07-9975-D4B7E58150DB} EndProjectSection @@ -237,291 +237,575 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|x64.ActiveCfg = Debug|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Debug|x64.Build.0 = Debug|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|Any CPU.ActiveCfg = Release|Any CPU {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|Any CPU.Build.0 = Release|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|x64.ActiveCfg = Release|Any CPU + {04147400-0AB0-4F07-9975-D4B7E58150DB}.Release|x64.Build.0 = Release|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|x64.ActiveCfg = Debug|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Debug|x64.Build.0 = Debug|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|Any CPU.Build.0 = Release|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|x64.ActiveCfg = Release|Any CPU + {2CC39BCB-7798-474C-AC97-1C5F664101E2}.Release|x64.Build.0 = Release|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|Any CPU.Build.0 = Debug|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|x64.ActiveCfg = Debug|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Debug|x64.Build.0 = Debug|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|Any CPU.ActiveCfg = Release|Any CPU {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|Any CPU.Build.0 = Release|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|x64.ActiveCfg = Release|Any CPU + {855FD8BE-6938-4784-B1EE-D90A8B5B2496}.Release|x64.Build.0 = Release|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|x64.ActiveCfg = Debug|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Debug|x64.Build.0 = Debug|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|Any CPU.ActiveCfg = Release|Any CPU {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|Any CPU.Build.0 = Release|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|x64.ActiveCfg = Release|Any CPU + {9BF2E5EF-186A-4179-B753-AE11EE90E026}.Release|x64.Build.0 = Release|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|x64.ActiveCfg = Debug|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Debug|x64.Build.0 = Debug|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|Any CPU.ActiveCfg = Release|Any CPU {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|Any CPU.Build.0 = Release|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|x64.ActiveCfg = Release|Any CPU + {AC5745DA-570C-4E57-9AE4-D1974F629428}.Release|x64.Build.0 = Release|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|x64.ActiveCfg = Debug|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Debug|x64.Build.0 = Debug|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|Any CPU.Build.0 = Release|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|x64.ActiveCfg = Release|Any CPU + {C048E3FB-CDC4-4577-A40E-8C9B1B7CEDF1}.Release|x64.Build.0 = Release|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|x64.ActiveCfg = Debug|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Debug|x64.Build.0 = Debug|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Release|Any CPU.ActiveCfg = Release|Any CPU {80C75A20-920A-4B30-B05E-970BE844456A}.Release|Any CPU.Build.0 = Release|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Release|x64.ActiveCfg = Release|Any CPU + {80C75A20-920A-4B30-B05E-970BE844456A}.Release|x64.Build.0 = Release|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|x64.ActiveCfg = Debug|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Debug|x64.Build.0 = Debug|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|Any CPU.Build.0 = Release|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|x64.ActiveCfg = Release|Any CPU + {3FB6CD31-0941-4372-9BDB-9E6830385DD4}.Release|x64.Build.0 = Release|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|x64.ActiveCfg = Debug|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Debug|x64.Build.0 = Debug|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|Any CPU.ActiveCfg = Release|Any CPU {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|Any CPU.Build.0 = Release|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|x64.ActiveCfg = Release|Any CPU + {8AC7DE3C-DF3C-44A8-9E69-E1F21BF3E564}.Release|x64.Build.0 = Release|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|x64.ActiveCfg = Debug|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Debug|x64.Build.0 = Debug|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|Any CPU.ActiveCfg = Release|Any CPU {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|Any CPU.Build.0 = Release|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|x64.ActiveCfg = Release|Any CPU + {FFFD905A-1672-4920-B790-EEA6A961383C}.Release|x64.Build.0 = Release|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|x64.ActiveCfg = Debug|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Debug|x64.Build.0 = Debug|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|Any CPU.Build.0 = Release|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|x64.ActiveCfg = Release|Any CPU + {7D481D0D-75C2-4E9F-9FE3-43EB63403F2B}.Release|x64.Build.0 = Release|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|x64.ActiveCfg = Debug|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Debug|x64.Build.0 = Debug|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|Any CPU.ActiveCfg = Release|Any CPU {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|Any CPU.Build.0 = Release|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|x64.ActiveCfg = Release|Any CPU + {191DF615-3D8F-45A3-B763-DD4A604A712A}.Release|x64.Build.0 = Release|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|x64.ActiveCfg = Debug|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Debug|x64.Build.0 = Debug|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|Any CPU.ActiveCfg = Release|Any CPU {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|Any CPU.Build.0 = Release|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|x64.ActiveCfg = Release|Any CPU + {57B57050-5044-4EA9-AC08-030F49E69D62}.Release|x64.Build.0 = Release|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|x64.ActiveCfg = Debug|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Debug|x64.Build.0 = Debug|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|Any CPU.Build.0 = Release|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|x64.ActiveCfg = Release|Any CPU + {F843DAFA-A02B-4B63-8985-6890E513312E}.Release|x64.Build.0 = Release|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|x64.ActiveCfg = Debug|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Debug|x64.Build.0 = Debug|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|Any CPU.Build.0 = Release|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|x64.ActiveCfg = Release|Any CPU + {D9EB512A-9F4F-4D46-86F1-57065CCC933D}.Release|x64.Build.0 = Release|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|x64.ActiveCfg = Debug|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Debug|x64.Build.0 = Debug|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|Any CPU.Build.0 = Release|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|x64.ActiveCfg = Release|Any CPU + {91184A9B-5AB9-4715-B853-8E95E5065AA3}.Release|x64.Build.0 = Release|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|x64.ActiveCfg = Debug|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Debug|x64.Build.0 = Debug|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|Any CPU.Build.0 = Release|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|x64.ActiveCfg = Release|Any CPU + {3A3F1C2C-A805-4EA2-B5AE-80371B565A15}.Release|x64.Build.0 = Release|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Debug|x64.Build.0 = Debug|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|Any CPU.Build.0 = Release|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|x64.ActiveCfg = Release|Any CPU + {84CE1FE5-8141-4C2A-AC30-21BDC87F5D0A}.Release|x64.Build.0 = Release|Any CPU {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|Any CPU.ActiveCfg = Debug|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|Any CPU.Build.0 = Debug|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|x64.ActiveCfg = Debug|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Debug|x64.Build.0 = Debug|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|Any CPU.ActiveCfg = Release|x64 {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|Any CPU.Build.0 = Release|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|x64.ActiveCfg = Release|x64 + {5348A94F-7B3A-4B42-8555-2A1491971090}.Release|x64.Build.0 = Release|x64 {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|x64.ActiveCfg = Debug|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Debug|x64.Build.0 = Debug|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|Any CPU.ActiveCfg = Release|Any CPU {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|Any CPU.Build.0 = Release|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|x64.ActiveCfg = Release|Any CPU + {16B58AE0-0E00-46FB-B114-72600DF6A78A}.Release|x64.Build.0 = Release|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|x64.ActiveCfg = Debug|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Debug|x64.Build.0 = Debug|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|Any CPU.ActiveCfg = Release|Any CPU {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|Any CPU.Build.0 = Release|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|x64.ActiveCfg = Release|Any CPU + {02A92F0E-98F1-4B42-883A-761272BAC185}.Release|x64.Build.0 = Release|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|Any CPU.Build.0 = Debug|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|x64.ActiveCfg = Debug|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Debug|x64.Build.0 = Debug|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|Any CPU.ActiveCfg = Release|Any CPU {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|Any CPU.Build.0 = Release|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|x64.ActiveCfg = Release|Any CPU + {808E6F51-9810-4461-AF4E-EF42EE47C806}.Release|x64.Build.0 = Release|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|x64.ActiveCfg = Debug|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Debug|x64.Build.0 = Debug|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|Any CPU.Build.0 = Release|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|x64.ActiveCfg = Release|Any CPU + {7F967CC6-905A-4198-A667-F9953C8A2139}.Release|x64.Build.0 = Release|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|x64.ActiveCfg = Debug|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Debug|x64.Build.0 = Debug|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|Any CPU.Build.0 = Release|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|x64.ActiveCfg = Release|Any CPU + {CFB5E6D3-C2FD-4D46-B8AC-7E39634E2CA9}.Release|x64.Build.0 = Release|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|x64.ActiveCfg = Debug|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Debug|x64.Build.0 = Debug|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|Any CPU.Build.0 = Release|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|x64.ActiveCfg = Release|Any CPU + {334726D9-6524-4318-82F1-4B72A1027E6E}.Release|x64.Build.0 = Release|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|x64.ActiveCfg = Debug|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Debug|x64.Build.0 = Debug|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|Any CPU.ActiveCfg = Release|Any CPU {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|Any CPU.Build.0 = Release|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|x64.ActiveCfg = Release|Any CPU + {2AE339CD-1D81-46F4-AA19-703EB0CF86FB}.Release|x64.Build.0 = Release|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Debug|x64.Build.0 = Debug|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|Any CPU.Build.0 = Release|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|x64.ActiveCfg = Release|Any CPU + {BE4A63D6-8153-458C-AC0E-744C320AA521}.Release|x64.Build.0 = Release|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|x64.ActiveCfg = Debug|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Debug|x64.Build.0 = Debug|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|Any CPU.Build.0 = Release|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|x64.ActiveCfg = Release|Any CPU + {E2810FAA-8EB3-4B3B-8667-C3C586137D28}.Release|x64.Build.0 = Release|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Debug|x64.Build.0 = Debug|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|Any CPU.Build.0 = Release|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|x64.ActiveCfg = Release|Any CPU + {C8E18D2B-A445-42C4-B6C6-D6CAC51065DC}.Release|x64.Build.0 = Release|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|x64.ActiveCfg = Debug|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Debug|x64.Build.0 = Debug|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|Any CPU.ActiveCfg = Release|Any CPU {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|Any CPU.Build.0 = Release|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|x64.ActiveCfg = Release|Any CPU + {C52E282C-FA0A-4847-8D28-E9C4FDD8B729}.Release|x64.Build.0 = Release|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|x64.ActiveCfg = Debug|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Debug|x64.Build.0 = Debug|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|Any CPU.ActiveCfg = Release|Any CPU {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|Any CPU.Build.0 = Release|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|x64.ActiveCfg = Release|Any CPU + {C72AED47-F5FF-4B7B-BD11-62149542FB22}.Release|x64.Build.0 = Release|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Debug|x64.Build.0 = Debug|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|Any CPU.Build.0 = Release|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|x64.ActiveCfg = Release|Any CPU + {5600A9AF-934C-4225-B05D-F11DBC29E0FF}.Release|x64.Build.0 = Release|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|x64.ActiveCfg = Debug|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Debug|x64.Build.0 = Debug|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|Any CPU.ActiveCfg = Release|Any CPU {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|Any CPU.Build.0 = Release|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|x64.ActiveCfg = Release|Any CPU + {D69636BA-CCE9-4A85-845E-A378A2B03D62}.Release|x64.Build.0 = Release|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|x64.ActiveCfg = Debug|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Debug|x64.Build.0 = Debug|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|Any CPU.Build.0 = Release|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|x64.ActiveCfg = Release|Any CPU + {B7C52FC7-9678-442B-9B1E-F19F09B05606}.Release|x64.Build.0 = Release|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|x64.ActiveCfg = Debug|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Debug|x64.Build.0 = Debug|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|Any CPU.Build.0 = Release|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|x64.ActiveCfg = Release|Any CPU + {3F40EF71-126D-4D2B-84DB-37A574091B13}.Release|x64.Build.0 = Release|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Debug|x64.Build.0 = Debug|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|Any CPU.Build.0 = Release|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|x64.ActiveCfg = Release|Any CPU + {E5E19772-C7DF-4586-AE35-3585AE28DBEB}.Release|x64.Build.0 = Release|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Debug|x64.Build.0 = Debug|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|Any CPU.Build.0 = Release|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|x64.ActiveCfg = Release|Any CPU + {B9F00634-88A1-40EF-9DAD-814A307AD81F}.Release|x64.Build.0 = Release|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Debug|x64.Build.0 = Debug|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|Any CPU.Build.0 = Release|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|x64.ActiveCfg = Release|Any CPU + {BE194924-7162-405D-BF6E-E6086BAA12F1}.Release|x64.Build.0 = Release|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|x64.Build.0 = Debug|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.Build.0 = Release|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|x64.ActiveCfg = Release|Any CPU + {4478A162-4FE9-4737-A630-3899DC5935C6}.Release|x64.Build.0 = Release|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|x64.Build.0 = Debug|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|Any CPU.Build.0 = Release|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|x64.ActiveCfg = Release|Any CPU + {7B73D864-9997-4637-8765-44C17FD09CE1}.Release|x64.Build.0 = Release|Any CPU {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|Any CPU.ActiveCfg = Debug|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|Any CPU.Build.0 = Debug|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|x64.ActiveCfg = Debug|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Debug|x64.Build.0 = Debug|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|Any CPU.ActiveCfg = Release|x64 {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|Any CPU.Build.0 = Release|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|x64.ActiveCfg = Release|x64 + {DAB8847B-DE0A-45E2-A7DA-30432A36525B}.Release|x64.Build.0 = Release|x64 {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|x64.ActiveCfg = Debug|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Debug|x64.Build.0 = Debug|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|Any CPU.ActiveCfg = Release|Any CPU {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|Any CPU.Build.0 = Release|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|x64.ActiveCfg = Release|Any CPU + {825B11E7-9BF3-43B7-9BCE-4309EE404AEE}.Release|x64.Build.0 = Release|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|x64.ActiveCfg = Debug|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Debug|x64.Build.0 = Debug|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|Any CPU.ActiveCfg = Release|Any CPU {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|Any CPU.Build.0 = Release|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|x64.ActiveCfg = Release|Any CPU + {896CE6A5-59AA-4F7B-90EB-562F47D3C49E}.Release|x64.Build.0 = Release|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Debug|x64.Build.0 = Debug|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|Any CPU.Build.0 = Release|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|x64.ActiveCfg = Release|Any CPU + {FE571017-BC81-4B70-A876-58A52CAB40B4}.Release|x64.Build.0 = Release|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|x64.ActiveCfg = Debug|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Debug|x64.Build.0 = Debug|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|Any CPU.Build.0 = Release|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|x64.ActiveCfg = Release|Any CPU + {F1D041E0-DDB2-41B8-97EE-5539B10D91BE}.Release|x64.Build.0 = Release|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|x64.ActiveCfg = Debug|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Debug|x64.Build.0 = Debug|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|Any CPU.Build.0 = Release|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|x64.ActiveCfg = Release|Any CPU + {6B572F54-0E2F-4223-8283-14B3BAB7534A}.Release|x64.Build.0 = Release|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|x64.ActiveCfg = Debug|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Debug|x64.Build.0 = Debug|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|Any CPU.ActiveCfg = Release|Any CPU {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|Any CPU.Build.0 = Release|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|x64.ActiveCfg = Release|Any CPU + {084FB05C-4022-40FD-B00B-E3229B882F08}.Release|x64.Build.0 = Release|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Debug|x64.Build.0 = Debug|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D33307F-0E96-491A-9D31-9025709310F6}.Release|Any CPU.Build.0 = Release|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Release|x64.ActiveCfg = Release|Any CPU + {8D33307F-0E96-491A-9D31-9025709310F6}.Release|x64.Build.0 = Release|Any CPU {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|Any CPU.ActiveCfg = Debug|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|Any CPU.Build.0 = Debug|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|x64.ActiveCfg = Debug|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Debug|x64.Build.0 = Debug|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|Any CPU.ActiveCfg = Release|x64 {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|Any CPU.Build.0 = Release|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|x64.ActiveCfg = Release|x64 + {C91D0412-1BB2-40D2-8DCA-A48B6C5B7E67}.Release|x64.Build.0 = Release|x64 {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|x64.ActiveCfg = Debug|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Debug|x64.Build.0 = Debug|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|Any CPU.Build.0 = Release|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|x64.ActiveCfg = Release|Any CPU + {F31606FF-3737-45DC-8E89-6256AACD841F}.Release|x64.Build.0 = Release|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|x64.ActiveCfg = Debug|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Debug|x64.Build.0 = Debug|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|Any CPU.Build.0 = Release|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|x64.ActiveCfg = Release|Any CPU + {5AC206E0-6B2E-4DBC-9B8A-74A47C907C6A}.Release|x64.Build.0 = Release|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|x64.ActiveCfg = Debug|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Debug|x64.Build.0 = Debug|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|Any CPU.ActiveCfg = Release|Any CPU {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|Any CPU.Build.0 = Release|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|x64.ActiveCfg = Release|Any CPU + {D18F494B-3639-4094-BD5E-BE8D81D5CD39}.Release|x64.Build.0 = Release|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|x64.ActiveCfg = Debug|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Debug|x64.Build.0 = Debug|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|Any CPU.ActiveCfg = Release|Any CPU {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|Any CPU.Build.0 = Release|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|x64.ActiveCfg = Release|Any CPU + {CAE417E8-0E2D-499D-B11D-78A95155AF8A}.Release|x64.Build.0 = Release|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|x64.ActiveCfg = Debug|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Debug|x64.Build.0 = Debug|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Release|Any CPU.ActiveCfg = Release|Any CPU {D649D56B-777C-4246-8D59-C32749D94D39}.Release|Any CPU.Build.0 = Release|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Release|x64.ActiveCfg = Release|Any CPU + {D649D56B-777C-4246-8D59-C32749D94D39}.Release|x64.Build.0 = Release|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|x64.ActiveCfg = Debug|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Debug|x64.Build.0 = Debug|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|Any CPU.Build.0 = Release|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|x64.ActiveCfg = Release|Any CPU + {8B4F93E0-86D7-474C-8DD5-14E0AAD8BF91}.Release|x64.Build.0 = Release|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|x64.ActiveCfg = Debug|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Debug|x64.Build.0 = Debug|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|Any CPU.Build.0 = Release|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|x64.ActiveCfg = Release|Any CPU + {A0677BEA-ADB1-4950-89E6-89483D621A52}.Release|x64.Build.0 = Release|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|x64.ActiveCfg = Debug|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Debug|x64.Build.0 = Debug|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|Any CPU.ActiveCfg = Release|Any CPU {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|Any CPU.Build.0 = Release|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|x64.ActiveCfg = Release|Any CPU + {E0621435-AF35-4CFA-BE9E-3781AF6E161F}.Release|x64.Build.0 = Release|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|x64.ActiveCfg = Debug|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Debug|x64.Build.0 = Debug|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|Any CPU.Build.0 = Release|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|x64.ActiveCfg = Release|Any CPU + {C3114338-AD22-4EBC-85C3-EE06045CDD78}.Release|x64.Build.0 = Release|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|x64.ActiveCfg = Debug|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Debug|x64.Build.0 = Debug|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|Any CPU.ActiveCfg = Release|Any CPU {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|Any CPU.Build.0 = Release|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|x64.ActiveCfg = Release|Any CPU + {A1429F96-C7F8-49D8-ADB8-73A1A4DAA70F}.Release|x64.Build.0 = Release|Any CPU {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|Any CPU.ActiveCfg = Debug|ARM {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|Any CPU.Build.0 = Debug|ARM + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|x64.ActiveCfg = Debug|x64 + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Debug|x64.Build.0 = Debug|x64 {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|Any CPU.ActiveCfg = Release|ARM {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|Any CPU.Build.0 = Release|ARM + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|x64.ActiveCfg = Release|x64 + {F50194C0-9561-40C7-B9CB-B977E3B3D76D}.Release|x64.Build.0 = Release|x64 {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|x64.ActiveCfg = Debug|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Debug|x64.Build.0 = Debug|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|Any CPU.ActiveCfg = Release|Any CPU {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|Any CPU.Build.0 = Release|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|x64.ActiveCfg = Release|Any CPU + {3434D5B2-B06F-4356-9E9B-90171CEF482B}.Release|x64.Build.0 = Release|Any CPU {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|Any CPU.ActiveCfg = Debug|ARM {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|Any CPU.Build.0 = Debug|ARM + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|x64.ActiveCfg = Debug|Win32 + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Debug|x64.Build.0 = Debug|Win32 {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|Any CPU.ActiveCfg = Release|ARM {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|Any CPU.Build.0 = Release|ARM + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|x64.ActiveCfg = Release|Win32 + {ECD9E150-8104-4DA3-B807-A6A4392A67C6}.Release|x64.Build.0 = Release|Win32 {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Debug|x64.Build.0 = Debug|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|Any CPU.Build.0 = Release|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|x64.ActiveCfg = Release|Any CPU + {BE95524A-F9C2-4D0D-8F7E-1C7019B5A114}.Release|x64.Build.0 = Release|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|x64.ActiveCfg = Debug|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Debug|x64.Build.0 = Debug|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|Any CPU.Build.0 = Release|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|x64.ActiveCfg = Release|Any CPU + {74504D41-B716-4B0B-B265-ED2A91A2A5C2}.Release|x64.Build.0 = Release|Any CPU {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.ActiveCfg = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.Build.0 = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|Any CPU.Deploy.0 = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.ActiveCfg = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.Build.0 = Debug|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Debug|x64.Deploy.0 = Debug|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.ActiveCfg = Release|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.Build.0 = Release|ARM {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|Any CPU.Deploy.0 = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.ActiveCfg = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.Build.0 = Release|ARM + {D318834B-5A27-4EAC-B17D-A9BD7A2DCA0D}.Release|x64.Deploy.0 = Release|ARM {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|x64.ActiveCfg = Debug|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Debug|x64.Build.0 = Debug|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|Any CPU.ActiveCfg = Release|Any CPU {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|Any CPU.Build.0 = Release|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|x64.ActiveCfg = Release|Any CPU + {272CEB19-2B5A-49BC-B8EA-CBC79AA87C37}.Release|x64.Build.0 = Release|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|x64.ActiveCfg = Debug|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Debug|x64.Build.0 = Debug|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|Any CPU.Build.0 = Release|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|x64.ActiveCfg = Release|Any CPU + {1C844B9E-A51C-483C-A045-7AB8F2012581}.Release|x64.Build.0 = Release|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|x64.ActiveCfg = Debug|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Debug|x64.Build.0 = Debug|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|Any CPU.ActiveCfg = Release|Any CPU {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|Any CPU.Build.0 = Release|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|x64.ActiveCfg = Release|Any CPU + {76E38559-0AF2-4AE3-BCE8-8653277A5B07}.Release|x64.Build.0 = Release|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|x64.ActiveCfg = Debug|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Debug|x64.Build.0 = Debug|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|Any CPU.Build.0 = Release|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|x64.ActiveCfg = Release|Any CPU + {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD}.Release|x64.Build.0 = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Debug|x64.Build.0 = Debug|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.Build.0 = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.ActiveCfg = Release|Any CPU + {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sources/Runtime/Microsoft.Psi/Common/PsiStreamMetadata.cs b/Sources/Runtime/Microsoft.Psi/Common/PsiStreamMetadata.cs index ad981123d..9b2153e84 100644 --- a/Sources/Runtime/Microsoft.Psi/Common/PsiStreamMetadata.cs +++ b/Sources/Runtime/Microsoft.Psi/Common/PsiStreamMetadata.cs @@ -235,7 +235,7 @@ public T GetSupplementalMetadata(KnownSerializers serializers) /// public T GetSupplementalMetadata() { - return this.GetSupplementalMetadata(KnownSerializers.Default); + return this.GetSupplementalMetadata(KnownSerializers.GetKnownSerializers()); } /// diff --git a/Sources/Runtime/Microsoft.Psi/Data/Importer.cs b/Sources/Runtime/Microsoft.Psi/Data/Importer.cs index 73ea3d68c..edbf03b95 100644 --- a/Sources/Runtime/Microsoft.Psi/Data/Importer.cs +++ b/Sources/Runtime/Microsoft.Psi/Data/Importer.cs @@ -69,7 +69,7 @@ public KnownSerializers Serializers return storeStreamReader.GetSerializers(); } - return KnownSerializers.Default; + return KnownSerializers.GetKnownSerializers(); } } diff --git a/Sources/Runtime/Microsoft.Psi/Serialization/KnownSerializers.cs b/Sources/Runtime/Microsoft.Psi/Serialization/KnownSerializers.cs index 5252c78a0..edab4a0f0 100644 --- a/Sources/Runtime/Microsoft.Psi/Serialization/KnownSerializers.cs +++ b/Sources/Runtime/Microsoft.Psi/Serialization/KnownSerializers.cs @@ -15,7 +15,7 @@ namespace Microsoft.Psi.Serialization /// /// Represents the registry of all serializers. - /// The contains system-wide serializers for the current version of the type system. + /// The contains system-wide serializers for the current version of the type system. /// Serializers explicitly registered with this instance are used by all other instances unless an override is specified. /// When deserializing from a persisted file, the instance returned by /// the will create its own KnownSerializer instance, and register serializers @@ -65,14 +65,14 @@ public class KnownSerializers // - there can be at most one schema for a type and at most one type for a schema, // and they must have matching IDs (implicitly or because of a user-specified name mapping) + // the set of types we don't know how to serialize + private static readonly HashSet UnserializableTypes = new (); + /// /// The default set of types and serializer creation rules globally known to the serialization subsystem. /// Custom serializers can be added directly to this set. /// - public static readonly KnownSerializers Default; - - // the set of types we don't know how to serialize - private static readonly HashSet UnserializableTypes = new (); + private static KnownSerializers defaultKnownSerializers; // mapping from fully-qualified .NET type names to synonyms private readonly Dictionary typeNameSynonyms = new (); @@ -131,7 +131,7 @@ static KnownSerializers() UnserializableTypes.Add(typeof(UIntPtr)); UnserializableTypes.Add(typeof(MemberInfo)); UnserializableTypes.Add(typeof(System.Diagnostics.StackTrace)); - Default = new KnownSerializers(true, RuntimeInfo.Latest); + defaultKnownSerializers = new KnownSerializers(true, RuntimeInfo.Latest); } /// @@ -177,13 +177,13 @@ private KnownSerializers(bool isDefault, RuntimeInfo runtimeInfo) else { // all other instances start off with the Default rules - this.templates = new Dictionary(Default.templates); - this.serializers = new Dictionary(Default.serializers); - this.knownTypes = new ConcurrentDictionary(Default.knownTypes); - this.knownNames = new ConcurrentDictionary(Default.knownNames); - this.schemas = new ConcurrentDictionary(Default.schemas); - this.schemasById = new ConcurrentDictionary(Default.schemasById); - this.cloningFlags = new ConcurrentDictionary(Default.cloningFlags); + this.templates = new Dictionary(defaultKnownSerializers.templates); + this.serializers = new Dictionary(defaultKnownSerializers.serializers); + this.knownTypes = new ConcurrentDictionary(defaultKnownSerializers.knownTypes); + this.knownNames = new ConcurrentDictionary(defaultKnownSerializers.knownNames); + this.schemas = new ConcurrentDictionary(defaultKnownSerializers.schemas); + this.schemasById = new ConcurrentDictionary(defaultKnownSerializers.schemasById); + this.cloningFlags = new ConcurrentDictionary(defaultKnownSerializers.cloningFlags); } } @@ -207,6 +207,15 @@ private KnownSerializers(bool isDefault, RuntimeInfo runtimeInfo) /// public IDictionary TypeNameSynonyms => this.typeNameSynonyms; + /// + /// Initializes a new instance of the class. + /// + /// static class. + public static KnownSerializers GetKnownSerializers() + { + return defaultKnownSerializers; + } + /// /// Registers type T with the specified contract name. /// Use this overload to deserialize data persisted before a type name change. diff --git a/Sources/Runtime/Microsoft.Psi/Serialization/SerializationContext.cs b/Sources/Runtime/Microsoft.Psi/Serialization/SerializationContext.cs index becb73803..e9b92fc47 100644 --- a/Sources/Runtime/Microsoft.Psi/Serialization/SerializationContext.cs +++ b/Sources/Runtime/Microsoft.Psi/Serialization/SerializationContext.cs @@ -27,7 +27,7 @@ public class SerializationContext /// This will become internal. Use Serializer.Schema instead. /// public SerializationContext() - : this(KnownSerializers.Default) + : this(KnownSerializers.GetKnownSerializers()) { } @@ -37,7 +37,7 @@ public SerializationContext() /// The set of custom serializers to use instead of the default ones. public SerializationContext(KnownSerializers serializers) { - this.serializers = serializers ?? KnownSerializers.Default; + this.serializers = serializers ?? KnownSerializers.GetKnownSerializers(); } internal KnownSerializers Serializers => this.serializers; diff --git a/Sources/Runtime/Microsoft.Psi/Serialization/Serializer.cs b/Sources/Runtime/Microsoft.Psi/Serialization/Serializer.cs index faf81af7d..29b6df56b 100644 --- a/Sources/Runtime/Microsoft.Psi/Serialization/Serializer.cs +++ b/Sources/Runtime/Microsoft.Psi/Serialization/Serializer.cs @@ -142,7 +142,7 @@ public static void Clear(ref T target, SerializationContext context) /// True if the type is immutable. public static bool IsImmutableType() { - return KnownSerializers.Default.GetHandler().IsImmutableType; + return KnownSerializers.GetKnownSerializers().GetHandler().IsImmutableType; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Sources/Runtime/Microsoft.Psi/Serialization/StructHandler.cs b/Sources/Runtime/Microsoft.Psi/Serialization/StructHandler.cs index b262eca8b..cd8674a43 100644 --- a/Sources/Runtime/Microsoft.Psi/Serialization/StructHandler.cs +++ b/Sources/Runtime/Microsoft.Psi/Serialization/StructHandler.cs @@ -15,7 +15,7 @@ namespace Microsoft.Psi.Serialization /// The type of objects the handler understands. internal sealed class StructHandler : SerializationHandler { - private static readonly CloneDelegate CopyToBox = Generator.GenerateCloneMethod(il => Generator.EmitCopyToBox(typeof(T), il)); + // private static readonly CloneDelegate CopyToBox = Generator.GenerateCloneMethod(il => Generator.EmitCopyToBox(typeof(T), il)); // the inner serializer and serializerEx private readonly ISerializer innerSerializer; @@ -71,7 +71,9 @@ internal override void UntypedDeserialize(BufferReader reader, ref object target context.AddDeserializedObject(target); this.innerSerializer.Deserialize(reader, ref typedTarget, context); - CopyToBox(typedTarget, ref target, context); + + // CopyToBox(typedTarget, ref target, context); + target = (object)typedTarget; } internal override void UntypedClone(object instance, ref object target, SerializationContext context) @@ -88,7 +90,9 @@ internal override void UntypedClone(object instance, ref object target, Serializ context.AddDeserializedObject(target); this.innerSerializer.Clone((T)instance, ref typedTarget, context); - CopyToBox(typedTarget, ref target, context); + + // CopyToBox(typedTarget, ref target, context); + target = (object)typedTarget; } internal override void UntypedClear(ref object target, SerializationContext context) @@ -105,7 +109,9 @@ internal override void UntypedClear(ref object target, SerializationContext cont context.AddDeserializedObject(target); this.innerSerializer.Clear(ref typedTarget, context); - CopyToBox(typedTarget, ref target, context); + + // CopyToBox(typedTarget, ref target, context); + target = (object)typedTarget; } } } \ No newline at end of file diff --git a/Sources/Runtime/Microsoft.Psi/Streams/Receiver{T}.cs b/Sources/Runtime/Microsoft.Psi/Streams/Receiver{T}.cs index 2ae7922c1..6990acc5f 100644 --- a/Sources/Runtime/Microsoft.Psi/Streams/Receiver{T}.cs +++ b/Sources/Runtime/Microsoft.Psi/Streams/Receiver{T}.cs @@ -422,7 +422,7 @@ private int ComputeDataSize(T data) { if (this.computeDataSize == null) { - var serializers = KnownSerializers.Default; + var serializers = KnownSerializers.GetKnownSerializers(); var context = new SerializationContext(serializers); var handler = serializers.GetHandler(); var writer = new BufferWriter(16); From 045f91932789a731ed50941c06de121f05327cff Mon Sep 17 00:00:00 2001 From: AuMilliat Date: Thu, 14 Mar 2024 15:47:54 +0100 Subject: [PATCH 07/21] New version of Interop for android --- .editorconfig | 4 + Psi.sln | 11 + .../Microsoft.Psi.InteropAndroid.csproj | 48 ++ .../Microsoft.Psi.InteropAndroid/Readme.md | 3 + .../Rendezvous/Operators.cs | 117 +++++ .../Rendezvous/Readme.md | 5 + .../Rendezvous/Rendezvous.cs | 422 ++++++++++++++++++ .../Rendezvous/RendezvousClient.cs | 191 ++++++++ .../Rendezvous/RendezvousClient.py | 212 +++++++++ .../Rendezvous/RendezvousRelay.cs | 213 +++++++++ .../Rendezvous/RendezvousServer.cs | 198 ++++++++ .../Serialization/Format{T}.cs | 97 ++++ .../Serialization/IFormatDeserializer.cs | 23 + .../Serialization/IFormatSerializer.cs | 22 + .../Serialization/Readme.md | 45 ++ .../Transport/Readme.md | 167 +++++++ .../Transport/TcpSource.cs | 172 +++++++ .../Transport/TcpWriter.cs | 105 +++++ .../Microsoft.Psi.InteropAndroid/build.sh | 3 + .../stylecop.json | 17 + 20 files changed, 2075 insertions(+) create mode 100644 .editorconfig create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Microsoft.Psi.InteropAndroid.csproj create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Readme.md create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Operators.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Readme.md create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Rendezvous.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.py create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousRelay.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousServer.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Format{T}.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatDeserializer.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatSerializer.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Readme.md create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/Readme.md create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/TcpSource.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/TcpWriter.cs create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/build.sh create mode 100644 Sources/Runtime/Microsoft.Psi.InteropAndroid/stylecop.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..4af53c05c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS0162: Unreachable code detected +dotnet_diagnostic.CS0162.severity = none diff --git a/Psi.sln b/Psi.sln index 8f804972d..c6b1bb194 100644 --- a/Psi.sln +++ b/Psi.sln @@ -234,6 +234,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestConnection", "TestConne {04147400-0AB0-4F07-9975-D4B7E58150DB} = {04147400-0AB0-4F07-9975-D4B7E58150DB} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Psi.InteropAndroid", "Sources\Runtime\Microsoft.Psi.InteropAndroid\Microsoft.Psi.InteropAndroid.csproj", "{3D49C0D3-B925-4C12-9191-87702DC20354}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -806,6 +808,14 @@ Global {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|Any CPU.Build.0 = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.ActiveCfg = Release|Any CPU {E4D7E21F-8469-456F-828D-DE1D2590E4EA}.Release|x64.Build.0 = Release|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Debug|x64.ActiveCfg = Debug|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Debug|x64.Build.0 = Debug|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Release|Any CPU.Build.0 = Release|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Release|x64.ActiveCfg = Release|Any CPU + {3D49C0D3-B925-4C12-9191-87702DC20354}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -906,6 +916,7 @@ Global {1C844B9E-A51C-483C-A045-7AB8F2012581} = {49072585-8CC1-43A5-BE0D-ABCE888BC5D1} {76E38559-0AF2-4AE3-BCE8-8653277A5B07} = {49072585-8CC1-43A5-BE0D-ABCE888BC5D1} {41FBDC53-3167-4DEA-8B87-CFCCAFBCE7DD} = {DF620739-6A2F-49F0-A732-6575879F1D86} + {3D49C0D3-B925-4C12-9191-87702DC20354} = {3F77CC04-2E58-452B-8107-0C93E7944D4E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EAF15EE9-DCC5-411B-A9E5-7C2F3D132331} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Microsoft.Psi.InteropAndroid.csproj b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Microsoft.Psi.InteropAndroid.csproj new file mode 100644 index 000000000..9032dd930 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Microsoft.Psi.InteropAndroid.csproj @@ -0,0 +1,48 @@ + + + + netstandard2.0 + False + Provides APIs and components for interoperation with other data formats. + + + + bin\Debug\netstandard2.0\Microsoft.Psi.Interop.xml + ../../../Build/Microsoft.Psi.ruleset + true + + + + + bin\Release\netstandard2.0\Microsoft.Psi.Interop.xml + ../../../Build/Microsoft.Psi.ruleset + true + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Readme.md b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Readme.md new file mode 100644 index 000000000..b4ee22b5f --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Readme.md @@ -0,0 +1,3 @@ +# Psi Interop Android + +Reduced version of `Microsoft.Psi.Interop` for using RendezVous system and TCPSource/Writer in Unity for Quest headset. \ No newline at end of file diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Operators.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Operators.cs new file mode 100644 index 000000000..c3c1af9a6 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Operators.cs @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Rendezvous +{ + using System; + using Microsoft.Psi.Interop.Serialization; + using Microsoft.Psi.Interop.Transport; + using Microsoft.Psi.Remoting; + + /// + /// Rendezvous related operators. + /// + public static class Operators + { + /// + /// Create a rendezvous endpoint from a . + /// + /// Type of data stream. + /// from which to create endpoint. + /// Address with which to create endpoint. + /// The name of the rendezvous stream. + /// Rendezvous endpoint. + public static Rendezvous.Endpoint ToRendezvousEndpoint(this TcpWriter writer, string address, string streamName) + => new Rendezvous.TcpSourceEndpoint(address, writer.Port, new Rendezvous.Stream(streamName, typeof(T))); + + /// + /// Create a from a . + /// + /// Type of data stream. + /// from which to create . + /// The pipeline to add the component to. + /// The deserializer to use to deserialize messages. + /// An optional deallocator for the data. + /// An optional parameter indicating whether to use originating times received from the source over the network or to re-timestamp with the current pipeline time upon receiving. + /// An optional name for the TCP source component. + /// . + public static TcpSource ToTcpSource( + this Rendezvous.TcpSourceEndpoint endpoint, + Pipeline pipeline, + IFormatDeserializer deserializer, + Action deallocator = null, + bool useSourceOriginatingTimes = true, + string name = nameof(TcpSource)) + => new (pipeline, endpoint.Host, endpoint.Port, deserializer, deallocator, useSourceOriginatingTimes, name); + + /// + /// Create a rendezvous endpoint from a . + /// + /// from which to create endpoint. + /// Host address with which to create endpoint. + /// Rendezvous endpoint. + public static Rendezvous.Endpoint ToRendezvousEndpoint(this RemoteClockExporter exporter, string host) + => new Rendezvous.RemoteClockExporterEndpoint(host, exporter.Port); + + /// + /// Create a rendezvous endpoint from a . + /// + /// from which to create endpoint. + /// Host name with which to create endpoint. + /// Rendezvous endpoint. + public static Rendezvous.Endpoint ToRendezvousEndpoint(this RemoteExporter exporter, string host) + { + // Each RemoteExporter is an endpoint emitting one or more streams. + var endpoint = new Rendezvous.RemoteExporterEndpoint(host, exporter.Port, exporter.TransportKind); + foreach (var m in exporter.Exporter.Metadata) + { + endpoint.AddStream(new Rendezvous.Stream(m.Name, m.TypeName)); + } + + return endpoint; + } + + /// + /// Create a from a . + /// + /// from which to create . + /// The pipeline to add the component to. + /// . + public static RemoteImporter ToRemoteImporter(this Rendezvous.RemoteExporterEndpoint endpoint, Pipeline pipeline) + => new (pipeline, endpoint.Host, endpoint.Port); + + /// + /// Create a from a . + /// + /// from which to create . + /// The pipeline to add the component to. + /// . + public static RemoteClockImporter ToRemoteClockImporter(this Rendezvous.RemoteClockExporterEndpoint endpoint, Pipeline pipeline) + => new (pipeline, endpoint.Host, endpoint.Port); + + /// + /// Writes a stream to a specified rendezvous process. + /// + /// The type of data in the stream. + /// The source stream to write. + /// The name under which to write the stream to the rendezvous process. + /// The rendezvous process. + /// The address to write the stream to. + /// The port to write the stream to. + /// The serializer to use when writing the stream. + /// An optional delivery policy. + public static void WriteToRendezvousProcess( + this IProducer source, + string streamName, + Rendezvous.Process rendezvousProcess, + string address, + int port, + IFormatSerializer serializer, + DeliveryPolicy deliveryPolicy = null) + { + var tcpWriter = new TcpWriter(source.Out.Pipeline, port, serializer); + source.PipeTo(tcpWriter, deliveryPolicy); + rendezvousProcess.AddEndpoint(tcpWriter.ToRendezvousEndpoint(address, streamName)); + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Readme.md b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Readme.md new file mode 100644 index 000000000..a2c561304 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Readme.md @@ -0,0 +1,5 @@ +# Interop Rendezvous + +A distributed \psi system may have many separate pipelines running in separate processes, on separate machines, publishing and subscribing to streams being conveyed using various protocols. The rendezvous system allows each pipeline process to advertise its available streams and to discover those of other pipelines. This is accomplished by a centralized "rendezvous point" which maintains and relays endpoint connection and stream information. + +For more information, see [the Rendezvous System wiki page](https://github.com/microsoft/psi/wiki/Rendezvous-System). diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Rendezvous.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Rendezvous.cs new file mode 100644 index 000000000..a910e257c --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/Rendezvous.cs @@ -0,0 +1,422 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Rendezvous +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Psi.Remoting; + + /// + /// Component that maintains rendezvous information. + /// + public class Rendezvous + { + /// + /// A rendezvous may know about many processes, each with many endpoints, each with many streams. + /// + private readonly ConcurrentDictionary processes = new (); + + private EventHandler processAdded; + + /// + /// Event raised when processes are added. + /// + /// Includes processes added before subscription. + public event EventHandler ProcessAdded + { + add + { + // inform late-joining handler of currently added processes + foreach (var p in this.Processes) + { + value.Invoke(this, p); + } + + this.processAdded += value; + } + + remove + { + this.processAdded -= value; + } + } + + /// + /// Event raised when processes are removed. + /// + public event EventHandler ProcessRemoved; + + /// + /// Gets the currently known processes. + /// + public IEnumerable Processes + { + get + { + return this.processes.Values; + } + } + + /// + /// Try to add a new process, if not already present. + /// + /// Process to add. + /// A value indicating whether the process was added. + public bool TryAddProcess(Process process) + { + if (this.processes.TryAdd(process.Name, process)) + { + this.processAdded?.Invoke(this, process); + return true; + } + + return false; + } + + /// + /// Try to remove a process if present. + /// + /// Process to remove. + /// A value indicating whether the process was removed. + public bool TryRemoveProcess(Process process) + { + if (this.processes.TryRemove(process.Name, out _)) + { + this.ProcessRemoved?.Invoke(this, process); + return true; + } + + return false; + } + + /// + /// Try to remove a process if present. + /// + /// Name of process to remove. + /// A value indicating whether the process was removed. + public bool TryRemoveProcess(string processName) + { + if (this.TryGetProcess(processName, out Process process)) + { + return this.TryRemoveProcess(process); + } + + return false; + } + + /// + /// Try to get process by name. + /// + /// Process name. + /// Process or null if not found. + /// A value indicating whether named process found. + public bool TryGetProcess(string processName, out Process process) + { + return this.processes.TryGetValue(processName, out process); + } + + /// + /// Represents a remoted stream of data. + /// + public class Stream + { + /// + /// Initializes a new instance of the class. + /// + /// Stream name. + /// Type name of stream data. + public Stream(string streamName, string typeName) + { + this.StreamName = streamName; + this.TypeName = typeName; + } + + /// + /// Initializes a new instance of the class. + /// + /// Stream name. + /// Type of stream data. + public Stream(string streamName, Type type) + : this(streamName, type.AssemblyQualifiedName) + { + } + + /// + /// Gets the stream name. + /// + public string StreamName { get; private set; } + + /// + /// Gets the type name of the stream data. + /// + public string TypeName { get; private set; } + } + + /// + /// Represents an endpoint providing remoted data streams. + /// + public abstract class Endpoint + { + private readonly ConcurrentDictionary streams; + + /// + /// Initializes a new instance of the class. + /// + /// Endpoint streams. + public Endpoint(IEnumerable streams) + { + this.streams = new ConcurrentDictionary(streams.Select(s => new KeyValuePair(s.StreamName, s))); + } + + /// + /// Initializes a new instance of the class. + /// + public Endpoint() + : this(Enumerable.Empty()) + { + } + + /// + /// Gets the streams. + /// + public IEnumerable Streams + { + get { return this.streams.Values; } + } + + /// + /// Add new stream. + /// + /// Endpoint stream to add. + public virtual void AddStream(Stream stream) + { + this.streams.TryAdd(stream.StreamName, stream); + } + } + + /// + /// Represents a simple TCP source endpoint providing a single remoted data stream. + /// + public class TcpSourceEndpoint : Endpoint + { + /// + /// Initializes a new instance of the class. + /// + /// Host name used by the endpoint. + /// Port number used by the endpoint. + /// Endpoint stream. + public TcpSourceEndpoint(string host, int port, Stream stream = null) + : base(stream is null ? Enumerable.Empty() : new[] { stream }) + { + if (string.IsNullOrEmpty(host)) + { + throw new ArgumentException("Host must be not null or empty."); + } + + this.Host = host; + this.Port = port; + } + + /// + /// Gets the endpoint address. + /// + public string Host { get; private set; } + + /// + /// Gets the endpoint port number. + /// + public int Port { get; private set; } + + /// + /// Gets the stream (Tcp endpoints have only one). + /// + public Stream Stream => this.Streams.FirstOrDefault(); + + /// + public override void AddStream(Stream stream) + { + if (this.Streams.Count() > 0) + { + throw new InvalidOperationException($"Cannot add more than one stream to a single {nameof(TcpSourceEndpoint)}"); + } + + base.AddStream(stream); + } + } + + /// + /// Represents a NetMQ source endpoint providing remoted data streams. + /// + public class NetMQSourceEndpoint : Endpoint + { + /// + /// Initializes a new instance of the class. + /// + /// Address used by the endpoint. + /// Endpoint streams. + public NetMQSourceEndpoint(string address, IEnumerable streams) + : base(streams) + { + this.Address = address; + } + + /// + /// Initializes a new instance of the class. + /// + /// Address used by the endpoint. + public NetMQSourceEndpoint(string address) + : this(address, Enumerable.Empty()) + { + } + + /// + /// Gets the endpoint address. + /// + public string Address { get; private set; } + } + + /// + /// Represents a remote exporter endpoint providing remoted data streams. + /// + public class RemoteExporterEndpoint : Endpoint + { + /// + /// Initializes a new instance of the class. + /// + /// Host name used by the endpoint. + /// Port used by the endpoint. + /// Tranport kind used by the endpoint. + /// Endpoint streams. + public RemoteExporterEndpoint(string host, int port, TransportKind transport, IEnumerable streams) + : base(streams) + { + this.Host = host; + this.Port = port; + this.Transport = transport; + } + + /// + /// Initializes a new instance of the class. + /// + /// Host name used by the endpoint. + /// Port used by the endpoint. + /// Tranport kind used by the endpoint. + public RemoteExporterEndpoint(string host, int port, TransportKind transport) + : this(host, port, transport, Enumerable.Empty()) + { + } + + /// + /// Gets the endpoint host name. + /// + public string Host { get; private set; } + + /// + /// Gets the endpoint port. + /// + public int Port { get; private set; } + + /// + /// Gets the endpoint transport kind. + /// + public TransportKind Transport { get; private set; } + } + + /// + /// Represents a remote clock exporter endpoint providing clock information. + /// + /// + /// Endpoint does not provide any streams. Clock information is exchanged directly. + /// + public class RemoteClockExporterEndpoint : Endpoint + { + /// + /// Initializes a new instance of the class. + /// + /// Host name used by the endpoint. + /// Port used by the endpoint. + public RemoteClockExporterEndpoint(string host, int port) + { + this.Host = host; + this.Port = port; + } + + /// + /// Gets the endpoint host name. + /// + public string Host { get; private set; } + + /// + /// Gets the endpoint port. + /// + public int Port { get; private set; } + + /// + public override void AddStream(Stream stream) + { + throw new InvalidOperationException($"Cannot add streams to a {nameof(RemoteClockExporterEndpoint)}"); + } + } + + /// + /// Represents an application process hosting endpoints. + /// + public class Process + { + private readonly List endpoints; + + /// + /// Initializes a new instance of the class. + /// + /// Unique name by which to refer to the process. + /// Process endpoints. + /// Optional process version (allowing negotiation of client compatibility). + public Process(string name, IEnumerable endpoints, string version = null) + { + this.Name = name; + this.Version = version ?? string.Empty; + this.endpoints = endpoints.ToList(); + } + + /// + /// Initializes a new instance of the class. + /// + /// Unique name by which to refer to the process. + /// Optional process version (allowing negotiation of client compatibility). + public Process(string name, string version = null) + : this(name, Enumerable.Empty(), version) + { + } + + /// + /// Gets the process name. + /// + public string Name { get; private set; } + + /// + /// Gets the process version. + /// + public string Version { get; private set; } + + /// + /// Gets the endpoints. + /// + public IEnumerable Endpoints + { + get { return this.endpoints; } + } + + /// + /// Add new endpoint. + /// + /// Process endpoint to add. + public void AddEndpoint(Endpoint endpoint) + { + this.endpoints.Add(endpoint); + } + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.cs new file mode 100644 index 000000000..58cb028cb --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.cs @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Rendezvous +{ + using System; + using System.Diagnostics; + using System.IO; + using System.Net.Sockets; + using System.Threading; + + /// + /// Client which connects to a and relays information. + /// + public class RendezvousClient : RendezvousRelay, IDisposable + { + private readonly string serverAddress; + private readonly int port; + private readonly EventWaitHandle connected = new (false, EventResetMode.ManualReset); + + private TcpClient client; + private BinaryReader reader; + private BinaryWriter writer; + private bool active = false; + private string clientAddress = null; + + /// + /// Initializes a new instance of the class. + /// + /// TCP address to which to connect. + /// Optional TCP port to which to connect. + /// Optional rendezvous instance to relay. + public RendezvousClient(string serverAddress, int port = RendezvousServer.DefaultPort, Rendezvous rendezvous = null) + : base(rendezvous) + { + this.serverAddress = serverAddress; + this.port = port; + this.connected.Reset(); + } + + /// + /// Gets wait handle for server connection being established. + /// + /// This should be waited on prior to trusting the processes list. + public EventWaitHandle Connected => this.connected; + + /// + /// Gets a value indicating whether the client is active. + /// + public bool IsActive => this.active; + + /// + /// Gets the client address (available after connection established). + /// + public string ClientAddress => this.clientAddress; + + /// + /// Start rendezvous client (blocking until connection is established). + /// + public void Start() + { + if (this.active) + { + throw new Exception($"{nameof(RendezvousClient)} already started."); + } + + this.Rendezvous.ProcessAdded += this.ProcessAdded; + this.Rendezvous.ProcessRemoved += this.ProcessRemoved; + while (!this.active) + { + try + { + (this.client = new TcpClient()).Connect(this.serverAddress, this.port); + var stream = this.client.GetStream(); + this.reader = new BinaryReader(stream); + this.writer = new BinaryWriter(stream); + this.writer.Write(RendezvousServer.ProtocolVersion); + this.writer.Flush(); + this.active = true; + new Thread(new ThreadStart(this.ReadFromServer)) { IsBackground = true }.Start(); + } + catch (SocketException ex) + { + Trace.WriteLine($"Failed to connect to {nameof(RendezvousServer)} (retrying): {ex.Message}"); + } + } + } + + /// + /// Stop rendezvous client. + /// + public void Stop() + { + TryWriteDisconnect(this.writer); + this.Rendezvous.ProcessAdded -= this.ProcessAdded; + this.Rendezvous.ProcessRemoved -= this.ProcessRemoved; + this.active = false; + this.client?.Close(); + this.client?.Dispose(); + this.client = null; + this.reader?.Dispose(); + this.reader = null; + this.writer?.Dispose(); + this.writer = null; + } + + /// + public void Dispose() + { + this.Stop(); + this.connected.Dispose(); + } + + private void ReadFromServer() + { + try + { + var version = this.reader.ReadInt16(); + if (version != RendezvousServer.ProtocolVersion) + { + var ex = new IOException($"{nameof(RendezvousServer)} protocol mismatch ({version})"); + this.ServerError(ex); + throw ex; + } + + this.clientAddress = this.reader.ReadString(); + + // initialize processes before signaling connected + var count = this.reader.ReadInt32(); + for (var i = 0; i < count; i++) + { + if (!this.ReadProcessUpdate(this.reader)) + { + this.ServerError(new IOException($"{nameof(RendezvousServer)} disconnected.")); + } + } + + this.connected.Set(); + + do + { + if (!this.ReadProcessUpdate(this.reader)) + { + this.ServerError(new IOException($"{nameof(RendezvousServer)} disconnected.")); + } + } + while (this.active && this.client.Connected); + } + catch (Exception ex) + { + this.ServerError(ex); + this.connected.Reset(); + } + } + + private void NotifyServer(Rendezvous.Process process, Action action) + { + try + { + action(process, this.writer); + } + catch (Exception ex) + { + this.ServerError(ex); + } + } + + private void ProcessAdded(object sender, Rendezvous.Process process) + { + if (this.writer != null) + { + this.NotifyServer(process, WriteAddProcess); + } + } + + private void ProcessRemoved(object sender, Rendezvous.Process process) + { + if (this.writer != null) + { + this.NotifyServer(process, WriteRemoveProcess); + } + } + + private void ServerError(Exception ex) + { + Trace.WriteLine($"{nameof(RendezvousServer)} error: {ex.Message}"); + this.Stop(); + this.OnError(ex); + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.py b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.py new file mode 100644 index 000000000..0b20b67ad --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousClient.py @@ -0,0 +1,212 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +import socket, struct, threading +from enum import IntEnum + +# Client which connects to a RendezvousServer and relays rendezvous information. +class RendezvousClient: + PROTOCOL_VERSION = 2 + + def __init__(self, host, port = 13331): + self.serverAddress = (host, port) + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + def __sendByte(self, b): + self.socket.send(struct.pack('b', b)) + + def __readByte(self): + b, = struct.unpack('b', self.socket.recv(1)) + return b + + def __sendInt(self, c): + self.socket.send(struct.pack(' + /// Base class for and . + /// + public abstract class RendezvousRelay + { + /// + /// Initializes a new instance of the class. + /// + /// Optional rendezvous instance to relay. + public RendezvousRelay(Rendezvous rendezvous = null) + { + this.Rendezvous = rendezvous ?? new Rendezvous(); + } + + /// + /// Event raised when errors occur. + /// + public event EventHandler Error; + + /// + /// Gets the underlying rendezvous. + /// + public Rendezvous Rendezvous { get; private set; } + + /// + /// Write update to add process. + /// + /// Process to add. + /// Writer to which to write update. + protected static void WriteAddProcess(Rendezvous.Process process, BinaryWriter writer) + { + writer.Write((byte)1); // add + writer.Write(process.Name); + writer.Write(process.Version); + writer.Write(process.Endpoints.Count()); + foreach (var endpoint in process.Endpoints) + { + if (endpoint is Rendezvous.TcpSourceEndpoint tcpEndpoint) + { + writer.Write((byte)0); // TcpEndpoint + writer.Write(tcpEndpoint.Host); + writer.Write(tcpEndpoint.Port); + } + else if (endpoint is Rendezvous.NetMQSourceEndpoint netMQEndpoint) + { + writer.Write((byte)1); // NetMQEndpoint + writer.Write(netMQEndpoint.Address); + } + else if (endpoint is Rendezvous.RemoteExporterEndpoint remoteExporterEndpoint) + { + writer.Write((byte)2); // RemoteExporterEndpoint + writer.Write(remoteExporterEndpoint.Host); + writer.Write(remoteExporterEndpoint.Port); + writer.Write((int)remoteExporterEndpoint.Transport); + } + else if (endpoint is Rendezvous.RemoteClockExporterEndpoint remoteClockExporterEndpoint) + { + writer.Write((byte)3); // RemoteClockExporterEndpoint + writer.Write(remoteClockExporterEndpoint.Host); + writer.Write(remoteClockExporterEndpoint.Port); + } + else + { + throw new ArgumentException($"Unknown type of Endpoint ({endpoint.GetType().Name})."); + } + + writer.Write(endpoint.Streams.Count()); + foreach (var stream in endpoint.Streams) + { + writer.Write(stream.StreamName); + writer.Write(stream.TypeName); + } + } + + writer.Flush(); + } + + /// + /// Write update to remove process. + /// + /// Process to remove. + /// Writer to which to write update. + protected static void WriteRemoveProcess(Rendezvous.Process process, BinaryWriter writer) + { + writer.Write((byte)2); // remove + writer.Write(process.Name); + writer.Flush(); + } + + /// + /// Write disconnection signal.. + /// + /// Writer to which to write disconnection signal. + protected static void TryWriteDisconnect(BinaryWriter writer) + { + try + { + writer?.Write((byte)0); // disconnect + writer?.Flush(); + } + catch + { + } + } + + /// + /// Raise error event. + /// + /// Underlying exception. + protected void OnError(Exception ex) + { + this.Error?.Invoke(this, ex); + } + + /// + /// Read process update record. + /// + /// Reader from which to read. + /// A value indicating whether an update was read, otherwise false indicated disconnection. + protected bool ReadProcessUpdate(BinaryReader reader) + { + try + { + switch (reader.ReadByte()) + { + case 0: // disconnect + return false; + case 1: // add process + var process = ReadProcess(reader); + this.Rendezvous.TryAddProcess(process); + return true; + case 2: // remove process + var name = reader.ReadString(); + this.Rendezvous.TryRemoveProcess(name); + return true; + default: + throw new Exception("Unexpected rendezvous action."); + } + } + catch (Exception ex) + { + this.OnError(ex); + return false; + } + } + + /// + /// Read process. + /// + /// Reader from which to deserialize. + /// Process. + private static Rendezvous.Process ReadProcess(BinaryReader reader) + { + var processName = reader.ReadString(); + var processVersion = reader.ReadString(); + var process = new Rendezvous.Process(processName, processVersion); + + // read endpoint info + var endpointCount = reader.ReadInt32(); + for (var i = 0; i < endpointCount; i++) + { + Rendezvous.Endpoint endpoint; + switch (reader.ReadByte()) + { + case 0: // TcpEndpoint + var address = reader.ReadString(); + var port = reader.ReadInt32(); + endpoint = new Rendezvous.TcpSourceEndpoint(address, port); + break; + case 1: // NetMQEndpoint + endpoint = new Rendezvous.NetMQSourceEndpoint(reader.ReadString()); + break; + case 2: // RemoteExporterEndpoint + var host = reader.ReadString(); + port = reader.ReadInt32(); + var transport = (TransportKind)reader.ReadInt32(); + endpoint = new Rendezvous.RemoteExporterEndpoint(host, port, transport); + break; + case 3: // RemoteClockExporerEndpoint + host = reader.ReadString(); + port = reader.ReadInt32(); + endpoint = new Rendezvous.RemoteClockExporterEndpoint(host, port); + break; + default: + throw new Exception("Unknown type of Endpoint."); + } + + // read stream info + var streamCount = reader.ReadInt32(); + for (var j = 0; j < streamCount; j++) + { + var name = reader.ReadString(); + var typeName = reader.ReadString(); + endpoint.AddStream(new Rendezvous.Stream(name, typeName)); + } + + process.AddEndpoint(endpoint); + } + + return process; + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousServer.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousServer.cs new file mode 100644 index 000000000..48bb9eacf --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Rendezvous/RendezvousServer.cs @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Rendezvous +{ + using System; + using System.Collections.Concurrent; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Net; + using System.Net.Sockets; + using System.Threading; + + /// + /// Server which accepts one or more connections and relays information. + /// + public class RendezvousServer : RendezvousRelay, IDisposable + { + /// + /// Default TCP port on which to listen for clients. + /// + public const int DefaultPort = 13331; + + /// + /// Protocol version. + /// + internal const short ProtocolVersion = 2; + + private readonly int port; + private readonly ConcurrentDictionary writers = new (); + + private TcpListener listener; + private bool active = false; + + /// + /// Initializes a new instance of the class. + /// + /// Optional TCP port on which to listen for clients. + /// Optional rendezvous instance to relay. + public RendezvousServer(int port = DefaultPort, Rendezvous rendezvous = null) + : base(rendezvous) + { + this.port = port; + } + + /// + /// Gets a value indicating whether the server is active. + /// + public bool IsActive => this.active; + + /// + /// Start rendezvous client (blocking until connection is established). + /// + public void Start() + { + if (this.active) + { + throw new Exception($"{nameof(RendezvousServer)} already started."); + } + + this.Rendezvous.ProcessAdded += (_, process) => this.NotifyClients(process, WriteAddProcess); + this.Rendezvous.ProcessRemoved += (_, process) => this.NotifyClients(process, WriteRemoveProcess); + this.listener = new TcpListener(IPAddress.Any, this.port); + this.active = true; + new Thread(new ThreadStart(this.ListenForClients)) { IsBackground = true }.Start(); + } + + /// + /// Stop rendezvous client. + /// + public void Stop() + { + this.active = false; + + foreach (var writer in this.writers.Values) + { + TryWriteDisconnect(writer); + writer.Dispose(); + } + + this.listener?.Stop(); + this.listener = null; + } + + /// + public void Dispose() + { + this.Stop(); + } + + private void ListenForClients() + { + this.listener.Start(); + do + { + try + { + var client = this.listener.AcceptTcpClient(); + var remoteAddress = client.Client.RemoteEndPoint.ToString().Split(':')[0]; + var stream = client.GetStream(); + var reader = new BinaryReader(stream); + var version = reader.ReadInt16(); + if (version != ProtocolVersion) + { + var ex = new IOException($"{nameof(RendezvousClient)} protocol mismatch ({version})"); + this.ClientError(ex); + continue; + } + + var writer = new BinaryWriter(stream); + var guid = Guid.NewGuid(); + this.writers.TryAdd(guid, writer); + + writer.Write(ProtocolVersion); + writer.Write(remoteAddress); + writer.Write(this.Rendezvous.Processes.Count()); + writer.Flush(); + + // notify client of curent process info + foreach (var process in this.Rendezvous.Processes) + { + WriteAddProcess(process, writer); + } + + new Thread(new ParameterizedThreadStart(this.ReadFromClient)) { IsBackground = true } + .Start(Tuple.Create(reader, guid)); + } + catch (Exception ex) + { + this.ClientError(ex); + } + } + while (this.active && this.listener != null); + } + + private void ReadFromClient(object param) + { + var tuple = param as Tuple; + var reader = tuple.Item1; + var guid = tuple.Item2; + try + { + do + { + if (!this.ReadProcessUpdate(reader)) + { + Trace.WriteLine($"{nameof(RendezvousClient)} disconnected."); + break; + } + } + while (this.active && this.listener != null); + } + catch (Exception ex) + { + this.ClientError(ex); + } + + reader.Dispose(); + if (this.writers.TryRemove(guid, out var writer)) + { + writer.Dispose(); + } + } + + private void NotifyClients(Rendezvous.Process process, Action action) + { + foreach (var kv in this.writers) + { + var writer = kv.Value; + try + { + if (writer.BaseStream.CanWrite) + { + action(process, writer); + } + } + catch (Exception ex) + { + this.ClientError(ex); + if (this.writers.TryRemove(kv.Key, out _)) + { + writer.Dispose(); + } + } + } + } + + private void ClientError(Exception ex) + { + Trace.WriteLine($"{nameof(RendezvousClient)} failed to connect: {ex.Message}"); + if (this.active) + { + this.OnError(ex); // note: only invoked on first error + } + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Format{T}.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Format{T}.cs new file mode 100644 index 000000000..bd13414b9 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Format{T}.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Serialization +{ + using System; + using System.IO; + using System.Text; + + /// + /// Helper class for making new formats (implementations of /. + /// + /// Type which is serialized/deserialized. + public class Format : IFormatSerializer, IFormatDeserializer, IDisposable + { + private readonly Func serialize; + private readonly Func deserialize; + private readonly MemoryStream memoryStream = null; + + /// + /// Initializes a new instance of the class. + /// + /// Serialization function. + /// Deserialization function. + public Format( + Func serializeFunc, + Func deserializeFunc) + { + this.serialize = serializeFunc; + this.deserialize = deserializeFunc; + } + + /// + /// Initializes a new instance of the class. + /// + /// Action to serialize using . + /// Function to deserialize using (also given raw payload, offset, length). + /// Serialization format. + public Format( + Action serializeAction, + Func deserializeFunc) + { + this.memoryStream = new MemoryStream(); + + this.serialize = (val, originatingTime) => + { + this.memoryStream.Position = 0; + using var writer = new BinaryWriter(this.memoryStream, Encoding.UTF8, true); + writer.Write(originatingTime.ToFileTimeUtc()); + serializeAction(val, writer); + return (this.memoryStream.GetBuffer(), 0, (int)this.memoryStream.Length); + }; + + this.deserialize = (payload, offset, length) => + { + using var reader = new BinaryReader(new MemoryStream(payload, offset, length), Encoding.UTF8); + var originatingTime = DateTime.FromFileTimeUtc(reader.ReadInt64()); + var val = deserializeFunc(reader, payload, offset, length); + return (val, originatingTime); + }; + } + + /// + /// Initializes a new instance of the class. + /// + /// Action to serialize using . + /// Function to deserialize using (also given raw payload, offset, length). + /// Serialization format. + public Format( + Action serializeAction, + Func deserializeFunc) + : this(serializeAction, (reader, _, _, _) => deserializeFunc(reader)) + { + } + + /// + public (byte[] Bytes, int Index, int Count) SerializeMessage(T message, DateTime originatingTime) + { + return this.serialize(message, originatingTime); + } + + /// + public (T Message, DateTime OriginatingTime) DeserializeMessage(byte[] payload, int index, int count) + { + return this.deserialize(payload, index, count); + } + + /// + public void Dispose() + { + if (this.memoryStream != null) + { + this.memoryStream.Dispose(); + } + } + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatDeserializer.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatDeserializer.cs new file mode 100644 index 000000000..502685840 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatDeserializer.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Serialization +{ + using System; + + /// + /// Format deserializer interface. + /// + /// Type which is deserialized. + public interface IFormatDeserializer + { + /// + /// Deserialize single message and originating time stamp payload. + /// + /// Payload bytes. + /// Starting index of message data. + /// Number of bytes constituting message data. + /// Dynamic of primitive or IEnumerable/ExpandoObject of primitive as well as originating time stamp. + (T Message, DateTime OriginatingTime) DeserializeMessage(byte[] payload, int index, int count); + } +} \ No newline at end of file diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatSerializer.cs b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatSerializer.cs new file mode 100644 index 000000000..270487513 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/IFormatSerializer.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Psi.Interop.Serialization +{ + using System; + + /// + /// Format serializer interface. + /// + /// Type which is serialized. + public interface IFormatSerializer + { + /// + /// Serialize single message with originating time stamp. + /// + /// Message of any type. + /// Originating time of message. + /// Serialized bytes, index and count. + (byte[] Bytes, int Index, int Count) SerializeMessage(T message, DateTime originatingTime); + } +} diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Readme.md b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Readme.md new file mode 100644 index 000000000..49c5be8d4 --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Serialization/Readme.md @@ -0,0 +1,45 @@ +# Interop Serialization Interfaces + +Each [concrete format](../Format/Readme.md) is an implementation of several serialization interfaces. These interfaces are similar to `Microsoft.Psi.Serialization.ISerializer` but are specific to dynamic types and don't include cloning. An `IFormatSerializer` converts a message of any type, along with its originating time, to a simple `byte[]`, while an `IFormatDeserializer` reverses the process; taking a `byte[]` and returning a message and originating time. + +```csharp +public interface IFormatSerializer +{ + (byte[], int, int) SerializeMessage(dynamic message, DateTime originatingTime); +} + +public interface IFormatDeserializer +{ + (dynamic, DateTime) DeserializeMessage(byte[] payload, int index, int count); +} +``` + +Versions of these intended for persistent storage, where a sequence of messages are persisted together, are provided as well. + +```csharp +public interface IPersistentFormatSerializer +{ + dynamic PersistHeader(dynamic message, Stream stream); + + void PersistRecord(dynamic message, DateTime originatingTime, bool first, Stream stream, dynamic state); + + void PersistFooter(Stream stream, dynamic state); +} + +public interface IPersistentFormatDeserializer +{ + IEnumerable<(dynamic, DateTime)> DeserializeRecords(Stream stream); +} +``` + +`IPersistentFormatSerializer` writes a set of messages to a `Stream`. The header may be field names in the case of CSV, a simple array container in the case of JSON, etc. Similarly, the footer may close such constructs. The `PersistRecord` method is very similar to `SerializeMessage` above, but may include message framing or delimiting, such as `Environment.NewLine` delimiting records in CSV or a comma for JSON, or maybe a length-prefix for binary MessagePack. The `IPersistentFormatDeserializer` reverses the process; producing messages and timestamps from a previously serialized stream. + +Notice that messages lose their types at this point; generally becoming `dynamic` over `ExpandoObject` and primitives. This means that it may no longer be possible to reify as the original .NET types after serialization in this way (unlike with Psi Stores). + +Note also that, while `dynamic` may be any type, it is recommended that deserialization returns primitives or composites in the form of `ExpandoObject`. For example, the JSON implementation uses `Newtonsoft.Json.JsonConvert` under the covers but, rather than returning `JObject`, is careful to not expose dependencies on this library. + +## Note About `dynamic` and `ExpandoObject` + +A `dynamic` type may be *anything* in .NET and an `ExpandoObject` may have properties of *any* type. We are using these types to represent untyped values flowing through the system in various places above. + +Composite/structured values should be restricted to collections (arrays or `IEnumerable<_>`) of primitives or other composites or `ExpandoObject` of named properties of primitives or other composites. Any "shape" of data is representable this way. \ No newline at end of file diff --git a/Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/Readme.md b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/Readme.md new file mode 100644 index 000000000..ae0a50b4f --- /dev/null +++ b/Sources/Runtime/Microsoft.Psi.InteropAndroid/Transport/Readme.md @@ -0,0 +1,167 @@ +# Interop Transports + +Here we describe several ways of getting data in and out of Psi in order to interop with other languages and platforms. + +## Generic File Source/Writer Component + +The simplest transport is via the file system. This is most appropriate for offline/batch processing. A generic `FileWriter` component is provided that, when given an `IPersistentFormatSerializer`, will persist a message stream to disk. Similarly, a generic `FileSource` component is provided, taking an `IPersistentFormatDeserializer`, to reconstitute such a persisted file as a Psi stream. + +For example, a stream of messages of any type may be written using the `FileWriter`: + +```csharp +using (var p = Pipeline.Create()) +{ + var gen = Generators.Range(p, 0, 1000); + var sin = gen.Select(x => Math.Sin(x / 100.0)); + var writer = new FileWriter(p, "TestFile.json", JsonFormat.Instance); + sin.PipeTo(writer); + p.Run(); +} +``` + +This produces a JSON file containing something like: + +```json +[ + { + "originatingTime": "2018-11-12T22:48:58.3770983Z", + "message": 0.0 + }, + { + "originatingTime": "2018-11-12T22:48:58.3770984Z", + "message": 0.0099998333341666645 + }, + { + "originatingTime": "2018-11-12T22:48:58.3770985Z", + "message": 0.01999866669333308 + }, + ... +] +``` + +This may then be read back into a proper \\psi stream using a `FileSource`: + +```csharp +using (var p = Pipeline.Create()) +{ + var reader = new FileSource(p, "TestFile.json", JsonFormat.Instance); + reader.Do(Console.WriteLine); + p.Run(); +} +``` + +## Message Queue Components + +Message queues are most appropriate for live interop. Currently, only ZeroMQ is supported. In the future, Azure Storage Queue and/or Service Bus as well as Amazon SMQ may be supported. While the Psi `RemoteExporter`/`Importer` is an excellent, high performance means of remoting, it assumes .NET on both ends. To facilitate remoting to Python and others, we provide message queuing components. These components are `IConsumer` and simply push to a message queue or are `IProducer` and take messages from a queue. Given an `IFormatSerializer`/`Deserializer`, they handle packing/unpacking messages. + +### ZeroMQ/NetMQ + +An implementation for ZeroMQ (calleg NetMQ for .NET) is provided. These components are configured with a URI, a topic name and an `IFormatSerializer`. + +#### `NetMQWriter` + +A stream of messages of any type may be piped to a `NetMQWriter`. These will be serialized and sent to the queue for consumption outside of Psi. + +```csharp +using (var p = Pipeline.Create()) +{ + var gen = Generators.Range(p, 0, 1000); + var sin = gen.Select(x => Math.Sin(x / 100.0)); + var mq = new NetMQWriter(p, "sin-topic", "tcp://localhost:12345", JsonFormat.Instance); + sin.PipeTo(mq); + p.Run(); +} +``` + +This component uses the [NetMQ Pub/Sub](https://netmq.readthedocs.io/en/latest/pub-sub/) pattern, in which messages convey _topic_ information (much like ROS). Subscribers may then subscribe by topic name. + +The generic `NetMQWriter` component has a single `In` receiver which sends to the topic specified at construction. This is the most common case. To facilitate multiple topics over one channel, the `AddTopic(...)` method may be called; returning an additional `IReceiver` to which to pipe. + +```csharp + var cos = gen.Select(x => Math.Cos(x / 100.0)); + var topic = mq.AddTopic("cos-topic"); + cos.PipeTo(topic); +``` + +Alternatively, the non-generic `NetMQWriter` may be used, which has _no_ receivers. Each must be created with `AddTopic(...)`. + +```csharp +using (var p = Pipeline.Create()) +{ + var gen = Generators.Range(p, 0, 1000); + var sin = gen.Select(x => Math.Sin(x / 100.0)); + var cos = gen.Select(x => Math.Cos(x / 100.0)); + + var mq = new NetMQWriter(p, "sin-topic", "tcp://localhost:12345", JsonFormat.Instance); + sin.PipeTo(mq.AddTopic("sin-topic"); + cos.PipeTo(mq.AddTopic("cos-topic"); + + p.Run(); +} +``` + +Then from Python, for example, messages may be consumed using `pyzmq` with something like: + +```python +import zmq, json + +socket = zmq.Context().socket(zmq.SUB) +socket.connect("tcp://localhost:12345") +socket.setsockopt(zmq.SUBSCRIBE, '') # '' means all topics, otherwise 'sin-topic'/'cos-topic' + +while True: + [topic, message] = socket.recv_multipart() + j = json.loads(message) + print "Message: ", repr(j['message']) + print "Originating Time: ", repr(j['originatingTime']) +``` + +#### `NetMQSource` + +Psi may also consume message that have been produced from "outside." For example, the below Python code produces an infinite stream of random doubles: + +```python +import zmq, random, datetime, json + +context = zmq.Context() +socket = context.socket(zmq.PUB) +socket.bind('tcp://127.0.0.1:45678') + +while True: + payload = {} + payload['message'] = random.uniform(0, 1) + payload['originatingTime'] = datetime.datetime.utcnow().isoformat() + socket.send_multipart(['test-topic'.encode(), json.dumps(payload).encode('utf-8')]) +``` + +Notice that the [Pub/Sub](https://netmq.readthedocs.io/en/latest/pub-sub/) pattern is expected here as well; using `socket.send_multipart` with a topic name and the JSON-encoded data. Also notice that the schema must match that expected by the `JsonFormat` `IFormatDeserializer` described above: + +```json +{ "message": , "originatingTime":