internal TargetInProgessState ( EngineCallback engineCallback, Target target, List <ProjectBuildState> waitingBuildStates, ProjectBuildState initiatingRequest, BuildRequest [] outstandingBuildRequests, string projectName ) { this.targetId = new TargetIdWrapper(target); this.outstandingBuildRequests = outstandingBuildRequests; // For each waiting build context try to find the parent target this.parentBuildRequests = new List <BuildRequest>(); this.parentTargets = new List <TargetIdWrapper>(); this.projectName = projectName; // Process the waiting contexts if there are any if (waitingBuildStates != null) { for (int i = 0; i < waitingBuildStates.Count; i++) { ProcessBuildContext(engineCallback, waitingBuildStates[i], target); } } // Process the initiating context ProcessBuildContext(engineCallback, initiatingRequest, target); }
/// <summary> /// Given a build state try to find the parent target that caused this build state to /// come into being either via dependent, on error relationship or via IBuildEngine call /// </summary> internal TargetIdWrapper FindParentTarget ( EngineCallback engineCallback, ProjectBuildState buildContext, Target target, out BuildRequest parentRequest ) { // We need to find the parent target parentRequest = null; // Skip build states that have already been filled if (buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.RequestFilled) { return(null); } // Check if the target was called due to a onerror or depends on call if (buildContext.ContainsBlockingTarget(target.Name)) { // Figure out the record for the parent target Project containingProject = target.ParentProject; Target parentTarget = containingProject.Targets[buildContext.GetParentTarget(target.Name)]; return(new TargetIdWrapper(parentTarget)); } else { // The build context must have formed due to IBuildEngine call ErrorUtilities.VerifyThrow( String.Compare(EscapingUtilities.UnescapeAll(buildContext.NameOfTargetInProgress), target.Name, StringComparison.OrdinalIgnoreCase) == 0, "The target should be the in progress target for the context"); // This target is called due to IBuildEngine or host request return(FindParentTargetForBuildRequest(engineCallback, buildContext.BuildRequest, out parentRequest)); } }
internal TargetCycleDetector(EngineLoggingServices engineLoggingService, EngineCallback engineCallback) { this.engineLoggingService = engineLoggingService; this.engineCallback = engineCallback; dependencyGraph = new Hashtable(); outstandingExternalRequests = new Hashtable(); cycleParent = null; cycleChild = null; }
/// <summary> /// Figure out the parent target or the parent build request for the given context /// </summary> private void ProcessBuildContext(EngineCallback engineCallback, ProjectBuildState buildContext, Target target) { BuildRequest parentRequest = null; TargetIdWrapper parentName = FindParentTarget(engineCallback, buildContext, target, out parentRequest); if (parentName != null) { parentTargets.Add(parentName); } if (parentRequest != null) { parentBuildRequests.Add(parentRequest); } }
/// <summary> /// Given a build request try to find the target that caused it to come into being /// </summary> private TargetIdWrapper FindParentTargetForBuildRequest ( EngineCallback engineCallback, BuildRequest triggeringBuildRequest, out BuildRequest parentTriggeringRequest ) { parentTriggeringRequest = null; // If request is non-external and generated due to IBuildEngine call try // to find the target that caused the IBuildEngine call if (triggeringBuildRequest.IsGeneratedRequest && !triggeringBuildRequest.IsExternalRequest) { ExecutionContext executionContext = engineCallback.GetExecutionContextFromHandleId(triggeringBuildRequest.HandleId); // If the parent context is not a routing context than we can // get the parent target from it if (executionContext is TaskExecutionContext) { return(new TargetIdWrapper(((TaskExecutionContext)executionContext).ParentTarget)); } // If the parent context if a routing context the parent target is not available // on the current node, so store the request instead else { parentTriggeringRequest = triggeringBuildRequest; } } // If the request is external to the node - store the request since the parent target // is not available else if (triggeringBuildRequest.IsExternalRequest) { parentTriggeringRequest = triggeringBuildRequest; } else { requestedByHost = true; } return(null); }
/// <summary> /// The TaskExecutionModule is a the external view into a subsystem responsible for executing user /// tasks. The subsystem consists of TaskWorkerThread, TaskEngine, TaskExecutionState and EngineProxy. /// The engine thread passes the TaskExecutionState to the TEM which after the task finishes passes the /// results back via the engineCallback. /// </summary> internal TaskExecutionModule ( EngineCallback engineCallback, TaskExecutionModuleMode moduleMode, bool profileExecution ) { this.engineCallback = engineCallback; this.moduleMode = moduleMode; // By default start in breadthFirst traversal. This is done to gather enough work at the start of the build to get all the nodes at least working on something. this.breadthFirstTraversal = true; this.profileExecution = profileExecution; this.totalTaskTime = 0; // Get the node the TEM is running on, this is so the parent engine knows which node is requesting a traversal strategy change. nodeId = engineCallback.GetParentEngine().NodeId; SetBatchRequestSize(); // In singleproc mode the task execution module executes tasks on the engine thread. In multi proc mode a new thread is // created so the TEM can submit tasks to a worker queue which will run the tasks on a new thread. if (moduleMode != TaskExecutionModuleMode.SingleProcMode) { this.isRunningMultipleNodes = true; this.activeThreadCount = 0; this.overallThreadCount = 0; this.threadActiveCountEvent = new ManualResetEvent(false); this.threadOverallCountEvent = new ManualResetEvent(false); this.lastTaskActivity = 0; // Create a worker thread and make it the active node thread workerThread = new TaskWorkerThread(this, profileExecution); workerThread.ActivateThread(); } else { this.isRunningMultipleNodes = false; } }
/// <summary> /// This function checks if the given ProjectBuildState is caused by a given parent target (via /// a dependency, onerror or IBuildEngine relationship) /// </summary> internal bool CheckBuildContextForParentMatch ( EngineCallback engineCallback, TargetIdWrapper parentId, Target target, ProjectBuildState projectBuildState ) { BuildRequest parentRequest = null; TargetInProgessState.TargetIdWrapper parentName = FindParentTarget(engineCallback, projectBuildState, target, out parentRequest); if (parentName != null && parentName.Equals(parentId)) { return(true); } if (parentRequest != null) { for (int j = 0; j < parentBuildRequests.Count; j++) { if (parentRequest.HandleId == parentBuildRequests[j].HandleId && parentRequest.RequestId == parentBuildRequests[j].RequestId) { if (parentTargetsForBuildRequests[j].Equals(parentId)) { return(true); } else { return(false); } } } } return(false); }