Exemple #1
0
 public async Task ConnectToNewBrokerAsync(CancellationToken cancellationToken)
 {
     using (_session._disposeToken.Link(ref cancellationToken)) {
         var connectionInfo = new HostConnectionInfo(_session.Name, _session, _session._startupInfo.UseRHostCommandLineArguments);
         _hostToSwitch = await _session.BrokerClient.ConnectAsync(connectionInfo, cancellationToken);
     }
 }
Exemple #2
0
        private static async Task StopHostAsync(IBrokerClient brokerClient, RHost host, Task hostRunTask, bool waitForShutdown)
        {
            // Try graceful shutdown with q() first.
            if (waitForShutdown)
            {
                try {
                    host.QuitAsync().SilenceException <Exception>().DoNotWait();
                    await Task.WhenAny(hostRunTask, Task.Delay(10000)).Unwrap();
                } catch (Exception) { }

                if (hostRunTask.IsCompleted)
                {
                    return;
                }
            }

            // If it didn't work, tell the broker to forcibly terminate the host process.
            try {
                brokerClient.TerminateSessionAsync(host.Name).Wait(10000);
            } catch (Exception) { }

            if (hostRunTask.IsCompleted)
            {
                return;
            }

            if (host != null)
            {
                // If nothing worked, then just disconnect.
                await host.DisconnectAsync();
            }

            await hostRunTask;
        }
Exemple #3
0
            public async Task ConnectToNewBrokerAsync(CancellationToken cancellationToken, ReentrancyToken reentrancyToken)
            {
                using (_session._disposeToken.Link(ref cancellationToken)) {
                    if (!VerifyTransactionState(nameof(ConnectToNewBrokerAsync)))
                    {
                        return;
                    }

                    var startupInfo = _session._startupInfo;
                    // host requires _startupInfo, so proceed only if session was started at least once
                    var connectionInfo = new BrokerConnectionInfo(startupInfo.Name, _session, startupInfo.RHostCommandLineArguments);
                    _hostToSwitch = await _session.BrokerClient.ConnectAsync(connectionInfo, cancellationToken, reentrancyToken);
                }
            }
Exemple #4
0
        private async Task StartHostAsyncBackground(RHostStartupInfo startupInfo, int timeout)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            _host = new RHost(startupInfo != null ? startupInfo.Name : "Empty", this);
            ClearPendingRequests();

            var initializationTask = _initializationTcs.Task;

            _hostRunTask = CreateAndRunHost(startupInfo, timeout);
            ScheduleAfterHostStarted(startupInfo);

            await initializationTask;
        }
Exemple #5
0
            public async Task CompleteSwitchingBrokerAsync(CancellationToken cancellationToken)
            {
                if (_lockToken == null)
                {
                    throw new InvalidOperationException($"{nameof(AcquireLockAsync)} must be called before {nameof(CompleteSwitchingBrokerAsync)}");
                }

                _session._disposeToken.ThrowIfDisposed();


                if (_session._startupInfo == null)
                {
                    // Session never started. No need to restart it.
                    // Reset _initializationLock so that next awaiter can proceed.
                    _lockToken.Reset();
                    return;
                }

                var brokerClient = _session.BrokerClient;
                var startupInfo  = _session._startupInfo;
                var host         = _session._host;
                var hostRunTask  = _session._hostRunTask;

                // host may be null if previous attempts to start it have failed
                if (host != null)
                {
                    // Detach RHost from RSession
                    host.DetachCallback();

                    // Cancel all current requests
                    await _session.CancelAllAsync(cancellationToken);
                }

                // Start new RHost
                await _session.StartHostAsyncBackground(_hostToSwitch, _lockToken, cancellationToken);

                // Shut down the old host, gracefully if possible, and wait for old hostRunTask to exit;
                if (hostRunTask != null)
                {
                    await StopHostAsync(brokerClient, startupInfo?.Name, host, hostRunTask);
                }
                host?.Dispose();

                if (hostRunTask != null && hostRunTask.Status == TaskStatus.Running)
                {
                    await hostRunTask;
                }

                _hostToSwitch = null;
            }
Exemple #6
0
 private static async Task RunHost(RHost host, TaskCompletionSourceEx <object> hostStartedTcs, CancellationToken initializationCt)
 {
     try {
         await host.Run(initializationCt);
     } catch (OperationCanceledException oce) {
         hostStartedTcs.TrySetCanceled(oce);
     } catch (MessageTransportException mte) {
         hostStartedTcs.TrySetCanceled(new RHostDisconnectedException(string.Empty, mte));
     } catch (Exception ex) {
         hostStartedTcs.TrySetException(ex);
     } finally {
         // RHost.Run shouldn't be completed before `IRCallback.Connected` is called
         hostStartedTcs.TrySetCanceled(new RHostDisconnectedException(Resources.Error_UnknownError));
     }
 }
Exemple #7
0
            public async Task CompleteSwitchingBrokerAsync(CancellationToken cancellationToken)
            {
                using (_session._disposeToken.Link(ref cancellationToken)) {
                    if (!VerifyTransactionState(nameof(ConnectToNewBrokerAsync)))
                    {
                        return;
                    }

                    if (_hostToSwitch == null)
                    {
                        Debugger.Launch();
                    }

                    try {
                        var brokerClient = _session.BrokerClient;
                        var startupInfo  = _session._startupInfo;
                        var host         = _session._host;
                        var hostRunTask  = _session._hostRunTask;

                        // host may be null if previous attempts to start it have failed
                        if (host != null)
                        {
                            // Detach RHost from RSession
                            host.DetachCallback();

                            // Cancel all current requests
                            await _session.CancelAllAsync(cancellationToken);
                        }

                        // Start new RHost
                        await _session.StartHostAsyncBackground(_hostToSwitch, _lockToken, cancellationToken);

                        // Shut down the old host, gracefully if possible, and wait for old hostRunTask to exit;
                        if (hostRunTask != null)
                        {
                            await StopHostAsync(brokerClient, startupInfo?.Name, host, hostRunTask);
                        }
                        host?.Dispose();

                        if (hostRunTask != null)
                        {
                            await hostRunTask;
                        }
                    } finally {
                        _hostToSwitch = null;
                    }
                }
            }
Exemple #8
0
        private async Task CreateAndRunHost(RHostStartupInfo startupInfo, int timeout)
        {
            try {
                _host = await BrokerConnector.ConnectAsync(startupInfo.Name, this, startupInfo.RHostCommandLineArguments, timeout);

                await _host.Run();
            } catch (OperationCanceledException oce) {
                _initializationTcs.TrySetCanceled(oce);
            } catch (MessageTransportException mte) {
                _initializationTcs.TrySetCanceled(new RHostDisconnectedException(string.Empty, mte));
            } catch (Exception ex) {
                _initializationTcs.TrySetException(ex);
            } finally {
                Interlocked.Exchange(ref _initializationTcs, null);
            }
        }
Exemple #9
0
            public async Task ConnectToNewBrokerAsync(CancellationToken cancellationToken, ReentrancyToken reentrancyToken)
            {
                if (_lockToken == null)
                {
                    throw new InvalidOperationException($"{nameof(AcquireLockAsync)} must be called before {nameof(ConnectToNewBrokerAsync)}");
                }

                _session._disposeToken.ThrowIfDisposed();
                var startupInfo = _session._startupInfo;

                if (startupInfo != null)
                {
                    // host requires _startupInfo, so proceed only if session was started at least once
                    _hostToSwitch = await _session.BrokerClient.ConnectAsync(startupInfo.Name, _session, startupInfo.RHostCommandLineArguments, cancellationToken : cancellationToken, reentrancyToken : reentrancyToken);
                }
            }
Exemple #10
0
        private async Task StartHostAsyncBackground(RHost host, IBinaryAsyncLockToken lockToken, CancellationToken cancellationToken = default(CancellationToken))
        {
            await TaskUtilities.SwitchToBackgroundThread();

            ResetInitializationTcs();
            ClearPendingRequests(new RHostDisconnectedException());

            Interlocked.Exchange(ref _host, host);
            var initializationCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            var hostRunTask       = RunHost(lockToken, initializationCts.Token);

            Interlocked.Exchange(ref _hostRunTask, hostRunTask)?.DoNotWait();

            await _initializationTcs.Task;

            initializationCts.Dispose();
            lockToken.Set();
        }
Exemple #11
0
        private async Task StartHostAsyncBackground(RHost host, CancellationToken cancellationToken = default(CancellationToken))
        {
            TaskUtilities.AssertIsOnBackgroundThread();

            ResetInitializationTcs();
            ClearPendingRequests(new RHostDisconnectedException());

            Interlocked.Exchange(ref _host, host);
            Interlocked.Exchange(ref _initializedTcs, new TaskCompletionSourceEx <object>());

            var initializationCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            var hostRunTask       = RunHost(_host, _hostStartedTcs, initializationCts.Token);

            Interlocked.Exchange(ref _hostRunTask, hostRunTask)?.DoNotWait();

            await _hostStartedTcs.Task;
            await _initializedTcs.Task;

            initializationCts.Dispose();
            _stopHostLock.EnqueueReset();
        }
Exemple #12
0
            public async Task CompleteSwitchingBrokerAsync(CancellationToken cancellationToken)
            {
                using (_session._disposeToken.Link(ref cancellationToken)) {
                    try {
                        var brokerClient = _session.BrokerClient;
                        var host         = _session._host;
                        var hostRunTask  = _session._hostRunTask;

                        // host may be null if previous attempts to start it have failed
                        if (host != null)
                        {
                            // Detach RHost from RSession
                            host.DetachCallback();

                            // Cancel all current requests
                            // If can't be canceled in 10s - just ignore, old host will be stopped later
                            await Task.WhenAny(_session.CancelAllAsync(cancellationToken), Task.Delay(10000, cancellationToken)).Unwrap();
                        }

                        // Start new RHost
                        await _session.StartHostAsyncBackground(_hostToSwitch, cancellationToken);

                        // Shut down the old host, gracefully if possible, and wait for old hostRunTask to exit;
                        if (hostRunTask != null && host != null)
                        {
                            await StopHostAsync(brokerClient, host, hostRunTask, true);
                        }
                        host?.Dispose();

                        if (hostRunTask != null)
                        {
                            await hostRunTask;
                        }
                    } finally {
                        _hostToSwitch = null;
                    }
                }
            }
Exemple #13
0
        private async Task StartHostAsyncBackground(RHostStartupInfo startupInfo, int timeout) {
            await TaskUtilities.SwitchToBackgroundThread();

            _host = new RHost(startupInfo != null ? startupInfo.Name : "Empty", this);
            ClearPendingRequests();

            var initializationTask = _initializationTcs.Task;
            _hostRunTask = CreateAndRunHost(startupInfo, timeout);
            ScheduleAfterHostStarted(startupInfo);

            await initializationTask;
        }
Exemple #14
0
        private static async Task StopHostAsync(IBrokerClient brokerClient, string hostName, RHost host, Task hostRunTask)
        {
            // Try graceful shutdown with q() first.
            if (host != null)
            {
                try {
                    await Task.WhenAny(hostRunTask, host.QuitAsync(), Task.Delay(500)).Unwrap();
                } catch (Exception) { }

                if (hostRunTask.IsCompleted)
                {
                    return;
                }
            }

            // If it didn't work, tell the broker to forcibly terminate the host process.
            if (hostName != null)
            {
                try {
                    await brokerClient.TerminateSessionAsync(hostName);
                } catch (Exception) { }

                if (hostRunTask.IsCompleted)
                {
                    return;
                }
            }

            if (host != null)
            {
                // If nothing worked, then just disconnect.
                await host.DisconnectAsync();
            }

            await hostRunTask;
        }