Exemplo n.º 1
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var actionVertex = vertex as ExecutingActionVertex;
            if (actionVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return ScheduleExecutionState.IncorrectProcessorForVertex;
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return ScheduleExecutionState.Canceled;
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            var id = actionVertex.ActionToExecute;
            if (!m_Storage.Contains(id))
            {
                throw new UnknownScheduleActionException();
            }

            var action = m_Storage.Action(id);
            action.Execute(executionInfo.Cancellation);
            return ScheduleExecutionState.Executing;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Links the given start vertex to the end vertex.
        /// </summary>
        /// <param name="start">The start vertex.</param>
        /// <param name="end">The end vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from <paramref name="start"/> to <paramref name="end"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="start"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="start"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="start"/> is equal to the start vertex of the schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="start"/> is equal to the end vertex of the schedule.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="end"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="end"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="end"/> is equal to the start vertex of the schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="end"/> is equal to the end vertex of the schedule.
        /// </exception>
        /// <exception cref="CannotLinkAVertexToItselfException">
        ///     Thrown if <paramref name="start"/> and <paramref name="end"/> are the same vertex.
        /// </exception>
        public void LinkTo(IScheduleVertex start, IScheduleVertex end, ScheduleElementId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => start);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(start),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);
                Lokad.Enforce.With <CannotExplicitlyLinkStartVertexException>(
                    !ReferenceEquals(m_Start, start),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkStartVertex);
                Lokad.Enforce.With <CannotExplicitlyLinkEndVertexException>(
                    !ReferenceEquals(m_End, start),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkEndVertex);

                Lokad.Enforce.Argument(() => end);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(end),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);
                Lokad.Enforce.With <CannotExplicitlyLinkStartVertexException>(
                    !ReferenceEquals(m_Start, end),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkStartVertex);
                Lokad.Enforce.With <CannotExplicitlyLinkEndVertexException>(
                    !ReferenceEquals(m_End, end),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkEndVertex);

                Lokad.Enforce.With <CannotLinkAVertexToItselfException>(
                    !ReferenceEquals(start, end),
                    Resources.Exceptions_Messages_CannotLinkAVertexToItself);
            }

            m_Schedule.AddEdge(new ScheduleEdge(start, end, traverseCondition));
        }
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var markVertex = vertex as MarkHistoryVertex;

            if (markVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return(ScheduleExecutionState.IncorrectProcessorForVertex);
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return(ScheduleExecutionState.Canceled);
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            var marker = m_Timeline.Mark();

            m_OnMarkerStorage(marker);
            return(ScheduleExecutionState.Executing);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var actionVertex = vertex as ExecutingActionVertex;

            if (actionVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return(ScheduleExecutionState.IncorrectProcessorForVertex);
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return(ScheduleExecutionState.Canceled);
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            var id = actionVertex.ActionToExecute;

            if (!m_Storage.Contains(id))
            {
                throw new UnknownScheduleActionException();
            }

            var action = m_Storage.Action(id);

            action.Execute(executionInfo.Cancellation);
            return(ScheduleExecutionState.Executing);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Traverses the schedule and applies an action to each vertex visited.
        /// </summary>
        /// <param name="start">The vertex where the traverse should be started.</param>
        /// <param name="vertexAction">
        /// The action taken for each vertex that is encountered. The function is provided with the current vertex and
        /// a collection of all outbound, if <paramref name="traverseViaOutboundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return <see langword="false" />
        /// to terminate the traverse.
        /// </param>
        /// <param name="directionAction">
        /// The function that determines in which direction the traverse should proceed. The function is provided with
        /// a collection of all outbound, if <paramref name="traverseViaOutboundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return the next vertex
        /// that should be traversed, or <see langword="null" /> if the traverse should be terminated.
        /// </param>
        /// <param name="traverseViaOutboundVertices">
        /// A flag indicating if the schedule should be traversed via the outbound edges of the vertices, or the inbound ones.
        /// </param>
        public void TraverseSchedule(
            IScheduleVertex start,
            Func <IScheduleVertex, bool> vertexAction,
            Func <IEnumerable <Tuple <ScheduleElementId, IScheduleVertex> >, IScheduleVertex> directionAction,
            bool traverseViaOutboundVertices = true)
        {
            {
                Lokad.Enforce.Argument(() => start);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Graph.ContainsVertex(start),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexAction);
                Lokad.Enforce.Argument(() => directionAction);
            }

            var source = start;

            while (source != null)
            {
                var result = vertexAction(source);
                if (!result)
                {
                    return;
                }

                var outEdges    = traverseViaOutboundVertices ? m_Graph.OutEdges(source) : m_Graph.InEdges(source);
                var traverseMap = from edge in outEdges
                                  select new Tuple <ScheduleElementId, IScheduleVertex>(
                    edge.TraversingCondition,
                    traverseViaOutboundVertices ? edge.Target : edge.Source);

                source = directionAction(traverseMap);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Schedule"/> class.
        /// </summary>
        /// <param name="information">The serialization information containing the data for the schedule.</param>
        /// <param name="context">The serialization context.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="information"/> is <see langword="null" />.
        /// </exception>
        public Schedule(SerializationInfo information, StreamingContext context)
        {
            {
                Lokad.Enforce.Argument(() => information);
            }

            m_Graph = new BidirectionalGraph <IScheduleVertex, ScheduleEdge>();
            var vertices = new List <IScheduleVertex>();

            var vertexCount = information.GetInt32(SerializationVertexCount);

            for (int i = 0; i < vertexCount; i++)
            {
                var type = (Type)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationVertexType,
                        i),
                    typeof(Type));

                var vertex = (IScheduleVertex)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationVertex,
                        i),
                    type);

                vertices.Add(vertex);
                m_Graph.AddVertex(vertex);
            }

            var edgeCount = information.GetInt32(SerializationEdgeCount);

            for (int i = 0; i < edgeCount; i++)
            {
                var tuple = (Tuple <int, int, ScheduleElementId>)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationEdge,
                        i),
                    typeof(Tuple <int, int, ScheduleElementId>));

                m_Graph.AddEdge(
                    new ScheduleEdge(
                        vertices[tuple.Item1],
                        vertices[tuple.Item2],
                        tuple.Item3));
            }

            var startIndex = information.GetInt32(SerializationStartVertex);

            m_Start = vertices[startIndex];

            var endIndex = information.GetInt32(SerializationEndVertex);

            m_End = vertices[endIndex];
        }
        /// <summary>
        /// Links the given vertex to the end point of the schedule.
        /// </summary>
        /// <param name="source">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from <paramref name="source"/> to the end point.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="source"/> is <see langword="null" />.
        /// </exception>
        public void LinkToEnd(IScheduleVertex source, ScheduleConditionRegistrationId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => source);
            }

            ScheduleElementId condition = ToScheduleCondition(traverseCondition);

            m_Builder.LinkToEnd(source, condition);
        }
        /// <summary>
        /// Links the start point of the schedule to the given vertex.
        /// </summary>
        /// <param name="target">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from the start point to <paramref name="target"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="target"/> is <see langword="null" />.
        /// </exception>
        public void LinkFromStart(IScheduleVertex target, ScheduleConditionRegistrationId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => target);
            }

            ScheduleElementId condition = ToScheduleCondition(traverseCondition);

            m_Builder.LinkFromStart(target, condition);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FixedScheduleBuilder"/> class.
        /// </summary>
        public FixedScheduleBuilder()
        {
            m_Schedule = new BidirectionalGraph <IScheduleVertex, ScheduleEdge>(false);

            m_Start = new StartVertex(m_Schedule.VertexCount);
            m_Schedule.AddVertex(m_Start);

            m_End = new EndVertex(m_Schedule.VertexCount);
            m_Schedule.AddVertex(m_End);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FixedScheduleBuilder"/> class.
        /// </summary>
        /// <param name="scheduleToStartWith">The schedule that will be copied as base schedule.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="scheduleToStartWith"/> is <see langword="null" />.
        /// </exception>
        public FixedScheduleBuilder(ISchedule scheduleToStartWith)
        {
            {
                Lokad.Enforce.Argument(() => scheduleToStartWith);
            }

            var tuple = CopySchedule(scheduleToStartWith);

            m_Schedule = tuple.Item1;
            m_Start    = tuple.Item2;
            m_End      = tuple.Item3;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var endVertex = vertex as EndVertex;
            if (endVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return ScheduleExecutionState.IncorrectProcessorForVertex;
            }

            // We don't check for pause or cancel here, we're done anyway
            return ScheduleExecutionState.Completed;
        }
Exemplo n.º 12
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var endVertex = vertex as EndVertex;

            if (endVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return(ScheduleExecutionState.IncorrectProcessorForVertex);
            }

            // We don't check for pause or cancel here, we're done anyway
            return(ScheduleExecutionState.Completed);
        }
        public bool Equals(IScheduleVertex other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            // Check if other is a null reference by using ReferenceEquals because
            // we overload the == operator. If other isn't actually null then
            // we get an infinite loop where we're constantly trying to compare to null.
            return(!ReferenceEquals(other, null) &&
                   Index == other.Index &&
                   GetType().Equals(other.GetType()));
        }
Exemplo n.º 14
0
        private static Tuple <BidirectionalGraph <IScheduleVertex, ScheduleEdge>, IScheduleVertex, IScheduleVertex> CopyGraph(
            BidirectionalGraph <IScheduleVertex, ScheduleEdge> graph,
            IScheduleVertex start)
        {
            var map      = new Dictionary <IScheduleVertex, IScheduleVertex>();
            var newGraph = new BidirectionalGraph <IScheduleVertex, ScheduleEdge>(false);

            var startVertex = CloneVertex(start);

            newGraph.AddVertex(startVertex);
            map.Add(start, startVertex);

            var nodeCounter       = new List <IScheduleVertex>();
            var uncheckedVertices = new Queue <IScheduleVertex>();

            uncheckedVertices.Enqueue(start);
            while (uncheckedVertices.Count > 0)
            {
                var source = uncheckedVertices.Dequeue();
                if (nodeCounter.Contains(source))
                {
                    continue;
                }

                nodeCounter.Add(source);

                var outEdges = graph.OutEdges(source);
                foreach (var outEdge in outEdges)
                {
                    var target = outEdge.Target;
                    if (!map.ContainsKey(target))
                    {
                        var targetVertex = CloneVertex(target);
                        newGraph.AddVertex(targetVertex);
                        map.Add(target, targetVertex);
                    }

                    var edgeSource = map[source];
                    var edgeTarget = map[target];
                    newGraph.AddEdge(new ScheduleEdge(edgeSource, edgeTarget, outEdge.TraversingCondition));

                    uncheckedVertices.Enqueue(outEdge.Target);
                }
            }

            var endVertex = map.First(p => p.Value is EndVertex).Value;

            return(new Tuple <BidirectionalGraph <IScheduleVertex, ScheduleEdge>, IScheduleVertex, IScheduleVertex>(newGraph, startVertex, endVertex));
        }
Exemplo n.º 15
0
        private IScheduleVertex DetermineNextScheduleStep(
            IEnumerable <Tuple <ScheduleElementId, IScheduleVertex> > availableNodes,
            ref ScheduleExecutionState state)
        {
            IScheduleVertex nextVertex = null;

            foreach (var pair in availableNodes)
            {
                if (m_ExecutionInfo.Cancellation.IsCancellationRequested)
                {
                    state = ScheduleExecutionState.Canceled;
                    break;
                }

                // If we need to pause we do it here
                m_ExecutionInfo.PauseHandler.WaitForUnPause(m_ExecutionInfo.Cancellation);

                bool canTraverse = true;
                if (pair.Item1 != null)
                {
                    Debug.Assert(m_Conditions.Contains(pair.Item1), "The traversing condition for the edge does not exist");
                    var condition = m_Conditions.Condition(pair.Item1);
                    try
                    {
                        canTraverse = condition.CanTraverse(m_ExecutionInfo.Cancellation);
                    }
                    catch (Exception)
                    {
                        state = ScheduleExecutionState.UnhandledException;
                        break;
                    }
                }

                if (canTraverse)
                {
                    nextVertex = pair.Item2;
                    break;
                }
            }

            // If we get here then there were no edges we could traverse. Fail the execution
            if ((nextVertex == null) && (state == ScheduleExecutionState.Executing))
            {
                state = ScheduleExecutionState.NoTraversableEdgeFound;
            }

            return(nextVertex);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var startVertex = vertex as StartVertex;
            if (startVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return ScheduleExecutionState.IncorrectProcessorForVertex;
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return ScheduleExecutionState.Canceled;
            }

            return ScheduleExecutionState.Executing;
        }
Exemplo n.º 17
0
        /// <summary>
        /// Traverses the schedule and applies an action to each vertex visited.
        /// </summary>
        /// <param name="start">The vertex where the traverse should be started.</param>
        /// <param name="vertexAction">
        /// The action taken for each vertex that is encountered. The action is provided with the current vertex and
        /// a collection of all outbound, if <paramref name="traverseViaOutBoundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return <see langword="false" />
        /// to terminate the traverse.
        /// </param>
        /// <param name="traverseViaOutBoundVertices">
        /// A flag indicating if the schedule should be traversed via the outbound edges of the vertices, or the inbound ones.
        /// </param>
        public void TraverseAllScheduleVertices(
            IScheduleVertex start,
            Func <IScheduleVertex, IEnumerable <Tuple <ScheduleElementId, IScheduleVertex> >, bool> vertexAction,
            bool traverseViaOutBoundVertices = true)
        {
            {
                Lokad.Enforce.Argument(() => start);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Graph.ContainsVertex(start),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexAction);
            }

            var nodeCounter = new List <IScheduleVertex>();

            var uncheckedVertices = new Queue <IScheduleVertex>();

            uncheckedVertices.Enqueue(start);
            while (uncheckedVertices.Count > 0)
            {
                var source = uncheckedVertices.Dequeue();
                if (nodeCounter.Contains(source))
                {
                    continue;
                }

                nodeCounter.Add(source);

                var outEdges    = traverseViaOutBoundVertices ? m_Graph.OutEdges(source) : m_Graph.InEdges(source);
                var traverseMap = from edge in outEdges
                                  select new Tuple <ScheduleElementId, IScheduleVertex>(
                    edge.TraversingCondition,
                    traverseViaOutBoundVertices ? edge.Target : edge.Source);

                var result = vertexAction(source, traverseMap);
                if (!result)
                {
                    return;
                }

                foreach (var outEdge in outEdges)
                {
                    uncheckedVertices.Enqueue(traverseViaOutBoundVertices ? outEdge.Target : outEdge.Source);
                }
            }
        }
Exemplo n.º 18
0
        private static ISchedule BuildThreeVertexSchedule(IScheduleVertex middle)
        {
            var graph = new BidirectionalGraph <IScheduleVertex, ScheduleEdge>();
            var start = new StartVertex(1);

            graph.AddVertex(start);

            var end = new EndVertex(2);

            graph.AddVertex(end);

            graph.AddVertex(middle);
            graph.AddEdge(new ScheduleEdge(start, middle));
            graph.AddEdge(new ScheduleEdge(middle, end));

            return(new Schedule(graph, start, end));
        }
Exemplo n.º 19
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var startVertex = vertex as StartVertex;

            if (startVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return(ScheduleExecutionState.IncorrectProcessorForVertex);
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return(ScheduleExecutionState.Canceled);
            }

            return(ScheduleExecutionState.Executing);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Links the start point of the schedule to the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from the start point to <paramref name="vertex"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="vertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="vertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="vertex"/> is equal to the end vertex of the schedule.
        /// </exception>
        /// <exception cref="CannotLinkAVertexToItselfException">
        ///     Thrown if the start vertex of the schedule and <paramref name="vertex"/> are the same vertex.
        /// </exception>
        public void LinkFromStart(IScheduleVertex vertex, ScheduleElementId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => vertex);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(vertex),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.With <CannotExplicitlyLinkEndVertexException>(
                    !ReferenceEquals(m_End, vertex),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkEndVertex);
                Lokad.Enforce.With <CannotLinkAVertexToItselfException>(
                    !ReferenceEquals(m_Start, vertex),
                    Resources.Exceptions_Messages_CannotLinkAVertexToItself);
            }

            m_Schedule.AddEdge(new ScheduleEdge(m_Start, vertex, traverseCondition));
        }
Exemplo n.º 21
0
        private bool ProcessScheduleStep(IScheduleVertex current, ref ScheduleExecutionState state)
        {
            if (m_ExecutionInfo.Cancellation.IsCancellationRequested)
            {
                state = ScheduleExecutionState.Canceled;
                return(false);
            }

            // If we need to pause we do it here
            m_ExecutionInfo.PauseHandler.WaitForUnPause(m_ExecutionInfo.Cancellation);

            // Get the executor for the current node type and run it
            // on the current node. If we fail then we exit the loop
            {
                var type = current.GetType();
                if (!m_Executors.ContainsKey(type))
                {
                    state = ScheduleExecutionState.NoProcessorForVertex;
                    return(false);
                }

                RaiseOnVertexProcess(Schedule, current.Index);
                var processor = m_Executors[type];
                try
                {
                    ScheduleExecutionState shouldContinue = processor.Process(current, m_ExecutionInfo);
                    if (shouldContinue != ScheduleExecutionState.Executing)
                    {
                        state = shouldContinue;
                        return(false);
                    }

                    RaiseOnExecutionProgress(-1, Resources.Progress_ExecutingSchedule, false);
                }
                catch (Exception)
                {
                    state = ScheduleExecutionState.UnhandledException;
                    return(false);
                }

                return(true);
            }
        }
Exemplo n.º 22
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Schedule"/> class.
        /// </summary>
        /// <param name="graph">The graph that describes the current schedule.</param>
        /// <param name="start">The start node for the schedule.</param>
        /// <param name="end">The end node for the schedule.</param>
        public Schedule(
            BidirectionalGraph <IScheduleVertex, ScheduleEdge> graph,
            IScheduleVertex start,
            IScheduleVertex end)
        {
            {
                Debug.Assert(graph != null, "The graph should not be a null reference.");

                Debug.Assert(start != null, "The start vertex should not be a null reference.");
                Debug.Assert(start is StartVertex, "The start vertex should be an editable start vertex.");
                Debug.Assert(graph.ContainsVertex(start), "The start vertex should be part of the graph.");

                Debug.Assert(end != null, "The end vertex should not be a null reference.");
                Debug.Assert(end is EndVertex, "The end vertex should be an editable end vertex.");
                Debug.Assert(graph.ContainsVertex(end), "The end vertex should be part of the graph.");
            }

            m_Start = start;
            m_End   = end;

            m_Graph = graph;
        }
Exemplo n.º 23
0
        private static bool AreVerticesEqual(IScheduleVertex first, IScheduleVertex second)
        {
            if (first.GetType() != second.GetType())
            {
                return(false);
            }

            var executingActionVertex = first as ExecutingActionVertex;

            if (executingActionVertex != null)
            {
                return(executingActionVertex.ActionToExecute == ((ExecutingActionVertex)second).ActionToExecute);
            }

            var subScheduleVertex = first as SubScheduleVertex;

            if (subScheduleVertex != null)
            {
                return(subScheduleVertex.ScheduleToExecute == ((SubScheduleVertex)second).ScheduleToExecute);
            }

            return(true);
        }
        /// <summary>
        /// Links the given vertex to the end point of the schedule.
        /// </summary>
        /// <param name="source">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from <paramref name="source"/> to the end point.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="source"/> is <see langword="null" />.
        /// </exception>
        public void LinkToEnd(IScheduleVertex source, ScheduleConditionRegistrationId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => source);
            }

            ScheduleElementId condition = ToScheduleCondition(traverseCondition);
            m_Builder.LinkToEnd(source, condition);
        }
Exemplo n.º 25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Schedule"/> class.
        /// </summary>
        /// <param name="information">The serialization information containing the data for the schedule.</param>
        /// <param name="context">The serialization context.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="information"/> is <see langword="null" />.
        /// </exception>
        public Schedule(SerializationInfo information, StreamingContext context)
        {
            {
                Lokad.Enforce.Argument(() => information);
            }

            m_Graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>();
            var vertices = new List<IScheduleVertex>();

            var vertexCount = information.GetInt32(SerializationVertexCount);
            for (int i = 0; i < vertexCount; i++)
            {
                var type = (Type)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationVertexType,
                        i),
                    typeof(Type));

                var vertex = (IScheduleVertex)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationVertex,
                        i),
                    type);

                vertices.Add(vertex);
                m_Graph.AddVertex(vertex);
            }

            var edgeCount = information.GetInt32(SerializationEdgeCount);
            for (int i = 0; i < edgeCount; i++)
            {
                var tuple = (Tuple<int, int, ScheduleElementId>)information.GetValue(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        SerializationEdge,
                        i),
                    typeof(Tuple<int, int, ScheduleElementId>));

                m_Graph.AddEdge(
                    new ScheduleEdge(
                        vertices[tuple.Item1],
                        vertices[tuple.Item2],
                        tuple.Item3));
            }

            var startIndex = information.GetInt32(SerializationStartVertex);
            m_Start = vertices[startIndex];

            var endIndex = information.GetInt32(SerializationEndVertex);
            m_End = vertices[endIndex];
        }
        private static bool AreVerticesEqual(IScheduleVertex first, IScheduleVertex second)
        {
            if (first.GetType() != second.GetType())
            {
                return false;
            }

            var executingActionVertex = first as ExecutingActionVertex;
            if (executingActionVertex != null)
            {
                return executingActionVertex.ActionToExecute == ((ExecutingActionVertex)second).ActionToExecute;
            }

            var subScheduleVertex = first as SubScheduleVertex;
            if (subScheduleVertex != null)
            {
                return subScheduleVertex.ScheduleToExecute == ((SubScheduleVertex)second).ScheduleToExecute;
            }

            return true;
        }
Exemplo n.º 27
0
        public bool Equals(IScheduleVertex other)
        {
            if (ReferenceEquals(this, other))
            {
                return true;
            }

            // Check if other is a null reference by using ReferenceEquals because
            // we overload the == operator. If other isn't actually null then
            // we get an infinite loop where we're constantly trying to compare to null.
            return !ReferenceEquals(other, null)
                && Index == other.Index
                && GetType().Equals(other.GetType());
        }
Exemplo n.º 28
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FixedScheduleBuilder"/> class.
        /// </summary>
        /// <param name="scheduleToStartWith">The schedule that will be copied as base schedule.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="scheduleToStartWith"/> is <see langword="null" />.
        /// </exception>
        public FixedScheduleBuilder(ISchedule scheduleToStartWith)
        {
            {
                Lokad.Enforce.Argument(() => scheduleToStartWith);
            }

            var tuple = CopySchedule(scheduleToStartWith);
            m_Schedule = tuple.Item1;
            m_Start = tuple.Item2;
            m_End = tuple.Item3;
        }
Exemplo n.º 29
0
        /// <summary>
        /// Inserts the given vertex in the position of the given insert vertex. The insert vertex will
        /// be removed if it has no more inserts left.
        /// </summary>
        /// <param name="insertVertex">The vertex which will be replaced.</param>
        /// <param name="vertexToInsert">The new vertex.</param>
        /// <returns>A tuple containing the insert vertices that were place before and after the newly inserted vertex.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="insertVertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="insertVertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="vertexToInsert"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="CannotInsertExistingVertexException">
        ///     Thrown if <paramref name="vertexToInsert"/> already exists in the schedule.
        /// </exception>
        /// <exception cref="NoInsertsLeftOnVertexException">
        ///     Thrown if <paramref name="insertVertex"/> has no more inserts left.
        /// </exception>
        public Tuple<InsertVertex, InsertVertex> InsertIn(
            InsertVertex insertVertex,
            IScheduleVertex vertexToInsert)
        {
            {
                Lokad.Enforce.Argument(() => insertVertex);
                Lokad.Enforce.With<UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(insertVertex),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexToInsert);
                Lokad.Enforce.With<CannotInsertExistingVertexException>(
                    !m_Schedule.ContainsVertex(vertexToInsert),
                    Resources.Exceptions_Messages_CannotInsertExistingVertex);

                Lokad.Enforce.With<NoInsertsLeftOnVertexException>(
                    (insertVertex.RemainingInserts == -1) || (insertVertex.RemainingInserts > 0),
                    Resources.Exceptions_Messages_NoInsertsLeftOnVertex);
            }

            // Find the inbound and outbound edges
            var inbound = from edge in m_Schedule.InEdges(insertVertex)
                          select edge;

            var outbound = from edge in m_Schedule.OutEdges(insertVertex)
                           select edge;

            // Add the new node
            m_Schedule.AddVertex(vertexToInsert);

            // Create two new insert vertices to be placed on either side of the new vertex
            var count = (insertVertex.RemainingInserts != -1) ? insertVertex.RemainingInserts - 1 : -1;

            InsertVertex inboundInsert = null;
            InsertVertex outboundInsert = null;
            if ((count == -1) || (count > 0))
            {
                inboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(inboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(inboundInsert, vertexToInsert, null));

                outboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(outboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(vertexToInsert, outboundInsert, null));
            }

            // Reconnect all the edges
            var inboundTarget = inboundInsert ?? vertexToInsert;
            var outboundSource = outboundInsert ?? vertexToInsert;

            foreach (var inboundEdge in inbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(inboundEdge.Source, inboundTarget, inboundEdge.TraversingCondition));
            }

            foreach (var outboundEdge in outbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(outboundSource, outboundEdge.Target, outboundEdge.TraversingCondition));
            }

            // Lastly remove the current insert node, which also destroys all the edges that are
            // connected to it.
            m_Schedule.RemoveVertex(insertVertex);

            return new Tuple<InsertVertex, InsertVertex>(inboundInsert, outboundInsert);
        }
Exemplo n.º 30
0
 private static IScheduleVertex CloneVertex(IScheduleVertex vertex)
 {
     return(s_VertexBuilder[vertex.GetType()](vertex, vertex.Index));
 }
Exemplo n.º 31
0
 /// <summary>
 /// Returns the number of vertices to which the current vertex connects.
 /// </summary>
 /// <param name="origin">The vertex for which the number of outbound connections should be returned.</param>
 /// <returns>The number of outbound connections for the current vertex.</returns>
 public int NumberOfOutboundConnections(IScheduleVertex origin)
 {
     return(m_Graph.OutDegree(origin));
 }
Exemplo n.º 32
0
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var subScheduleVertex = vertex as SubScheduleVertex;

            if (subScheduleVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return(ScheduleExecutionState.IncorrectProcessorForVertex);
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return(ScheduleExecutionState.Canceled);
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            // And how do we deal with loops? We'll cache the schedule if we're in-process but what about being out-of-process? We'll need to
            // keep the remote app alive ...
            // --> We'll need some kind of class that handles making the decision for in-process / out-of-process.
            //     * If it's small then we want to do in-process because the loading of a new dataset takes a while
            //     * If it's a parametrized thing then we might want to do out-of-process because we can run many more in one go
            //
            // Determine if we're running the sub-simulation synchronous (in-process) or ascynchronous (out-of-process)
            // Depends on:
            // - If the original schedule is allowed to split out sub-schedules out-of-process (when running in interactive mode we may
            //   not allow this)
            // - 'size' of the sub-schedule
            //
            // Determine if we should go out of process here
            // Going out of process only makes sense if the overhead of going out of process is less than
            // the overhead of staying in process.
            // The overhead of going out of process is:
            // * Serialize all the data we need
            // * Load an application
            // * Stream the data across
            // * Deserialize data
            // * Re-serialize the data that we need (this may be less than what we send across)
            // * Send data across
            // * Deserialize data in original app
            // The overhead for staying in process is given by the fact that we can only run one schedule
            // at the time
            //
            // So going out of process makes sense when:
            // * There are multiple sub-schedules before the next sync block
            //   ==> that means we can run all of them in parallel and the sync block indicates when we'll need the data
            // * We want to run the same sub-schedule with multiple parameters
            //   ==> Run the parameter values all at the same time
            // * We want to split the current calculation out into multiple bits (domain decomposition type)
            //
            // Can we determine this when we build the schedule?
            // Possibly for some sections?
            bool executeOutOfProcess = false;
            IEnumerable <IScheduleVariable> parameters = null;
            var executor = m_Executor.Execute(subScheduleVertex.ScheduleToExecute, parameters, executionInfo, executeOutOfProcess);

            // if we're running in-process then we probably have to wait for the sub-schedule to
            // finish executing because we don't want to have to make the schedule execution thread safe
            // If it's running out-of-process then we don't bother waiting. There should be a sync block
            // around this section that will sort out the variable synchronization.
            if (executor.IsLocal)
            {
                var resetEvent  = new AutoResetEvent(false);
                var wrapperWait = Observable.FromEventPattern <ScheduleExecutionStateEventArgs>(
                    h => executor.OnFinish += h,
                    h => executor.OnFinish -= h)
                                  .Take(1)
                                  .Subscribe(args => resetEvent.Set());

                using (wrapperWait)
                {
                    resetEvent.WaitOne();
                }
            }

            return(ScheduleExecutionState.Executing);
        }
Exemplo n.º 33
0
        /// <summary>
        /// Traverses the schedule and applies an action to each vertex visited.
        /// </summary>
        /// <param name="start">The vertex where the traverse should be started.</param>
        /// <param name="vertexAction">
        /// The action taken for each vertex that is encountered. The action is provided with the current vertex and
        /// a collection of all outbound, if <paramref name="traverseViaOutBoundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return <see langword="false" />
        /// to terminate the traverse.
        /// </param>
        /// <param name="traverseViaOutBoundVertices">
        /// A flag indicating if the schedule should be traversed via the outbound edges of the vertices, or the inbound ones.
        /// </param>
        public void TraverseAllScheduleVertices(
            IScheduleVertex start,
            Func<IScheduleVertex, IEnumerable<Tuple<ScheduleElementId, IScheduleVertex>>, bool> vertexAction,
            bool traverseViaOutBoundVertices = true)
        {
            {
                Lokad.Enforce.Argument(() => start);
                Lokad.Enforce.With<UnknownScheduleVertexException>(
                    m_Graph.ContainsVertex(start),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexAction);
            }

            var nodeCounter = new List<IScheduleVertex>();

            var uncheckedVertices = new Queue<IScheduleVertex>();
            uncheckedVertices.Enqueue(start);
            while (uncheckedVertices.Count > 0)
            {
                var source = uncheckedVertices.Dequeue();
                if (nodeCounter.Contains(source))
                {
                    continue;
                }

                nodeCounter.Add(source);

                var outEdges = traverseViaOutBoundVertices ? m_Graph.OutEdges(source) : m_Graph.InEdges(source);
                var traverseMap = from edge in outEdges
                                  select new Tuple<ScheduleElementId, IScheduleVertex>(
                                      edge.TraversingCondition,
                                      traverseViaOutBoundVertices ? edge.Target : edge.Source);

                var result = vertexAction(source, traverseMap);
                if (!result)
                {
                    return;
                }

                foreach (var outEdge in outEdges)
                {
                    uncheckedVertices.Enqueue(traverseViaOutBoundVertices ? outEdge.Target : outEdge.Source);
                }
            }
        }
Exemplo n.º 34
0
        /// <summary>
        /// Inserts the given vertex in the position of the given insert vertex. The insert vertex will
        /// be removed if it has no more inserts left.
        /// </summary>
        /// <param name="insertVertex">The vertex which will be replaced.</param>
        /// <param name="vertexToInsert">The new vertex.</param>
        /// <returns>A tuple containing the insert vertices that were place before and after the newly inserted vertex.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="insertVertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="insertVertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="vertexToInsert"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="CannotInsertExistingVertexException">
        ///     Thrown if <paramref name="vertexToInsert"/> already exists in the schedule.
        /// </exception>
        /// <exception cref="NoInsertsLeftOnVertexException">
        ///     Thrown if <paramref name="insertVertex"/> has no more inserts left.
        /// </exception>
        public Tuple <InsertVertex, InsertVertex> InsertIn(
            InsertVertex insertVertex,
            IScheduleVertex vertexToInsert)
        {
            {
                Lokad.Enforce.Argument(() => insertVertex);
                Lokad.Enforce.With <UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(insertVertex),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexToInsert);
                Lokad.Enforce.With <CannotInsertExistingVertexException>(
                    !m_Schedule.ContainsVertex(vertexToInsert),
                    Resources.Exceptions_Messages_CannotInsertExistingVertex);

                Lokad.Enforce.With <NoInsertsLeftOnVertexException>(
                    (insertVertex.RemainingInserts == -1) || (insertVertex.RemainingInserts > 0),
                    Resources.Exceptions_Messages_NoInsertsLeftOnVertex);
            }

            // Find the inbound and outbound edges
            var inbound = from edge in m_Schedule.InEdges(insertVertex)
                          select edge;

            var outbound = from edge in m_Schedule.OutEdges(insertVertex)
                           select edge;

            // Add the new node
            m_Schedule.AddVertex(vertexToInsert);

            // Create two new insert vertices to be placed on either side of the new vertex
            var count = (insertVertex.RemainingInserts != -1) ? insertVertex.RemainingInserts - 1 : -1;

            InsertVertex inboundInsert  = null;
            InsertVertex outboundInsert = null;

            if ((count == -1) || (count > 0))
            {
                inboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(inboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(inboundInsert, vertexToInsert, null));

                outboundInsert = new InsertVertex(m_Schedule.VertexCount, count);
                m_Schedule.AddVertex(outboundInsert);
                m_Schedule.AddEdge(new ScheduleEdge(vertexToInsert, outboundInsert, null));
            }

            // Reconnect all the edges
            var inboundTarget  = inboundInsert ?? vertexToInsert;
            var outboundSource = outboundInsert ?? vertexToInsert;

            foreach (var inboundEdge in inbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(inboundEdge.Source, inboundTarget, inboundEdge.TraversingCondition));
            }

            foreach (var outboundEdge in outbound)
            {
                m_Schedule.AddEdge(new ScheduleEdge(outboundSource, outboundEdge.Target, outboundEdge.TraversingCondition));
            }

            // Lastly remove the current insert node, which also destroys all the edges that are
            // connected to it.
            m_Schedule.RemoveVertex(insertVertex);

            return(new Tuple <InsertVertex, InsertVertex>(inboundInsert, outboundInsert));
        }
        /// <summary>
        /// Links the start point of the schedule to the given vertex.
        /// </summary>
        /// <param name="target">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from the start point to <paramref name="target"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="target"/> is <see langword="null" />.
        /// </exception>
        public void LinkFromStart(IScheduleVertex target, ScheduleConditionRegistrationId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => target);
            }

            ScheduleElementId condition = ToScheduleCondition(traverseCondition);
            m_Builder.LinkFromStart(target, condition);
        }
Exemplo n.º 36
0
        /// <summary>
        /// Links the given vertex to the end point of the schedule.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="traverseCondition">
        /// The ID of the condition that determines if it is possible to move from <paramref name="vertex"/> to the end point.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="vertex"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownScheduleVertexException">
        ///     Thrown if <paramref name="vertex"/> does not exist in the current schedule.
        /// </exception>
        /// <exception cref="CannotExplicitlyLinkStartVertexException">
        ///     Thrown if <paramref name="vertex"/> is equal to the start vertex of the schedule.
        /// </exception>
        /// <exception cref="CannotLinkAVertexToItselfException">
        ///     Thrown if the end vertex of the schedule and <paramref name="vertex"/> are the same vertex.
        /// </exception>
        public void LinkToEnd(IScheduleVertex vertex, ScheduleElementId traverseCondition = null)
        {
            {
                Lokad.Enforce.Argument(() => vertex);
                Lokad.Enforce.With<UnknownScheduleVertexException>(
                    m_Schedule.ContainsVertex(vertex),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);
                Lokad.Enforce.With<CannotExplicitlyLinkStartVertexException>(
                    !ReferenceEquals(m_Start, vertex),
                    Resources.Exceptions_Messages_CannotExplicitlyLinkStartVertex);
                Lokad.Enforce.With<CannotLinkAVertexToItselfException>(
                    !ReferenceEquals(m_End, vertex),
                    Resources.Exceptions_Messages_CannotLinkAVertexToItself);
            }

            m_Schedule.AddEdge(new ScheduleEdge(vertex, m_End, traverseCondition));
        }
Exemplo n.º 37
0
 private static bool AreVerticesEqual(IScheduleVertex first, IScheduleVertex second)
 {
     return first.Equals(second);
 }
Exemplo n.º 38
0
 private static IScheduleVertex CloneVertex(IScheduleVertex vertex)
 {
     return s_VertexBuilder[vertex.GetType()](vertex, vertex.Index);
 }
Exemplo n.º 39
0
 private static bool AreVerticesEqual(IScheduleVertex first, IScheduleVertex second)
 {
     return(first.Equals(second));
 }
Exemplo n.º 40
0
        private static Tuple<BidirectionalGraph<IScheduleVertex, ScheduleEdge>, IScheduleVertex, IScheduleVertex> CopyGraph(
            BidirectionalGraph<IScheduleVertex, ScheduleEdge> graph,
            IScheduleVertex start)
        {
            var map = new Dictionary<IScheduleVertex, IScheduleVertex>();
            var newGraph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(false);

            var startVertex = CloneVertex(start);
            newGraph.AddVertex(startVertex);
            map.Add(start, startVertex);

            var nodeCounter = new List<IScheduleVertex>();
            var uncheckedVertices = new Queue<IScheduleVertex>();
            uncheckedVertices.Enqueue(start);
            while (uncheckedVertices.Count > 0)
            {
                var source = uncheckedVertices.Dequeue();
                if (nodeCounter.Contains(source))
                {
                    continue;
                }

                nodeCounter.Add(source);

                var outEdges = graph.OutEdges(source);
                foreach (var outEdge in outEdges)
                {
                    var target = outEdge.Target;
                    if (!map.ContainsKey(target))
                    {
                        var targetVertex = CloneVertex(target);
                        newGraph.AddVertex(targetVertex);
                        map.Add(target, targetVertex);
                    }

                    var edgeSource = map[source];
                    var edgeTarget = map[target];
                    newGraph.AddEdge(new ScheduleEdge(edgeSource, edgeTarget, outEdge.TraversingCondition));

                    uncheckedVertices.Enqueue(outEdge.Target);
                }
            }

            var endVertex = map.First(p => p.Value is EndVertex).Value;
            return new Tuple<BidirectionalGraph<IScheduleVertex, ScheduleEdge>, IScheduleVertex, IScheduleVertex>(newGraph, startVertex, endVertex);
        }
Exemplo n.º 41
0
        private static ISchedule BuildThreeVertexSchedule(IScheduleVertex middle)
        {
            var graph = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>();
            var start = new StartVertex(1);
            graph.AddVertex(start);

            var end = new EndVertex(2);
            graph.AddVertex(end);

            graph.AddVertex(middle);
            graph.AddEdge(new ScheduleEdge(start, middle));
            graph.AddEdge(new ScheduleEdge(middle, end));

            return new Schedule(graph, start, end);
        }
Exemplo n.º 42
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FixedScheduleBuilder"/> class.
        /// </summary>
        public FixedScheduleBuilder()
        {
            m_Schedule = new BidirectionalGraph<IScheduleVertex, ScheduleEdge>(false);

            m_Start = new StartVertex(m_Schedule.VertexCount);
            m_Schedule.AddVertex(m_Start);

            m_End = new EndVertex(m_Schedule.VertexCount);
            m_Schedule.AddVertex(m_End);
        }
Exemplo n.º 43
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Schedule"/> class.
        /// </summary>
        /// <param name="graph">The graph that describes the current schedule.</param>
        /// <param name="start">The start node for the schedule.</param>
        /// <param name="end">The end node for the schedule.</param>
        public Schedule(
            BidirectionalGraph<IScheduleVertex, ScheduleEdge> graph,
            IScheduleVertex start,
            IScheduleVertex end)
        {
            {
                Debug.Assert(graph != null, "The graph should not be a null reference.");

                Debug.Assert(start != null, "The start vertex should not be a null reference.");
                Debug.Assert(start is StartVertex, "The start vertex should be an editable start vertex.");
                Debug.Assert(graph.ContainsVertex(start), "The start vertex should be part of the graph.");

                Debug.Assert(end != null, "The end vertex should not be a null reference.");
                Debug.Assert(end is EndVertex, "The end vertex should be an editable end vertex.");
                Debug.Assert(graph.ContainsVertex(end), "The end vertex should be part of the graph.");
            }

            m_Start = start;
            m_End = end;

            m_Graph = graph;
        }
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var markVertex = vertex as MarkHistoryVertex;
            if (markVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return ScheduleExecutionState.IncorrectProcessorForVertex;
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return ScheduleExecutionState.Canceled;
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            var marker = m_Timeline.Mark();
            m_OnMarkerStorage(marker);
            return ScheduleExecutionState.Executing;
        }
Exemplo n.º 45
0
 /// <summary>
 /// Returns the number of vertices to which the current vertex connects.
 /// </summary>
 /// <param name="origin">The vertex for which the number of outbound connections should be returned.</param>
 /// <returns>The number of outbound connections for the current vertex.</returns>
 public int NumberOfOutboundConnections(IScheduleVertex origin)
 {
     return m_Graph.OutDegree(origin);
 }
Exemplo n.º 46
0
        private bool ProcessScheduleStep(IScheduleVertex current, ref ScheduleExecutionState state)
        {
            if (m_ExecutionInfo.Cancellation.IsCancellationRequested)
            {
                state = ScheduleExecutionState.Canceled;
                return false;
            }

            // If we need to pause we do it here
            m_ExecutionInfo.PauseHandler.WaitForUnPause(m_ExecutionInfo.Cancellation);

            // Get the executor for the current node type and run it
            // on the current node. If we fail then we exit the loop
            {
                var type = current.GetType();
                if (!m_Executors.ContainsKey(type))
                {
                    state = ScheduleExecutionState.NoProcessorForVertex;
                    return false;
                }

                RaiseOnVertexProcess(Schedule, current.Index);
                var processor = m_Executors[type];
                try
                {
                    ScheduleExecutionState shouldContinue = processor.Process(current, m_ExecutionInfo);
                    if (shouldContinue != ScheduleExecutionState.Executing)
                    {
                        state = shouldContinue;
                        return false;
                    }

                    RaiseOnExecutionProgress(-1, Resources.Progress_ExecutingSchedule, false);
                }
                catch (Exception)
                {
                    state = ScheduleExecutionState.UnhandledException;
                    return false;
                }

                return true;
            }
        }
Exemplo n.º 47
0
        /// <summary>
        /// Traverses the schedule and applies an action to each vertex visited.
        /// </summary>
        /// <param name="start">The vertex where the traverse should be started.</param>
        /// <param name="vertexAction">
        /// The action taken for each vertex that is encountered. The function is provided with the current vertex and
        /// a collection of all outbound, if <paramref name="traverseViaOutboundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return <see langword="false" />
        /// to terminate the traverse.
        /// </param>
        /// <param name="directionAction">
        /// The function that determines in which direction the traverse should proceed. The function is provided with
        /// a collection of all outbound, if <paramref name="traverseViaOutboundVertices"/> is <see langword="true" />,
        /// or inbound vertices and the ID of the traversing condition. The function should return the next vertex
        /// that should be traversed, or <see langword="null" /> if the traverse should be terminated.
        /// </param>
        /// <param name="traverseViaOutboundVertices">
        /// A flag indicating if the schedule should be traversed via the outbound edges of the vertices, or the inbound ones.
        /// </param>
        public void TraverseSchedule(
            IScheduleVertex start,
            Func<IScheduleVertex, bool> vertexAction,
            Func<IEnumerable<Tuple<ScheduleElementId, IScheduleVertex>>, IScheduleVertex> directionAction,
            bool traverseViaOutboundVertices = true)
        {
            {
                Lokad.Enforce.Argument(() => start);
                Lokad.Enforce.With<UnknownScheduleVertexException>(
                    m_Graph.ContainsVertex(start),
                    Resources.Exceptions_Messages_UnknownScheduleVertex);

                Lokad.Enforce.Argument(() => vertexAction);
                Lokad.Enforce.Argument(() => directionAction);
            }

            var source = start;
            while (source != null)
            {
                var result = vertexAction(source);
                if (!result)
                {
                    return;
                }

                var outEdges = traverseViaOutboundVertices ? m_Graph.OutEdges(source) : m_Graph.InEdges(source);
                var traverseMap = from edge in outEdges
                                  select new Tuple<ScheduleElementId, IScheduleVertex>(
                                      edge.TraversingCondition,
                                      traverseViaOutboundVertices ? edge.Target : edge.Source);

                source = directionAction(traverseMap);
            }
        }
        /// <summary>
        /// Processes action provided by the given vertex.
        /// </summary>
        /// <param name="vertex">The vertex.</param>
        /// <param name="executionInfo">The object that stores the information about the execution of the schedule.</param>
        /// <returns>A value indicating if the execution of the schedule should continue.</returns>
        public ScheduleExecutionState Process(IScheduleVertex vertex, ScheduleExecutionInfo executionInfo)
        {
            var subScheduleVertex = vertex as SubScheduleVertex;
            if (subScheduleVertex == null)
            {
                Debug.Assert(false, "The vertex is of the incorrect type.");
                return ScheduleExecutionState.IncorrectProcessorForVertex;
            }

            if (executionInfo.Cancellation.IsCancellationRequested)
            {
                return ScheduleExecutionState.Canceled;
            }

            if (executionInfo.PauseHandler.IsPaused)
            {
                executionInfo.PauseHandler.WaitForUnPause(executionInfo.Cancellation);
            }

            // And how do we deal with loops? We'll cache the schedule if we're in-process but what about being out-of-process? We'll need to
            // keep the remote app alive ...
            // --> We'll need some kind of class that handles making the decision for in-process / out-of-process.
            //     * If it's small then we want to do in-process because the loading of a new dataset takes a while
            //     * If it's a parametrized thing then we might want to do out-of-process because we can run many more in one go
            //
            // Determine if we're running the sub-simulation synchronous (in-process) or ascynchronous (out-of-process)
            // Depends on:
            // - If the original schedule is allowed to split out sub-schedules out-of-process (when running in interactive mode we may
            //   not allow this)
            // - 'size' of the sub-schedule
            //
            // Determine if we should go out of process here
            // Going out of process only makes sense if the overhead of going out of process is less than
            // the overhead of staying in process.
            // The overhead of going out of process is:
            // * Serialize all the data we need
            // * Load an application
            // * Stream the data across
            // * Deserialize data
            // * Re-serialize the data that we need (this may be less than what we send across)
            // * Send data across
            // * Deserialize data in original app
            // The overhead for staying in process is given by the fact that we can only run one schedule
            // at the time
            //
            // So going out of process makes sense when:
            // * There are multiple sub-schedules before the next sync block
            //   ==> that means we can run all of them in parallel and the sync block indicates when we'll need the data
            // * We want to run the same sub-schedule with multiple parameters
            //   ==> Run the parameter values all at the same time
            // * We want to split the current calculation out into multiple bits (domain decomposition type)
            //
            // Can we determine this when we build the schedule?
            // Possibly for some sections?
            bool executeOutOfProcess = false;
            IEnumerable<IScheduleVariable> parameters = null;
            var executor = m_Executor.Execute(subScheduleVertex.ScheduleToExecute, parameters, executionInfo, executeOutOfProcess);

            // if we're running in-process then we probably have to wait for the sub-schedule to
            // finish executing because we don't want to have to make the schedule execution thread safe
            // If it's running out-of-process then we don't bother waiting. There should be a sync block
            // around this section that will sort out the variable synchronization.
            if (executor.IsLocal)
            {
                var resetEvent = new AutoResetEvent(false);
                var wrapperWait = Observable.FromEventPattern<ScheduleExecutionStateEventArgs>(
                        h => executor.OnFinish += h,
                        h => executor.OnFinish -= h)
                    .Take(1)
                    .Subscribe(args => resetEvent.Set());

                using (wrapperWait)
                {
                    resetEvent.WaitOne();
                }
            }

            return ScheduleExecutionState.Executing;
        }