Beispiel #1
0
        /// <summary>
        /// Initialize the grain client. This should be already done by <see cref="Deploy()"/> or <see cref="DeployAsync"/>
        /// </summary>
        public void InitializeClient()
        {
            WriteLog("Initializing Cluster Client");

            this.InternalClient = (IInternalClusterClient)TestClusterHostFactory.CreateClusterClient("MainClient", this.ConfigurationSources);
            this.InternalClient.Connect().GetAwaiter().GetResult();
        }
Beispiel #2
0
        public static async Task Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Expected JSON-serialized configuration to be provided as an argument");
            }

            var monitorProcessId        = int.Parse(args[0], NumberStyles.Integer, CultureInfo.InvariantCulture);
            var serializedConfiguration = args[1];
            var configuration           = TestClusterHostFactory.DeserializeConfiguration(serializedConfiguration);
            var name = configuration["SiloName"];
            var host = TestClusterHostFactory.CreateSiloHost(name, configuration);
            var cts  = new CancellationTokenSource();

            Console.CancelKeyPress += (sender, eventArgs) => cts.Cancel();

            ListenForShutdownCommand(cts);
            MonitorParentProcess(monitorProcessId);

            await host.StartAsync(cts.Token);

            // This is a special marker line.
            var localSiloDetails = (ILocalSiloDetails)host.Services.GetService(typeof(ILocalSiloDetails));

            Console.WriteLine($"{SiloAddressLog}{localSiloDetails.SiloAddress.ToParsableString()}");
            Console.WriteLine($"{GatewayAddressLog}{localSiloDetails.GatewayAddress.ToParsableString()}");
            Console.WriteLine(StartedLog);

            await cts.Token.WhenCancelled();

            await host.StopAsync(CancellationToken.None);
        }
        /// <summary>Creates and initializes a silo in the current app domain.</summary>
        /// <param name="appDomainName">Name of this silo.</param>
        /// <param name="serializedConfigurationSources">Silo config data to be used for this silo.</param>
        public AppDomainSiloHost(string appDomainName, string serializedConfigurationSources)
        {
            var deserializedSources = TestClusterHostFactory.DeserializeConfigurationSources(serializedConfigurationSources);

            this.host = TestClusterHostFactory.CreateSiloHost(appDomainName, deserializedSources);
            this.AppDomainTestHook = new AppDomainTestHooks(this.host);
        }
Beispiel #4
0
        /// <summary>
        /// Initialize the grain client. This should be already done by <see cref="Deploy()"/> or <see cref="DeployAsync"/>
        /// </summary>
        public void InitializeClient()
        {
            WriteLog("Initializing Cluster Client");

            this.InternalClient = (IInternalClusterClient)TestClusterHostFactory.CreateClusterClient("MainClient", this.ConfigurationSources);
            this.InternalClient.Connect().GetAwaiter().GetResult();
            this.SerializationManager = this.ServiceProvider.GetRequiredService <SerializationManager>();
        }
Beispiel #5
0
        /// <summary>Creates and initializes a silo in the current app domain.</summary>
        /// <param name="appDomainName">Name of this silo.</param>
        /// <param name="serializedConfigurationSources">Silo config data to be used for this silo.</param>
        public AppDomainSiloHost(string appDomainName, string serializedConfigurationSources)
        {
            // Force TLS 1.2. It should be done by TestUtils.CheckForAzureStorage and TestUtils.CheckForEventHub,
            // but they will not have any effect here since this silo will run on a different AppDomain
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var deserializedSources = TestClusterHostFactory.DeserializeConfigurationSources(serializedConfigurationSources);

            this.host = TestClusterHostFactory.CreateSiloHost(appDomainName, deserializedSources);
        }
Beispiel #6
0
        private static Task <SiloHandle> Create(
            string siloName,
            IList <IConfigurationSource> configurationSources,
            Assembly[] assemblies)
        {
            var configBuilder = new ConfigurationBuilder();

            foreach (var source in configurationSources)
            {
                configBuilder.Add(source);
            }
            var configuration = configBuilder.Build();

            var            applicationBase = configuration[nameof(TestClusterOptions.ApplicationBaseDirectory)];
            AppDomainSetup setup           = GetAppDomainSetupInfo(applicationBase);

            var appDomain = AppDomain.CreateDomain(siloName, null, setup);

            try
            {
                var asms = (assemblies ?? Array.Empty <Assembly>()).Select(asm => asm.GetName().Name).ToArray();
                var serializedHostConfiguration = TestClusterHostFactory.SerializeConfigurationSources(configurationSources);
                var args = new object[] { siloName, serializedHostConfiguration, asms };

                var siloHost = (AppDomainSiloHost)appDomain.CreateInstanceAndUnwrap(
                    typeof(AppDomainSiloHost).Assembly.FullName,
                    typeof(AppDomainSiloHost).FullName,
                    false,
                    BindingFlags.Default,
                    null,
                    args,
                    CultureInfo.CurrentCulture,
                    new object[] { });

                appDomain.UnhandledException += ReportUnobservedException;

                siloHost.Start();

                SiloHandle retValue = new AppDomainSiloHandle
                {
                    Name           = siloName,
                    SiloHost       = siloHost,
                    SiloAddress    = siloHost.SiloAddress,
                    GatewayAddress = siloHost.GatewayAddress,
                    AppDomain      = appDomain,
                };

                return(Task.FromResult(retValue));
            }
            catch (Exception)
            {
                UnloadAppDomain(appDomain);
                throw;
            }
        }
Beispiel #7
0
        /// <summary>Creates a new silo in a remote app domain and returns a handle to it.</summary>
        public static SiloHandle Create(
            string siloName,
            IList <IConfigurationSource> configurationSources)
        {
            var configBuilder = new ConfigurationBuilder();

            foreach (var source in configurationSources)
            {
                configBuilder.Add(source);
            }
            var configuration = configBuilder.Build();

            var            applicationBase = configuration[nameof(TestClusterOptions.ApplicationBaseDirectory)];
            AppDomainSetup setup           = GetAppDomainSetupInfo(applicationBase);

            var appDomain = AppDomain.CreateDomain(siloName, null, setup);

            try
            {
                var serializedHostConfiguration = TestClusterHostFactory.SerializeConfigurationSources(configurationSources);
                var args = new object[] { siloName, serializedHostConfiguration };

                var siloHost = (AppDomainSiloHost)appDomain.CreateInstanceAndUnwrap(
                    typeof(AppDomainSiloHost).Assembly.FullName,
                    typeof(AppDomainSiloHost).FullName,
                    false,
                    BindingFlags.Default,
                    null,
                    args,
                    CultureInfo.CurrentCulture,
                    new object[] { });

                appDomain.UnhandledException += ReportUnobservedException;

                siloHost.Start();

                var retValue = new AppDomainSiloHandle
                {
                    Name              = siloName,
                    SiloHost          = siloHost,
                    SiloAddress       = siloHost.SiloAddress,
                    GatewayAddress    = siloHost.GatewayAddress,
                    AppDomain         = appDomain,
                    AppDomainTestHook = siloHost.AppDomainTestHook,
                };

                return(retValue);
            }
            catch (Exception)
            {
                UnloadAppDomain(appDomain);
                throw;
            }
        }
Beispiel #8
0
        /// <summary>
        /// Initialize the grain client. This should be already done by <see cref="Deploy()"/> or <see cref="DeployAsync"/>
        /// </summary>
        public async Task InitializeClientAsync()
        {
            WriteLog("Initializing Cluster Client");

            if (ClientHost is not null)
            {
                await StopClusterClientAsync();
            }

            this.ClientHost = TestClusterHostFactory.CreateClusterClient("MainClient", this.ConfigurationSources);
            await this.ClientHost.StartAsync();
        }
        /// <summary>Creates a new silo and returns a handle to it.</summary>
        /// <param name="siloName">The name for the new silo.</param>
        /// <param name="configurationSources">
        /// The configuration sources, interpreted by <see cref="TestClusterHostFactory.CreateSiloHost"/>.
        /// </param>
        public static async Task <SiloHandle> CreateAsync(
            string siloName,
            IList <IConfigurationSource> configurationSources)
        {
            var host = TestClusterHostFactory.CreateSiloHost(siloName, configurationSources);
            await host.StartAsync();

            var retValue = new InProcessSiloHandle
            {
                Name           = siloName,
                SiloHost       = host,
                SiloAddress    = host.Services.GetRequiredService <ILocalSiloDetails>().SiloAddress,
                GatewayAddress = host.Services.GetRequiredService <ILocalSiloDetails>().GatewayAddress,
            };

            return(retValue);
        }
        /// <summary>
        /// Create a silo handle.
        /// </summary>
        /// <param name="siloName">Name of the silo.</param>
        /// <param name="configuration">The configuration.</param>
        /// <param name="postConfigureHostBuilder">An optional delegate which is invoked just prior to building the host builder.</param>
        /// <returns>The silo handle.</returns>
        public static async Task <SiloHandle> CreateAsync(
            string siloName,
            IConfiguration configuration,
            Action <IHostBuilder> postConfigureHostBuilder = null)
        {
            var host = await Task.Run(async() =>
            {
                var result = TestClusterHostFactory.CreateSiloHost(siloName, configuration, postConfigureHostBuilder);
                await result.StartAsync();
                return(result);
            });

            var retValue = new InProcessSiloHandle
            {
                Name           = siloName,
                SiloHost       = host,
                SiloAddress    = host.Services.GetRequiredService <ILocalSiloDetails>().SiloAddress,
                GatewayAddress = host.Services.GetRequiredService <ILocalSiloDetails>().GatewayAddress,
            };

            return(retValue);
        }
Beispiel #11
0
        public StandaloneSiloHandle(string siloName, IConfiguration configuration, string executablePath)
        {
            if (string.IsNullOrWhiteSpace(executablePath) || !File.Exists(executablePath))
            {
                throw new ArgumentException("Must provide at least one assembly path");
            }

            Name = siloName;

            // If the debugger is attached to this process, give it an opportunity to attach to the remote process.
            if (Debugger.IsAttached)
            {
                configuration["AttachDebugger"] = "true";
            }

            var serializedConfiguration = TestClusterHostFactory.SerializeConfiguration(configuration);

            Process           = new Process();
            Process.StartInfo = new ProcessStartInfo(executablePath)
            {
                ArgumentList           = { Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture), serializedConfiguration },
                CreateNoWindow         = true,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                RedirectStandardInput  = true,
                WorkingDirectory       = new FileInfo(executablePath).Directory.FullName,
                UseShellExecute        = false,
            };

            _outputBuilder    = new StringBuilder();
            _outputCloseEvent = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            _startedEvent     = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            Process.OutputDataReceived += (s, e) =>
            {
                if (e.Data == null)
                {
                    _outputCloseEvent.SetResult(true);
                }
                else
                {
                    // Read standard output from the process for status updates.
                    if (!_startedEvent.Task.IsCompleted)
                    {
                        if (e.Data.StartsWith(StandaloneSiloHost.SiloAddressLog, StringComparison.Ordinal))
                        {
                            SiloAddress = Orleans.Runtime.SiloAddress.FromParsableString(e.Data.Substring(StandaloneSiloHost.SiloAddressLog.Length));
                        }
                        else if (e.Data.StartsWith(StandaloneSiloHost.GatewayAddressLog, StringComparison.Ordinal))
                        {
                            GatewayAddress = Orleans.Runtime.SiloAddress.FromParsableString(e.Data.Substring(StandaloneSiloHost.GatewayAddressLog.Length));
                        }
                        else if (e.Data.StartsWith(StandaloneSiloHost.StartedLog, StringComparison.Ordinal))
                        {
                            _startedEvent.TrySetResult(true);
                        }
                    }

                    lock (_outputBuilder)
                    {
                        _outputBuilder.AppendLine(e.Data);
                    }
                }
            };

            _errorBuilder    = new StringBuilder();
            _errorCloseEvent = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            Process.ErrorDataReceived += (s, e) =>
            {
                if (e.Data == null)
                {
                    _errorCloseEvent.SetResult(true);
                }
                else
                {
                    lock (_errorBuilder)
                    {
                        _errorBuilder.AppendLine(e.Data);
                    }
                }
            };

            var selfReference = new WeakReference <StandaloneSiloHandle>(this);

            _processExitHandler = (o, e) =>
            {
                if (selfReference.TryGetTarget(out var target))
                {
                    try
                    {
                        target.Process.Kill(entireProcessTree: true);
                    }
                    catch
                    {
                    }
                }
            };
            AppDomain.CurrentDomain.ProcessExit += _processExitHandler;
        }