1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.Collections.Generic; 6 using System.Collections; 7 using System.Text; 8 9 using Microsoft.Build.Framework; 10 using Microsoft.Build.BuildEngine.Shared; 11 12 namespace Microsoft.Build.BuildEngine 13 { 14 #region Base Command Class 15 /// <summary> 16 /// Base class for classes which wrap operations that should be executed on the engine thread 17 /// </summary> 18 internal class EngineCommand 19 { Execute(Engine parentEngine)20 internal virtual void Execute(Engine parentEngine) 21 { 22 ErrorUtilities.VerifyThrow(false, "Should overwrite the execute method"); 23 } 24 } 25 #endregion 26 27 #region RequestStatus 28 /// <summary> 29 /// Wrapper class for a node status request 30 /// </summary> 31 internal class RequestStatusEngineCommand : EngineCommand 32 { RequestStatusEngineCommand(int requestId)33 internal RequestStatusEngineCommand(int requestId) 34 { 35 this.requestId = requestId; 36 } 37 Execute(Engine parentEngine)38 internal override void Execute(Engine parentEngine) 39 { 40 NodeStatus nodeStatus = parentEngine.RequestStatus(requestId); 41 ErrorUtilities.VerifyThrow(parentEngine.Router.ParentNode != null, 42 "Method should be called only on child nodes"); 43 parentEngine.Router.ParentNode.PostStatus(nodeStatus, false /* don't block waiting on the send */); 44 } 45 46 #region Data 47 private int requestId; 48 #endregion 49 } 50 #endregion 51 52 #region HostBuildRequestCompletion 53 /// <summary> 54 /// Wrapper class for a reporting completion of a host build request to the engine 55 /// </summary> 56 internal class HostBuildRequestCompletionEngineCommand : EngineCommand 57 { HostBuildRequestCompletionEngineCommand()58 internal HostBuildRequestCompletionEngineCommand() 59 { 60 } 61 Execute(Engine parentEngine)62 internal override void Execute(Engine parentEngine) 63 { 64 parentEngine.DecrementProjectsInProgress(); 65 } 66 67 #region Data 68 #endregion 69 } 70 #endregion 71 72 #region ReportException 73 /// <summary> 74 /// Wrapper class for a reporting completion of a host build request to the engine 75 /// </summary> 76 internal class ReportExceptionEngineCommand : EngineCommand 77 { ReportExceptionEngineCommand(Exception e)78 internal ReportExceptionEngineCommand(Exception e) 79 { 80 this.e = e; 81 } 82 Execute(Engine parentEngine)83 internal override void Execute(Engine parentEngine) 84 { 85 // Figure out if the exception occured on a parent or child engine 86 // On the parent rethrow nicely and make sure the finallies run 87 // On the child try to communicate with the parent - if success, exit 88 // if failure rethrow and hope Watson will pick the exception up 89 string message = ResourceUtilities.FormatResourceString("RethrownEngineException"); 90 throw new Exception(message, e); 91 } 92 93 #region Data 94 private Exception e; 95 #endregion 96 } 97 #endregion 98 99 #region ChangeTraversalType 100 /// <summary> 101 /// Wrapper class for a changing the traversal approach used by the TEM 102 /// </summary> 103 internal class ChangeTraversalTypeCommand : EngineCommand 104 { 105 /// <summary> 106 /// Create a command that will switch the traversal of the system to breadthFirst traversal or depth first traveral. 107 /// changeLocalTraversalOnly is used to determine whether or not to change the traversal for the whole system or only the current node. 108 /// changeLocalTraversalOnly is set to true in the when a node is first started and in the updateNodeSettings method as these traversal changes are for the local node only. The reason 109 /// is because updateNodeSettings is called when the parent has told the node to switch traversal types, there is no need to forward the change to the engine again. 110 /// Also, when a node starts up it is set to breadth first traversal, this is the default so the parent engine need not be notified of this change. 111 /// </summary> ChangeTraversalTypeCommand(bool breadthFirstTraversal, bool changeLocalTraversalOnly)112 internal ChangeTraversalTypeCommand(bool breadthFirstTraversal, bool changeLocalTraversalOnly) 113 { 114 this.breadthFirstTraversal = breadthFirstTraversal; 115 this.changeLocalTraversalOnly = changeLocalTraversalOnly; 116 } 117 Execute(Engine parentEngine)118 internal override void Execute(Engine parentEngine) 119 { 120 parentEngine.NodeManager.TaskExecutionModule.UseBreadthFirstTraversal = breadthFirstTraversal; 121 if (!parentEngine.Router.ChildMode) 122 { 123 parentEngine.NodeManager.ChangeNodeTraversalType(breadthFirstTraversal); 124 } 125 else 126 { 127 if (!changeLocalTraversalOnly) 128 { 129 parentEngine.Router.ParentNode.PostStatus(new NodeStatus(breadthFirstTraversal), false /* don't block waiting on the send */); 130 } 131 } 132 } 133 134 #region Data 135 private bool breadthFirstTraversal; 136 private bool changeLocalTraversalOnly; 137 #endregion 138 } 139 #endregion 140 } 141