/// <summary> /// This method is called to update the datastructures to reflect that given request will /// be built on a given node. /// </summary> /// <param name="currentRequest"></param> /// <param name="nodeUsed"></param> internal void NotifyOfSchedulingDecision(BuildRequest currentRequest, int nodeUsed) { // Don't update structures on the child node or in single proc mode if (childMode || nodes.Length == 1) { return; } // Update the count of requests being build on the node totalRequestsPerNode[nodeUsed]++; // Ignore host requests if (currentRequest.HandleId == EngineCallback.invalidEngineHandle) { return; } if (Engine.debugMode) { string targetnames = currentRequest.TargetNames != null?String.Join(";", currentRequest.TargetNames) : "null"; Console.WriteLine("Sending project " + currentRequest.ProjectFileName + " Target " + targetnames + " to " + nodeUsed); } // Update the records ScheduleRecordKey recordKey = new ScheduleRecordKey(currentRequest.HandleId, currentRequest.RequestId); ScheduleRecordKey parentKey = new ScheduleRecordKey(currentRequest.ParentHandleId, currentRequest.ParentRequestId); ScheduleRecord record = new ScheduleRecord(recordKey, parentKey, nodeUsed, currentRequest.ProjectFileName, currentRequest.ToolsetVersion, currentRequest.TargetNames); lock (scheduleTableLock) { ErrorUtilities.VerifyThrow(!handleIdToScheduleRecord.ContainsKey(recordKey), "Schedule record should not be in the table"); handleIdToScheduleRecord.Add(recordKey, record); // The ParentHandleId is an invalidEngineHandle when the host is the one who created // the current request if (currentRequest.ParentHandleId != EngineCallback.invalidEngineHandle) { ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(parentKey), "Parent schedule record should be in the table"); ScheduleRecord parentRecord = handleIdToScheduleRecord[parentKey]; if (!parentRecord.Blocked) { blockedRequestsPerNode[parentRecord.EvaluationNode]++; } parentRecord.AddChildRecord(record); } } }
/// <summary> /// Called by the engine to indicate that a particular request is no longer blocked waiting for another /// request to finish building a target /// </summary> internal void NotifyOfUnblockedRequest(BuildRequest currentRequest) { if (!childMode && nodes.Length > 1) { ScheduleRecordKey recordKey = new ScheduleRecordKey(currentRequest.HandleId, currentRequest.RequestId); lock (scheduleTableLock) { ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(recordKey), "Schedule record should be in the table"); handleIdToScheduleRecord[recordKey].Blocked = false; blockedRequestsPerNode[handleIdToScheduleRecord[recordKey].EvaluationNode]--; } } }
/// <summary> /// This method is called when a build request is completed on a particular node. NodeId is never used instead we look up the node from the build request /// and the schedule record table /// </summary> internal void NotifyOfBuildResult(int nodeId, BuildResult buildResult) { if (!childMode && nodes.Length > 1) { // Ignore host requests if (buildResult.HandleId == EngineCallback.invalidEngineHandle) { return; } ScheduleRecordKey recordKey = new ScheduleRecordKey(buildResult.HandleId, buildResult.RequestId); ScheduleRecord scheduleRecord = null; lock (scheduleTableLock) { ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(recordKey), "Schedule record should be in the table"); scheduleRecord = handleIdToScheduleRecord[recordKey]; totalRequestsPerNode[scheduleRecord.EvaluationNode]--; handleIdToScheduleRecord.Remove(recordKey); if (scheduleRecord.ParentKey.HandleId != EngineCallback.invalidEngineHandle) { ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(scheduleRecord.ParentKey), "Parent schedule record should be in the table"); ScheduleRecord parentRecord = handleIdToScheduleRecord[scheduleRecord.ParentKey]; // As long as there are child requests under the parent request the parent request is considered blocked // Remove this build request from the list of requests the parent request is waiting on. This may unblock the parent request parentRecord.ReportChildCompleted(recordKey); // If completing the child request has unblocked the parent request due to all of the the Child requests being completed // decrement the number of blocked requests. if (!parentRecord.Blocked) { blockedRequestsPerNode[parentRecord.EvaluationNode]--; } } } // Dump some interesting information to the console if profile build is turned on by an environment variable if (parentEngine.ProfileBuild && scheduleRecord != null && buildResult.TaskTime != 0) { Console.WriteLine("N " + scheduleRecord.EvaluationNode + " Name " + scheduleRecord.ProjectName + ":" + scheduleRecord.ParentKey.HandleId + ":" + scheduleRecord.ParentKey.RequestId + " Total " + buildResult.TotalTime + " Engine " + buildResult.EngineTime + " Task " + buildResult.TaskTime); } } }
/// <summary> /// Override the equals operator to give valuetype comparison semantics /// </summary> public override bool Equals(object obj) { ScheduleRecordKey other = obj as ScheduleRecordKey; if (other != null) { if (other.handleId == handleId && other.requestId == requestId) { return(true); } return(false); } return(base.Equals(obj)); }
internal ScheduleRecord ( ScheduleRecordKey recordKey, ScheduleRecordKey parentKey, int evaluationNode, string projectName, string toolsVersion, string [] targetsBuild ) { this.recordKey = recordKey; this.parentKey = parentKey; this.evaluationNode = evaluationNode; this.blockedFlag = false; this.projectName = projectName; this.toolsVersion = toolsVersion; this.targetsBuild = targetsBuild; }
/// <summary> /// Called by the engine to indicate that a particular request is blocked waiting for another /// request to finish building a target. /// </summary> internal void NotifyOfBlockedRequest(BuildRequest currentRequest) { if (!childMode && nodes.Length > 1) { ScheduleRecordKey recordKey = new ScheduleRecordKey(currentRequest.HandleId, currentRequest.RequestId); // Ignore host requests if (currentRequest.HandleId == EngineCallback.invalidEngineHandle) { return; } lock (scheduleTableLock) { ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(recordKey), "Schedule record should be in the table"); handleIdToScheduleRecord[recordKey].Blocked = true; blockedRequestsPerNode[handleIdToScheduleRecord[recordKey].EvaluationNode]++; } } }
/// <summary> /// Remove a completed child request possibly unblocking the parent /// </summary> /// <param name="key"></param> internal void ReportChildCompleted(ScheduleRecordKey key) { requestIdToChildRecord.Remove(key); }