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); } }
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; }
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); } }
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; }
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; }
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)); } }
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; } } }
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); } }
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); } }
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(); }
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(); }
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; } } }
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; }