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