Пример #1
0
 public Task Activate(
     DistributionLocations preferredLocation,
     Func <IEnumerable <DistributionSuggestion>, SelectedProposal> machineSelector,
     CancellationToken token)
 {
     return(m_Dataset.Activate(preferredLocation, machineSelector, token));
 }
Пример #2
0
        /// <summary>
        /// Activates the dataset.
        /// </summary>
        /// <param name="preferredLocation">
        /// Indicates a preferred machine location for the dataset to be distributed to.
        /// </param>
        /// <param name="machineSelector">
        ///     The function that selects the most suitable machine for the dataset to run on.
        /// </param>
        /// <remarks>
        /// Note that the <paramref name="preferredLocation"/> is
        /// only a suggestion. The loader may decide to ignore the suggestion if there is a distribution
        /// plan that is better suited to the contents of the dataset.
        /// </remarks>
        public void Activate(
            DistributionLocations preferredLocation,
            Func <DistributionSuggestionProxy[], DistributionSuggestionProxy> machineSelector)
        {
            var selector = new MachineSelectorFacade(machineSelector);

            m_Dataset.Activate(preferredLocation, selector);
        }
Пример #3
0
        /// <summary>
        /// Activates the dataset in an asynchronous manner.
        /// </summary>
        /// <param name="preferredLocation">
        /// Indicates a preferred machine location for the dataset to be distributed to.
        /// </param>
        /// <param name="machineSelector">
        ///     The function that selects the most suitable machine for the dataset to run on.
        /// </param>
        /// <param name="token">The token that is used to cancel the activation.</param>
        /// <remarks>
        /// Note that the <paramref name="preferredLocation"/> is
        /// only a suggestion. The activator may decide to ignore the suggestion if there is a distribution
        /// plan that is better suited to the contents of the dataset.
        /// </remarks>
        /// <returns>
        ///     A <see cref="Task"/> that completes when the dataset is activated.
        /// </returns>
        /// <exception cref="ArgumentException">
        ///     Thrown when the project that owns this dataset has been closed.
        /// </exception>
        /// <exception cref="CannotActivateDatasetWithoutDistributionLocationException">
        ///     Thrown when the <paramref name="preferredLocation"/> is <see cref="DistributionLocations.None"/>.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when <paramref name="machineSelector"/> is <see langword="null" />.
        /// </exception>
        public Task Activate(
            DistributionLocations preferredLocation,
            Func <IEnumerable <DistributionSuggestion>, SelectedProposal> machineSelector,
            CancellationToken token)
        {
            {
                Lokad.Enforce.With <ArgumentException>(
                    !Owner.IsClosed,
                    Resources.Exceptions_Messages_CannotUseProjectAfterClosingIt);
                Lokad.Enforce.With <CannotActivateDatasetWithoutDistributionLocationException>(
                    preferredLocation != DistributionLocations.None,
                    Resources.Exceptions_Messages_CannotActivateDatasetWithoutDistributionLocation);
                Lokad.Enforce.Argument(() => machineSelector);
            }

            return(Activate(preferredLocation, machineSelector, m_Notifications, token, true));
        }
Пример #4
0
        /// <summary>
        /// Activates the dataset.
        /// </summary>
        /// <param name="preferredLocation">
        /// Indicates a preferred machine location for the dataset to be distributed to.
        /// </param>
        /// <param name="machineSelector">
        ///     The function that selects the most suitable machine for the dataset to run on.
        /// </param>
        /// <remarks>
        /// Note that the <paramref name="preferredLocation"/> is
        /// only a suggestion. The loader may decide to ignore the suggestion if there is a distribution
        /// plan that is better suited to the contents of the dataset.
        /// </remarks>
        public void Activate(
            DistributionLocations preferredLocation,
            MachineSelectorFacade machineSelector)
        {
            Func <IEnumerable <DistributionSuggestion>, SelectedProposal> func =
                enumerable =>
            {
                var selection = enumerable.ToList();
                var proxies   = selection.Select(s => new DistributionSuggestionProxy(s)).ToArray();
                var result    = machineSelector.SelectFrom(proxies);

                var selectedPlan = selection.Find(s => s.Plan.MachineToDistributeTo.Equals(result.MachineToDistributeTo));
                return(new SelectedProposal(selectedPlan.Plan));
            };

            // CancellationToken is not serializable hence ...
            var token = new CancellationTokenSource();

            m_Dataset.Activate(preferredLocation, func, token.Token)
            .ContinueWith(t => token.Dispose());
        }
Пример #5
0
        private static IEnumerable <DatasetActivationProposal> OrderProposals(
            ExpectedDatasetLoad load,
            DistributionLocations preferedLocations,
            IEnumerable <Tuple <EndpointId, IDatasetActivationCommands> > usableNodes,
            CancellationToken token)
        {
            var loadingProposals = new Queue <Task <DatasetActivationProposal> >();

            bool shouldLoad = ShouldLoadDistributed(preferedLocations);

            foreach (var pair in usableNodes)
            {
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }

                if (shouldLoad)
                {
                    try
                    {
                        var result = pair.Item2.ProposeFor(load);
                        loadingProposals.Enqueue(result);
                    }
                    catch (CommandInvocationFailedException)
                    {
                        // Chances are the endpoint just disappeared
                        // so we just ignore it and move on.
                    }
                }
            }

            while (loadingProposals.Count > 0)
            {
                if (token.IsCancellationRequested)
                {
                    // Just abandon any tasks that were running but not finished
                    token.ThrowIfCancellationRequested();
                }

                var task = loadingProposals.Dequeue();
                if (!task.IsCompleted)
                {
                    if (loadingProposals.Count > 1)
                    {
                        loadingProposals.Enqueue(task);
                        continue;
                    }
                    else
                    {
                        try
                        {
                            task.Wait();
                        }
                        catch (AggregateException)
                        {
                            continue;
                        }
                    }
                }

                if (task.IsCanceled || task.IsFaulted)
                {
                    // Get the exception so that the task doesn't throw in
                    // the finalizer. Don't do anything with this though
                    // because we don't really care.
                    var exception = task.Exception;
                    continue;
                }

                var proposal = task.Result;
                if (proposal.IsAvailable)
                {
                    yield return(proposal);
                }
            }
        }
Пример #6
0
 private static bool ShouldLoadDistributed(DistributionLocations preferedLocations)
 {
     return(((preferedLocations & DistributionLocations.DistributedOnCluster) == DistributionLocations.DistributedOnCluster) ||
            ((preferedLocations & DistributionLocations.DistributedOnPeerToPeer) == DistributionLocations.DistributedOnPeerToPeer));
 }
 private static bool ShouldLoadDistributed(DistributionLocations preferedLocations)
 {
     return ((preferedLocations & DistributionLocations.DistributedOnCluster) == DistributionLocations.DistributedOnCluster)
         || ((preferedLocations & DistributionLocations.DistributedOnPeerToPeer) == DistributionLocations.DistributedOnPeerToPeer);
 }
        private static IEnumerable<DatasetActivationProposal> OrderProposals(
            ExpectedDatasetLoad load,
            DistributionLocations preferedLocations,
            IEnumerable<Tuple<EndpointId, IDatasetActivationCommands>> usableNodes,
            CancellationToken token)
        {
            var loadingProposals = new Queue<Task<DatasetActivationProposal>>();

            bool shouldLoad = ShouldLoadDistributed(preferedLocations);
            foreach (var pair in usableNodes)
            {
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }

                if (shouldLoad)
                {
                    try
                    {
                        var result = pair.Item2.ProposeFor(load);
                        loadingProposals.Enqueue(result);
                    }
                    catch (CommandInvocationFailedException)
                    {
                        // Chances are the endpoint just disappeared
                        // so we just ignore it and move on.
                    }
                }
            }

            while (loadingProposals.Count > 0)
            {
                if (token.IsCancellationRequested)
                {
                    // Just abandon any tasks that were running but not finished
                    token.ThrowIfCancellationRequested();
                }

                var task = loadingProposals.Dequeue();
                if (!task.IsCompleted)
                {
                    if (loadingProposals.Count > 1)
                    {
                        loadingProposals.Enqueue(task);
                        continue;
                    }
                    else
                    {
                        try
                        {
                            task.Wait();
                        }
                        catch (AggregateException)
                        {
                            continue;
                        }
                    }
                }

                if (task.IsCanceled || task.IsFaulted)
                {
                    // Get the exception so that the task doesn't throw in
                    // the finalizer. Don't do anything with this though
                    // because we don't really care.
                    var exception = task.Exception;
                    continue;
                }

                var proposal = task.Result;
                if (proposal.IsAvailable)
                {
                    yield return proposal;
                }
            }
        }
Пример #9
0
        private Task Activate(
            DistributionLocations preferredLocation,
            Func <IEnumerable <DistributionSuggestion>, SelectedProposal> machineSelector,
            ICollectNotifications notifications,
            CancellationToken token,
            bool storeLocation)
        {
            {
                Debug.Assert(!Owner.IsClosed, "The owner should not be closed.");
                Debug.Assert(preferredLocation != DistributionLocations.None, "A distribution location should be specified.");
            }

            if (IsActivated)
            {
                return(Task.Factory.StartNew(
                           () => { },
                           token,
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            }

            if (m_IsActivating)
            {
                var onActivated = Observable.FromEventPattern <EventArgs>(
                    h => OnActivated += h,
                    h => OnActivated -= h)
                                  .Take(1);
                var onDeactivated = Observable.FromEventPattern <EventArgs>(
                    h => OnDeactivated += h,
                    h => OnDeactivated -= h)
                                    .Take(1);

                return(Observable.Amb(onActivated, onDeactivated)
                       .ToTask(token));
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.DatasetProxy_LogMessage_ActivatingDataset_WithId,
                    Id));

            m_IsActivating = true;
            try
            {
                var request = new DatasetActivationRequest
                {
                    DatasetToActivate      = this,
                    PreferredLocations     = preferredLocation,
                    ExpectedLoadPerMachine = new ExpectedDatasetLoad
                    {
                        OnDiskSizeInBytes   = StoredAt.StoredSizeInBytes(),
                        InMemorySizeInBytes = StoredAt.StoredSizeInBytes(),
                        RelativeMemoryExpansionWhileRunning = 2.0,
                        RelativeOnDiskExpansionAfterRunning = 2.0,
                    },
                };

                var suggestedPlans = m_ConstructorArgs.DistributionPlanGenerator(request, token);
                var selection      = suggestedPlans.Select(plan => new DistributionSuggestion(plan));
                var selectedPlan   = machineSelector(selection);
                if (token.IsCancellationRequested || selectedPlan.WasSelectionCanceled)
                {
                    return(Task.Factory.StartNew(
                               () => { },
                               token,
                               TaskCreationOptions.None,
                               new CurrentThreadTaskScheduler()));
                }

                RaiseOnProgressOfCurrentAction(0, Resources.Progress_ActivatingDataset, false);
                var task             = selectedPlan.Plan.Accept(token, RaiseOnProgressOfCurrentAction);
                var continuationTask = task.ContinueWith(
                    t =>
                {
                    try
                    {
                        if (t.Exception != null)
                        {
                            m_Diagnostics.Log(
                                LevelToLog.Error,
                                HostConstants.LogPrefix,
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    Resources.DatasetProxy_LogMessage_FailedToActivateDataset_WithException,
                                    Id,
                                    t.Exception));

                            // Obviously not activated so ...
                            RaiseOnProgressOfCurrentAction(100, string.Empty, false);
                            RaiseOnDeactivated();

                            notifications.StoreNotification(Resources.Notifications_FailedToActivateDataset);
                            return;
                        }

                        var online   = t.Result;
                        m_Connection = online;
                        m_Connection.OnSwitchToEditMode      += HandleOnSwitchToEditMode;
                        m_Connection.OnSwitchToExecutingMode += HandleOnSwitchToExecutingMode;

                        m_DataProxy = m_ProxyBuilder(m_Connection);

                        if (storeLocation)
                        {
                            m_DistributionLocation.Current = selectedPlan.Plan.MachineToDistributeTo;
                        }

                        m_Diagnostics.Log(
                            LevelToLog.Trace,
                            HostConstants.LogPrefix,
                            string.Format(
                                CultureInfo.InvariantCulture,
                                Resources.DatasetProxy_LogMessage_DatasetActivationComplete_WithId,
                                Id));

                        RaiseOnActivated();
                    }
                    finally
                    {
                        m_IsActivating = false;
                    }
                },
                    TaskContinuationOptions.ExecuteSynchronously);

                return(continuationTask);
            }
            catch (Exception)
            {
                // Only clean this up if the whole thing falls over
                m_IsActivating = false;
                throw;
            }
        }