private void HandleOnEndpointConnected(object sender, EndpointEventArgs args)
        {
            var endpoint      = args.Endpoint;
            var notifications = m_RemoteNotifications.NotificationsFor <ITestNotificationSet>(endpoint);

            notifications.OnNotify += (s, e) => AddNewMessage(endpoint, "Received notification");
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DatasetOnlineInformation"/> class.
        /// </summary>
        /// <param name="id">The ID number of the dataset.</param>
        /// <param name="endpoint">The ID number of the endpoint that has the actual dataset loaded.</param>
        /// <param name="networkId">The network identifier of the machine on which the dataset runs.</param>
        /// <param name="commandHub">The object that handles sending commands to the remote endpoint.</param>
        /// <param name="notificationHub">The object that handles the event notifications for remote endpoints.</param>
        /// <param name="systemDiagnostics">The object that provides the diagnostics methods for the system.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="endpoint"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="networkId"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="commandHub"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="notificationHub"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="systemDiagnostics"/> is <see langword="null" />.
        /// </exception>
        public DatasetOnlineInformation(
            DatasetId id,
            EndpointId endpoint,
            NetworkIdentifier networkId,
            ISendCommandsToRemoteEndpoints commandHub,
            INotifyOfRemoteEndpointEvents notificationHub,
            SystemDiagnostics systemDiagnostics)
        {
            {
                Enforce.Argument(() => id);
                Enforce.Argument(() => endpoint);
                Enforce.Argument(() => networkId);
                Enforce.Argument(() => commandHub);
                Enforce.Argument(() => notificationHub);
                Enforce.Argument(() => systemDiagnostics);
            }

            Id            = id;
            Endpoint      = endpoint;
            RunsOn        = networkId;
            m_CommandHub  = commandHub;
            m_Diagnostics = systemDiagnostics;

            m_NotificationHub = notificationHub;
            {
                Debug.Assert(
                    m_NotificationHub.HasNotificationFor(Endpoint, typeof(IDatasetApplicationNotifications)),
                    "Missing essential notification set.");

                var notifications = m_NotificationHub.NotificationsFor <IDatasetApplicationNotifications>(Endpoint);
                notifications.OnSwitchToEditingMode +=
                    (s, e) =>
                {
                    m_IsEditMode = true;
                    RaiseOnSwitchToEditMode();
                };
                notifications.OnSwitchToExecutingMode +=
                    (s, e) =>
                {
                    m_IsEditMode = false;
                    RaiseOnSwitchToExecutingMode();
                };
                notifications.OnTimelineUpdate +=
                    (s, e) =>
                {
                    RaiseOnTimelineUpdate();
                };
            }
        }
Пример #3
0
        /// <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 =
                () =>
            {
                IDatasetActivationCommands activationCommands;
                lock (m_Lock)
                {
                    if (!m_ActivatorCommands.ContainsKey(planToImplement.Proposal.Endpoint))
                    {
                        throw new EndpointNotContactableException(planToImplement.Proposal.Endpoint);
                    }

                    activationCommands = m_ActivatorCommands[planToImplement.Proposal.Endpoint];
                }

                // We shouldn't have to load the TCP channel at this point because that channel would have
                // been loaded when the loaders broadcast their message indicating that they exist.
                var info         = m_CommunicationLayer.LocalConnectionFor(ChannelType.TcpIP);
                var endpointTask = activationCommands.Activate(info.Item1, ChannelType.TcpIP, info.Item2, planToImplement.DistributionFor.Id);
                endpointTask.Wait();

                var endpoint   = endpointTask.Result;
                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)
                    .Subscribe(
                        args =>
                {
                    resetEvent.Set();
                });

                using (commandAvailabilityNotifier)
                {
                    if (!m_CommandHub.HasCommandsFor(endpoint) || !m_NotificationHub.HasNotificationsFor(endpoint))
                    {
                        resetEvent.WaitOne();
                    }
                }

                EventHandler <ProgressEventArgs> progressHandler =
                    (s, e) => progressReporter(e.Progress, e.Description, e.HasErrors);
                var notifications = m_NotificationHub.NotificationsFor <IDatasetApplicationNotifications>(endpoint);
                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 applicationCommands = m_CommandHub.CommandsFor <IDatasetApplicationCommands>(endpoint);
                    var task = applicationCommands.Load(
                        EndpointIdExtensions.CreateEndpointIdForCurrentProcess(),
                        uploadToken);
                    task.Wait();

                    return(m_DatasetInformationBuilder(
                               planToImplement.DistributionFor.Id,
                               endpoint,
                               planToImplement.MachineToDistributeTo));
                }
                finally
                {
                    notifications.OnProgress -= progressHandler;
                }
            };

            return(Task <DatasetOnlineInformation> .Factory.StartNew(
                       result,
                       token,
                       TaskCreationOptions.LongRunning,
                       m_Scheduler));
        }
 /// <summary>
 /// Returns a collection containing all the notifications that a dataset has
 /// defined.
 /// </summary>
 /// <returns>The collection with all the notifications that the dataset has defined.</returns>
 public IEnumerable <INotificationSet> AvailableNotifications()
 {
     return(from notificationType in m_NotificationHub.AvailableNotificationsFor(Endpoint)
            where (notificationType.GetCustomAttributes(typeof(InternalNotificationAttribute), true).Length == 0)
            select m_NotificationHub.NotificationsFor(Endpoint, notificationType));
 }
Пример #5
0
        /// <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));
        }