Example #1
0
 internal GraphNode(TargetInProgessState targetState)
 {
     this.targetState    = targetState;
     this.children       = new List <GraphNode>();
     this.traversalIndex = InvalidIndex;
     this.isRoot         = false;
 }
Example #2
0
        /// <summary>
        /// Find all the build contexts that connects child to parent. The only time multiple contexts are possible
        /// is if the connection is formed by an IBuildEngine callback which requests the same target in the
        /// same project to be build in parallel multiple times.
        /// </summary>
        internal List <ProjectBuildState> FindConnectingContexts
        (
            TargetInProgessState child,
            TargetInProgessState parent,
            Target childTarget,
            List <ProjectBuildState> waitingStates,
            ProjectBuildState initiatingBuildContext
        )
        {
            List <ProjectBuildState> connectingContexts = new List <ProjectBuildState>();

            // Since the there is a cycle formed at the child there must be at least two requests
            // since the edge between the parent and the child is a backward edge
            ErrorUtilities.VerifyThrow(waitingStates != null, "There must be a at least two requests at the child");


            for (int i = 0; i < waitingStates.Count; i++)
            {
                if (child.CheckBuildContextForParentMatch(parentEngine.EngineCallback, parent.TargetId, childTarget, waitingStates[i]))
                {
                    connectingContexts.Add(waitingStates[i]);
                }
            }


            if (child.CheckBuildContextForParentMatch(parentEngine.EngineCallback, parent.TargetId, childTarget, initiatingBuildContext))
            {
                connectingContexts.Add(initiatingBuildContext);
            }

            return(connectingContexts);
        }
Example #3
0
        /// <summary>
        /// This function is called to break the link between two targets that creates a cycle. The link could be
        /// due to depends/onerror relationship between parent and child. In that case both parent and child are
        /// on the same node and within the same project. Or the link could be formed by an IBuildEngine callback
        /// (made such by tasks such as MSBuild or CallTarget) in which case there maybe multiple requests forming
        /// same link between parent and child. Also in that case parent and child maybe on different nodes and/or in
        /// different projects. In either case the break is forced by finding the correct builds states and causing
        /// them to fail.
        /// </summary>
        internal void BreakCycle(TargetInProgessState child, TargetInProgessState parent)
        {
            ErrorUtilities.VerifyThrow(child.TargetId.nodeId == parentEngine.NodeId,
                                       "Expect the child target to be on the node");

            Project parentProject = projectManager.GetProject(child.TargetId.projectId);

            ErrorUtilities.VerifyThrow(parentProject != null,
                                       "Expect the parent project to be on the node");

            Target childTarget = parentProject.Targets[child.TargetId.name];

            List <ProjectBuildState> parentStates = FindConnectingContexts(child, parent, childTarget, childTarget.ExecutionState.GetWaitingBuildContexts(),
                                                                           childTarget.ExecutionState.InitiatingBuildContext);

            ErrorUtilities.VerifyThrow(parentStates.Count > 0, "Must find at least one matching context");

            for (int i = 0; i < parentStates.Count; i++)
            {
                parentStates[i].CurrentBuildContextState = ProjectBuildState.BuildContextState.CycleDetected;
                TaskExecutionContext taskExecutionContext =
                    new TaskExecutionContext(parentProject, childTarget, null, parentStates[i], EngineCallback.invalidEngineHandle,
                                             EngineCallback.inProcNode, null);

                parentEngine.PostTaskOutputUpdates(taskExecutionContext);
            }
        }
Example #4
0
        public void PostIntrospectorCommand(int nodeIndex, TargetInProgessState child, TargetInProgessState parent)
        {
            // Send the updated settings once the node has initialized
            LocalCallDescriptorForPostIntrospectorCommand callDescriptor =
                new LocalCallDescriptorForPostIntrospectorCommand(child, parent);

            nodeData[nodeIndex].NodeCommandQueue.Enqueue(callDescriptor);
        }
Example #5
0
 internal override void CreateFromStream(BinaryReader reader)
 {
     base.CreateFromStream(reader);
     child = new TargetInProgessState();
     child.CreateFromStream(reader);
     parent = new TargetInProgessState();
     parent.CreateFromStream(reader);
 }
Example #6
0
        /// <summary>
        /// Add a information about a given inprogress target to the graph
        /// </summary>
        private void AddTargetToGraph(TargetInProgessState inProgressTarget)
        {
            // Check if the target is already in the graph in which
            // case reuse the current object
            GraphNode targetNode = (GraphNode)dependencyGraph[inProgressTarget.TargetId];

            if (targetNode == null)
            {
                targetNode = new GraphNode(inProgressTarget);
                dependencyGraph.Add(inProgressTarget.TargetId, targetNode);
            }
            else
            {
                ErrorUtilities.VerifyThrow(targetNode.targetState == null, "Target should only be added once");
                targetNode.targetState = inProgressTarget;
            }

            // For each parent target - add parent links creating parent targets if necessary
            foreach (TargetInProgessState.TargetIdWrapper parentTarget in inProgressTarget.ParentTargets)
            {
                GraphNode parentNode = (GraphNode)dependencyGraph[parentTarget];
                if (parentNode == null)
                {
                    parentNode = new GraphNode(null);
                    dependencyGraph.Add(parentTarget, parentNode);
                }
                parentNode.children.Add(targetNode);
            }

            // For all outgoing requests add them to the list of outstanding requests for the system
            if (inProgressTarget.OutstandingBuildRequests != null)
            {
                // Since the nodeIndex is not serialized it is necessary to restore it after the request
                // travels across the wire
                for (int i = 0; i < inProgressTarget.OutstandingBuildRequests.Length; i++)
                {
                    inProgressTarget.OutstandingBuildRequests[i].NodeIndex = inProgressTarget.TargetId.nodeId;
                }
                outstandingExternalRequests.Add(inProgressTarget.TargetId, inProgressTarget.OutstandingBuildRequests);
            }

            // If the target has no parents mark it as root (such targets are created due to host requests)
            if (inProgressTarget.RequestedByHost)
            {
                targetNode.isRoot = true;
            }
        }
Example #7
0
        internal static NodeStatus CreateFromStream(BinaryReader reader)
        {
            NodeStatus status = new NodeStatus(null);

            status.traversalType               = reader.ReadBoolean();
            status.statusTimeStamp             = reader.ReadInt64();
            status.requestId                   = reader.ReadInt32();
            status.isActive                    = reader.ReadBoolean();
            status.isLaunchInProgress          = reader.ReadBoolean();
            status.queueDepth                  = reader.ReadInt32();
            status.lastTaskActivityTimeStamp   = reader.ReadInt64();
            status.lastEngineActivityTimeStamp = reader.ReadInt64();

            if (reader.ReadByte() == 0)
            {
                status.stateOfInProgressTargets = null;
            }
            else
            {
                int numberOfInProgressTargets = reader.ReadInt32();
                status.stateOfInProgressTargets = new TargetInProgessState[numberOfInProgressTargets];
                for (int i = 0; i < numberOfInProgressTargets; i++)
                {
                    if (reader.ReadByte() == 0)
                    {
                        status.stateOfInProgressTargets[i] = null;
                    }
                    else
                    {
                        TargetInProgessState state = new TargetInProgessState();
                        state.CreateFromStream(reader);
                        status.stateOfInProgressTargets[i] = state;
                    }
                }
            }

            if (reader.ReadByte() == 0)
            {
                status.unhandledException = null;
            }
            else
            {
                status.unhandledException = (Exception)formatter.Deserialize(reader.BaseStream);
            }
            return(status);
        }
Example #8
0
        internal void PostCycleNotification
        (
            int nodeId,
            TargetInProgessState child,
            TargetInProgessState parent)
        {
            if (nodeId == 0)
            {
                parentEngine.Introspector.BreakCycle(child, parent);
            }

            for (int i = 0; i < nodeList.Count; i++)
            {
                if (nodeList[i].NodeId == nodeId)
                {
                    nodeList[i].NodeProvider.PostIntrospectorCommand(nodeList[i].NodeIndex, child, parent);
                    break;
                }
            }
        }
Example #9
0
 internal LocalCallDescriptorForPostIntrospectorCommand(TargetInProgessState child, TargetInProgessState parent)
     : base(LocalCallType.PostIntrospectorCommand)
 {
     this.child  = child;
     this.parent = parent;
 }