| File: BackEnd\Components\Scheduler\ScheduleResponse.cs | Web Access |
| Project: src\msbuild\src\Build\Microsoft.Build.csproj (Microsoft.Build) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Execution; #nullable disable namespace Microsoft.Build.BackEnd { /// <summary> /// The type of action to take in response to a scheduling request. /// </summary> internal enum ScheduleActionType { /// <summary> /// The response indicates that no action should be taken. /// </summary> NoAction, /// <summary> /// The response indicates that the request should be sent to the specified node. /// </summary> Schedule, /// <summary> /// The response indicates that the request should be send to the specified node, /// along with the configuration for the request. /// </summary> ScheduleWithConfiguration, /// <summary> /// The response has results for a particular blocked request /// </summary> ReportResults, /// <summary> /// The specified request id should now resume execution /// </summary> ResumeExecution, /// <summary> /// The response indicates that a new node should be created rather than scheduling this request. /// The request may be scheduled at a later time. /// </summary> CreateNode, /// <summary> /// The response indicates that the submission is complete. /// </summary> SubmissionComplete, /// <summary> /// The last action caused a circular dependency which cannot be resolved. /// </summary> CircularDependency } /// <summary> /// A response from the scheduler indicating where a build request should be handled. /// </summary> internal class ScheduleResponse { /// <summary> /// The type of action to take on this response. /// </summary> internal readonly ScheduleActionType Action; /// <summary> /// The node ID to which the request should be sent. /// </summary> internal readonly int NodeId; /// <summary> /// The results for a completed submission. /// </summary> internal readonly BuildResult BuildResult; /// <summary> /// The build request to send. /// </summary> internal readonly BuildRequest BuildRequest; /// <summary> /// The unblocking information. /// </summary> internal readonly BuildRequestUnblocker Unblocker; /// <summary> /// The type of node we must create. /// </summary> internal readonly NodeAffinity RequiredNodeType; /// <summary> /// The number of nodes of the requested affinity to create. /// </summary> internal readonly int NumberOfNodesToCreate; /// <summary> /// Constructs a response where no action should be taken. /// </summary> internal ScheduleResponse(ScheduleActionType type) { Action = type; } /// <summary> /// Constructs a response indicating what type of node we need to create. /// </summary> private ScheduleResponse(NodeAffinity affinity, int count) { Action = ScheduleActionType.CreateNode; RequiredNodeType = affinity; NumberOfNodesToCreate = count; } /// <summary> /// Constructs a response indicating that a specific submission has completed. /// </summary> private ScheduleResponse(BuildResult result) { Action = ScheduleActionType.SubmissionComplete; BuildResult = result; } /// <summary> /// Constructs a response indicating there is a circular dependency caused by the specified request. /// </summary> private ScheduleResponse(int nodeId, BuildRequest parentRequest, BuildRequest requestCausingCircularDependency) { Action = ScheduleActionType.CircularDependency; BuildRequest = requestCausingCircularDependency; NodeId = nodeId; Unblocker = new BuildRequestUnblocker(parentRequest, new BuildResult(requestCausingCircularDependency, true /* circularDependency */)); } /// <summary> /// Constructs a response where a request should be scheduled. /// </summary> /// <param name="node">The node ID to which the request should be sent.</param> /// <param name="request">The request to send.</param> /// <param name="sendConfiguration"><code>true</code> to send the configuration, otherwise <code>false</code>.</param> private ScheduleResponse(int node, BuildRequest request, bool sendConfiguration) { Action = sendConfiguration ? ScheduleActionType.ScheduleWithConfiguration : ScheduleActionType.Schedule; NodeId = node; BuildRequest = request; } /// <summary> /// Constructs a response where a result should be sent or execution should be resumed. /// </summary> /// <param name="node">The node ID to which the result should be sent.</param> /// <param name="unblocker">The result to send.</param> private ScheduleResponse(int node, BuildRequestUnblocker unblocker) { Action = (unblocker.Result == null) ? ScheduleActionType.ResumeExecution : ScheduleActionType.ReportResults; NodeId = node; Unblocker = unblocker; BuildResult = unblocker.Result; } /// <summary> /// Creates a Schedule or ScheduleWithConfiguration response /// </summary> /// <param name="node">The node to which the response should be sent.</param> /// <param name="requestToSchedule">The request to be scheduled.</param> /// <param name="sendConfiguration">Flag indicating whether or not the configuration for the request must be sent to the node as well.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateScheduleResponse(int node, BuildRequest requestToSchedule, bool sendConfiguration) { return new ScheduleResponse(node, requestToSchedule, sendConfiguration); } /// <summary> /// Creates a ReportResult response. /// </summary> /// <param name="node">The node to which the response should be sent.</param> /// <param name="resultToReport">The result to be reported.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateReportResultResponse(int node, BuildResult resultToReport) { return new ScheduleResponse(node, new BuildRequestUnblocker(resultToReport)); } /// <summary> /// Creates a ResumeExecution response. /// </summary> /// <param name="node">The node to which the response should be sent.</param> /// <param name="globalRequestIdToResume">The request which should resume executing.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateResumeExecutionResponse(int node, int globalRequestIdToResume) { return new ScheduleResponse(node, new BuildRequestUnblocker(globalRequestIdToResume)); } /// <summary> /// Creates a CircularDependency response. /// </summary> /// <param name="node">The node to which the response should be sent.</param> /// <param name="parentRequest">The request which attempted to invoke the request causing the circular dependency.</param> /// <param name="requestCausingCircularDependency">The request which caused the circular dependency.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateCircularDependencyResponse(int node, BuildRequest parentRequest, BuildRequest requestCausingCircularDependency) { return new ScheduleResponse(node, parentRequest, requestCausingCircularDependency); } /// <summary> /// Creates a SubmissionComplete response. /// </summary> /// <param name="rootRequestResult">The result for the submission's root request.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateSubmissionCompleteResponse(BuildResult rootRequestResult) { return new ScheduleResponse(rootRequestResult); } /// <summary> /// Create a CreateNode response /// </summary> /// <param name="typeOfNodeToCreate">The type of node to create.</param> /// <param name="count">The number of new nodes of that particular affinity to create.</param> /// <returns>The ScheduleResponse.</returns> public static ScheduleResponse CreateNewNodeResponse(NodeAffinity typeOfNodeToCreate, int count) { return new ScheduleResponse(typeOfNodeToCreate, count); } /// <summary> /// Returns the schedule response as a descriptive string. /// </summary> public override string ToString() { switch (Action) { case ScheduleActionType.ReportResults: case ScheduleActionType.ResumeExecution: return $"Act: {Action} Node: {NodeId} Request: {Unblocker.BlockedRequestId}"; case ScheduleActionType.Schedule: return $"Act: {Action} Node: {NodeId} Request: {BuildRequest.GlobalRequestId} Parent {BuildRequest.ParentGlobalRequestId}"; case ScheduleActionType.ScheduleWithConfiguration: return $"Act: {Action} Node: {NodeId} Request: {BuildRequest.GlobalRequestId} Parent {BuildRequest.ParentGlobalRequestId} Configuration: {BuildRequest.ConfigurationId}"; case ScheduleActionType.CircularDependency: return $"Act: {Action} Node: {NodeId} Request: {BuildRequest.GlobalRequestId} Parent {BuildRequest.ParentGlobalRequestId} Configuration: {BuildRequest.ConfigurationId}"; case ScheduleActionType.SubmissionComplete: return $"Act: {Action} Submission: {BuildResult.SubmissionId}"; case ScheduleActionType.CreateNode: return $"Act: {Action} Count: {NumberOfNodesToCreate}"; case ScheduleActionType.NoAction: default: return $"Act: {Action}"; } } } }