/// <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));
             }
         });
     }
 }
示例#2
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));
        }
示例#3
0
 public bool CanContactEndpoint(EndpointId endpoint)
 {
     return(m_Commands.HasCommandFor(endpoint, typeof(ITestCommandSet)));
 }
示例#4
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));
        }