private void AddNewEndpoint(EndpointId endpoint, IEnumerable <Type> commandTypes) { if (commandTypes.Contains(typeof(IDatasetActivationCommands))) { lock (m_Lock) { if (!m_ActivatorCommands.ContainsKey(endpoint)) { IDatasetActivationCommands command = null; try { command = m_CommandHub.CommandsFor <IDatasetActivationCommands>(endpoint); } catch (CommandNotSupportedException) { // Secretly we actually don't have the command so just ignore this // endpoint. This could be caused by the endpoint disappearing or // some other networky problem. } if (command != null) { m_ActivatorCommands.Add(endpoint, command); } } } } }
/// <summary> /// Sends an echo message to the given endpoint. /// </summary> /// <param name="endpoint">The endpoint to which the message should be send.</param> /// <param name="messageText">The text of the message.</param> public void SendEchoMessageTo(EndpointId endpoint, string messageText) { if (m_Commands.HasCommandFor(endpoint, typeof(ITestCommandSet))) { var commands = m_Commands.CommandsFor <ITestCommandSet>(endpoint); commands.Echo(messageText, 10, 15 * 1000); } }
/// <summary> /// Switches the dataset to edit mode. /// </summary> public void SwitchToEditMode() { if (!m_IsEditMode) { Debug.Assert(m_CommandHub.HasCommandFor(Endpoint, typeof(IDatasetApplicationCommands)), "Missing essential command set."); var commands = m_CommandHub.CommandsFor <IDatasetApplicationCommands>(Endpoint); var result = commands.SwitchToEditMode(); result.ContinueWith( t => { if (t.Exception != null) { m_Diagnostics.Log( LevelToLog.Error, BaseConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "The begin edit dataset task threw an exception. Exception details: {0}", t.Exception)); } }); } }
/// <summary> /// An event handler which is invoked when the search for an assembly fails. /// </summary> /// <param name="sender">The object which raised the event.</param> /// <param name="args"> /// The <see cref="System.ResolveEventArgs"/> instance containing the event data. /// </param> /// <returns> /// An assembly reference if the required assembly can be found; otherwise <see langword="null"/>. /// </returns> public Assembly LocatePluginAssembly(object sender, ResolveEventArgs args) { var name = new AssemblyName(args.Name); var commands = m_HostCommands.CommandsFor <IHostApplicationCommands>(m_HostId); var prepareTask = commands.PreparePluginContainerForTransfer(name); try { prepareTask.Wait(); } catch (AggregateException) { return(null); } var file = m_FileSystem.Path.GetTempFileName(); try { var finalAssemblyPath = string.Format(CultureInfo.InvariantCulture, "{0}.dll", name.Name); var streamTask = m_Layer(m_HostId, prepareTask.Result, file); var copyTask = streamTask.ContinueWith( t => m_FileSystem.File.Move(t.Result.FullName, finalAssemblyPath), TaskContinuationOptions.ExecuteSynchronously); try { copyTask.Wait(); } catch (AggregateException) { return(null); } // The assembly should be here now so we should be able to load it return(Assembly.Load(name)); } finally { if (m_FileSystem.File.Exists(file)) { m_FileSystem.File.Delete(file); } } }
/// <summary> /// Takes the set of distribution plans and loads the given datasets onto the specified machines. /// </summary> /// <param name="planToImplement">The distribution plan that should be implemented.</param> /// <param name="token">The token used to indicate cancellation of the task.</param> /// <param name="progressReporter">The action that handles the reporting of progress.</param> /// <returns> /// A set of objects which allow act as proxies for the loaded datasets. /// </returns> public Task <DatasetOnlineInformation> ImplementPlan( DistributionPlan planToImplement, CancellationToken token, Action <int, string, bool> progressReporter) { Func <DatasetOnlineInformation> result = () => { m_Diagnostics.Log(LevelToLog.Info, BaseConstants.LogPrefix, "Activating dataset"); var info = m_CommunicationLayer.LocalConnectionFor(ChannelType.NamedPipe); EndpointId endpoint; try { endpoint = m_Loader.ActivateDataset(info.Item1, ChannelType.NamedPipe, info.Item2); } catch (Exception e) { m_Diagnostics.Log( LevelToLog.Error, BaseConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Failed to activate the dataset. Error was: {0}", e)); throw; } var resetEvent = new AutoResetEvent(false); var commandAvailabilityNotifier = Observable.FromEventPattern <CommandSetAvailabilityEventArgs>( h => m_CommandHub.OnEndpointSignedIn += h, h => m_CommandHub.OnEndpointSignedIn -= h) .Where(args => args.EventArgs.Endpoint.Equals(endpoint)) .Take(1); var notificationAvailabilityNotifier = Observable.FromEventPattern <NotificationSetAvailabilityEventArgs>( h => m_NotificationHub.OnEndpointSignedIn += h, h => m_NotificationHub.OnEndpointSignedIn -= h) .Where(args => args.EventArgs.Endpoint.Equals(endpoint)) .Take(1); var availability = commandAvailabilityNotifier.Zip( notificationAvailabilityNotifier, (a, b) => { return(true); }) .Subscribe( args => { resetEvent.Set(); }); using (availability) { if (!m_CommandHub.HasCommandsFor(endpoint) || !m_NotificationHub.HasNotificationsFor(endpoint)) { m_Diagnostics.Log(LevelToLog.Trace, BaseConstants.LogPrefix, "Waiting for dataset to connect."); resetEvent.WaitOne(); } } m_Diagnostics.Log(LevelToLog.Trace, "Received commands and notifications from dataset."); IDatasetApplicationNotifications notifications; try { notifications = m_NotificationHub.NotificationsFor <IDatasetApplicationNotifications>(endpoint); } catch (Exception e) { m_Diagnostics.Log( LevelToLog.Error, BaseConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Failed to get the notifications. Error was: {0}", e)); throw; } EventHandler <ProgressEventArgs> progressHandler = (s, e) => progressReporter(e.Progress, e.Description, e.HasErrors); notifications.OnProgress += progressHandler; try { // Store the file var file = planToImplement.DistributionFor.StoredAt.AsFile(); var uploadToken = m_Uploads.Register(file.FullName); // The commands have been registered, so now load the dataset Debug.Assert( m_CommandHub.HasCommandFor(endpoint, typeof(IDatasetApplicationCommands)), "No application commands registered."); var commands = m_CommandHub.CommandsFor <IDatasetApplicationCommands>(endpoint); var task = commands.Load( EndpointIdExtensions.CreateEndpointIdForCurrentProcess(), uploadToken); task.Wait(); // Now the dataset loading is complete return(m_DatasetInformationBuilder( planToImplement.DistributionFor.Id, endpoint, planToImplement.MachineToDistributeTo)); } finally { notifications.OnProgress -= progressHandler; } }; return(Task <DatasetOnlineInformation> .Factory.StartNew( result, token, TaskCreationOptions.LongRunning, m_Scheduler)); }