/// <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);
        }
        public void TargetInProgressStateCustomSerialization()
        {
            Engine engine = new Engine(@"c:\");
            Project project = ObjectModelHelpers.CreateInMemoryProject(@"
                   <Project DefaultTargets=`t` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`>
                        <PropertyGroup>
                        <OutputPath>bin\Debug\</OutputPath>
                        <AssemblyName>MyAssembly</AssemblyName>
                        <OutputType>Exe</OutputType>
                        <Configuration>Debug</Configuration>
                      </PropertyGroup>
                      <ItemGroup>
                        <Compile Include=`Class1.cs` />
                        <EmbeddedResource Include=`Resource1.txt` />
                        <EmbeddedResource Include=`Resource2.resx` />
                      </ItemGroup>
                      <Target Name='t' DependsOnTargets='Build'/>
                    <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.Targets` />
                    </Project>
                "); 
            EngineCallback engineCallback = new EngineCallback(engine);
            Target build = project.Targets["Build"];
            List<ProjectBuildState> waitingBuildStates = null;

            int handleId = 1;
            string projectFileName = "ProjectFileName";
            string[] targetNames = new string[] { "t" };
            Dictionary<string, string> dictionary = null;
            int requestId = 1;
            BuildRequest request = new BuildRequest(handleId, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false);
            ArrayList targetNamesToBuild = new ArrayList();
            targetNamesToBuild.Add("t");
            ProjectBuildState initiatingRequest = new ProjectBuildState(request, targetNamesToBuild, new BuildEventContext(1, 2, 2, 2));
            initiatingRequest.AddBlockingTarget("Build");
            BuildRequest [] outstandingBuildRequests = null;
            string projectName = "SuperTestProject";
            
            

            TargetInProgessState targetInProgress1 = new TargetInProgessState(
                                                              engineCallback,
                                                              build,
                                                              waitingBuildStates,
                                                              initiatingRequest,
                                                              outstandingBuildRequests,
                                                              projectName
                                                          );
            
            targetInProgress1.ParentTargetsForBuildRequests = null;
            Assertion.AssertNull(targetInProgress1.ParentTargetsForBuildRequests);
            Assertion.Assert(!targetInProgress1.RequestedByHost);

            build = project.Targets["t"];
             request = new BuildRequest(handleId, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false);
            request.IsExternalRequest = true;
            targetNamesToBuild.Add("t");
            initiatingRequest = new ProjectBuildState(request, targetNamesToBuild, new BuildEventContext(1, 2, 2, 2));
            outstandingBuildRequests = new BuildRequest[]{
                new BuildRequest(1, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false),
                new BuildRequest(2, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false),
                new BuildRequest(3, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false),
                new BuildRequest(4, projectFileName, targetNames, (IDictionary)dictionary, null, requestId, false, false)
            };

            TargetInProgessState.TargetIdWrapper originalWrapper = new TargetInProgessState.TargetIdWrapper();
            originalWrapper.id = 1;
            originalWrapper.name = "Wrapper";
            originalWrapper.nodeId = 4;
            originalWrapper.projectId = 6;
            waitingBuildStates = new List<ProjectBuildState>();
            waitingBuildStates.Add(initiatingRequest);

            TargetInProgessState targetInProgress3 = new TargetInProgessState(
                                                              engineCallback,
                                                              build,
                                                              waitingBuildStates,
                                                              initiatingRequest,
                                                              outstandingBuildRequests,
                                                              projectName
                                                          );
            targetInProgress3.ParentTargetsForBuildRequests = new TargetInProgessState.TargetIdWrapper[] { originalWrapper };

            // Stream, writer and reader where the events will be serialized and deserialized from
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);
            BinaryReader reader = new BinaryReader(stream);
            try
            {
                stream.Position = 0;
                // Serialize
                targetInProgress3.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                long streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                TargetInProgessState newInProgressState = new TargetInProgessState();
                newInProgressState.CreateFromStream(reader);
                long streamReadEndPosition = stream.Position;
                Assert.IsTrue(string.Compare(newInProgressState.ProjectName, projectName, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(newInProgressState.TargetId.name, "t", StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsNotNull(newInProgressState.ParentTargets);
                Assert.IsTrue(newInProgressState.OutstandingBuildRequests.Length == 4);
                Assert.IsNotNull(newInProgressState.ParentBuildRequests);
                Assert.IsNotNull(newInProgressState.ParentTargetsForBuildRequests.Length == 1);

                stream.Position = 0;
                // Serialize
                targetInProgress1.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                 streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                newInProgressState = new TargetInProgessState();
                newInProgressState.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsTrue(string.Compare(newInProgressState.ProjectName, projectName,StringComparison.OrdinalIgnoreCase)==0);
                Assert.IsTrue(string.Compare(newInProgressState.TargetId.name,"Build",StringComparison.OrdinalIgnoreCase)==0);
                Assert.IsNotNull(newInProgressState.ParentTargets);
                Assert.IsNull(newInProgressState.OutstandingBuildRequests);
                Assert.IsNotNull(newInProgressState.ParentBuildRequests);

                TargetInProgessState targetInProgress2 = new TargetInProgessState();
                stream.Position = 0;
                // Serialize
                targetInProgress2.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                newInProgressState = new TargetInProgessState();
                newInProgressState.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsNull(newInProgressState.ProjectName);
                Assert.IsNull(newInProgressState.TargetId);
                Assert.IsNull(newInProgressState.ParentTargets);
                Assert.IsNull(newInProgressState.OutstandingBuildRequests);
                Assert.IsNull(newInProgressState.ParentBuildRequests);
            }
            finally
            {
                // Close will close the writer/reader and the underlying stream
                writer.Close();
                reader.Close();
                reader = null;
                stream = null;
                writer = null;
            }
        }
        public void TargetIdWrapperCustomSerialization()
        {
            // Stream, writer and reader where the events will be serialized and deserialized from
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);
            BinaryReader reader = new BinaryReader(stream);
            try
            {
                TargetInProgessState.TargetIdWrapper originalWrapper = new TargetInProgessState.TargetIdWrapper();
                originalWrapper.id = 1;
                originalWrapper.name = "Wrapper";
                originalWrapper.nodeId = 4;
                originalWrapper.projectId = 6;

                stream.Position = 0;
                // Serialize
                originalWrapper.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                long streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                TargetInProgessState.TargetIdWrapper newWrapper = new TargetInProgessState.TargetIdWrapper();
                newWrapper.CreateFromStream(reader);
                long streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(originalWrapper.Equals(newWrapper));
                Assert.IsTrue(1 == newWrapper.id);

                originalWrapper = new TargetInProgessState.TargetIdWrapper();
                originalWrapper.id = 4;
                originalWrapper.name = string.Empty;
                originalWrapper.nodeId = 6;
                originalWrapper.projectId = 8;
                
                stream.Position = 0;
                // Serialize
                originalWrapper.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                newWrapper = new TargetInProgessState.TargetIdWrapper();
                newWrapper.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(originalWrapper.Equals(newWrapper));
                Assert.IsTrue(4 == newWrapper.id);

                originalWrapper = new TargetInProgessState.TargetIdWrapper();
                originalWrapper.id = 10;
                originalWrapper.name = null;
                originalWrapper.nodeId = 6;
                originalWrapper.projectId = 8;

                stream.Position = 0;
                // Serialize
                originalWrapper.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                newWrapper = new TargetInProgessState.TargetIdWrapper();
                newWrapper.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(originalWrapper.Equals(newWrapper));
                Assert.IsTrue(10 == newWrapper.id);
            }
            finally
            {
                // Close will close the writer/reader and the underlying stream
                writer.Close();
                reader.Close();
                reader = null;
                stream = null;
                writer = null;
            }

        }
Example #4
0
        /// <summary>
        /// For each target that has a cross node build request waiting for it to complete, iterate
        /// over the list of outstanding requests and find the matching out going request. Once
        /// the matching request is found - link the parent and child targets.
        /// </summary>
        private void LinkCrossNodeBuildRequests()
        {
            foreach (GraphNode node in dependencyGraph.Values)
            {
                TargetInProgessState.TargetIdWrapper[] parentsForBuildRequests = 
                    new TargetInProgessState.TargetIdWrapper[node.targetState.ParentBuildRequests.Count];

                for (int j = 0; j < node.targetState.ParentBuildRequests.Count; j++ )
                {
                    BuildRequest buildRequest = node.targetState.ParentBuildRequests[j];
                    int nodeIndex = buildRequest.NodeIndex;
                    int handleId = buildRequest.HandleId;
                    int requestId = buildRequest.RequestId;
                    bool foundParent = false;

                    // Skip requests that originated from the host
                    if (handleId == EngineCallback.invalidEngineHandle)
                    {
                        node.isRoot = true;
                        continue;
                    }

                    // If the request being analyzed came from one of the child nodes, its incoming external request's
                    // handleId will point at a routing context on the parent engine. If the outgoing request 
                    // orginated from another child the two requests (outgoing and incoming) point at different 
                    // routing contexts. In that case it is necessary to unwind the incoming request to the routing 
                    // context of the outgoing request. If outgoing request originated from the parent node - 
                    // there will be only one routing request.
                    if (node.targetState.TargetId.nodeId != 0)
                    {
                        ExecutionContext executionContext = engineCallback.GetExecutionContextFromHandleId(buildRequest.HandleId);
                        RequestRoutingContext routingContext = executionContext as RequestRoutingContext;
                        if (routingContext != null && routingContext.ParentHandleId != EngineCallback.invalidEngineHandle)
                        {
                            ExecutionContext nextExecutionContext = engineCallback.GetExecutionContextFromHandleId(routingContext.ParentHandleId);

                            if (nextExecutionContext is RequestRoutingContext)
                            {
                                nodeIndex   = nextExecutionContext.NodeIndex;
                                handleId = routingContext.ParentHandleId;
                                requestId   = routingContext.ParentRequestId;
                            }
                        }
                        else
                        {
                            // Skip requests that originated from the host
                            node.isRoot = true;
                            continue;
                        }
                    }

                    // Iterate over all outstanding requests until a match is found
                    foreach (DictionaryEntry entry in outstandingExternalRequests)
                    {
                        BuildRequest[] externalRequests = (BuildRequest[])entry.Value;
                        for (int i = 0; i < externalRequests.Length && !foundParent; i++)
                        {
                            if (handleId == externalRequests[i].HandleId &&
                                requestId == externalRequests[i].RequestId &&
                                nodeIndex == externalRequests[i].NodeIndex)
                            {
                                // Verify that the project name is the same
                                ErrorUtilities.VerifyThrow(
                                    String.Compare(buildRequest.ProjectFileName, externalRequests[i].ProjectFileName, StringComparison.OrdinalIgnoreCase) == 0,
                                    "The two requests should have the same project name");

                                // Link the two graph nodes together
                                GraphNode parentNode = (GraphNode)dependencyGraph[entry.Key];
                                parentNode.children.Add(node);

                                parentsForBuildRequests[j] = parentNode.targetState.TargetId;

                                foundParent = true;
                            }
                        }

                        if (foundParent)
                        {
                            break;
                        }
                    }
                }
                node.targetState.ParentTargetsForBuildRequests = parentsForBuildRequests;
            }
        }
Example #5
0
        /// <summary>
        /// For each target that has a cross node build request waiting for it to complete, iterate
        /// over the list of outstanding requests and find the matching out going request. Once
        /// the matching request is found - link the parent and child targets.
        /// </summary>
        private void LinkCrossNodeBuildRequests()
        {
            foreach (GraphNode node in dependencyGraph.Values)
            {
                TargetInProgessState.TargetIdWrapper[] parentsForBuildRequests =
                    new TargetInProgessState.TargetIdWrapper[node.targetState.ParentBuildRequests.Count];

                for (int j = 0; j < node.targetState.ParentBuildRequests.Count; j++)
                {
                    BuildRequest buildRequest = node.targetState.ParentBuildRequests[j];
                    int          nodeIndex    = buildRequest.NodeIndex;
                    int          handleId     = buildRequest.HandleId;
                    int          requestId    = buildRequest.RequestId;
                    bool         foundParent  = false;

                    // Skip requests that originated from the host
                    if (handleId == EngineCallback.invalidEngineHandle)
                    {
                        node.isRoot = true;
                        continue;
                    }

                    // If the request being analyzed came from one of the child nodes, its incoming external request's
                    // handleId will point at a routing context on the parent engine. If the outgoing request
                    // orginated from another child the two requests (outgoing and incoming) point at different
                    // routing contexts. In that case it is necessary to unwind the incoming request to the routing
                    // context of the outgoing request. If outgoing request originated from the parent node -
                    // there will be only one routing request.
                    if (node.targetState.TargetId.nodeId != 0)
                    {
                        ExecutionContext      executionContext = engineCallback.GetExecutionContextFromHandleId(buildRequest.HandleId);
                        RequestRoutingContext routingContext   = executionContext as RequestRoutingContext;
                        if (routingContext != null && routingContext.ParentHandleId != EngineCallback.invalidEngineHandle)
                        {
                            ExecutionContext nextExecutionContext = engineCallback.GetExecutionContextFromHandleId(routingContext.ParentHandleId);

                            if (nextExecutionContext is RequestRoutingContext)
                            {
                                nodeIndex = nextExecutionContext.NodeIndex;
                                handleId  = routingContext.ParentHandleId;
                                requestId = routingContext.ParentRequestId;
                            }
                        }
                        else
                        {
                            // Skip requests that originated from the host
                            node.isRoot = true;
                            continue;
                        }
                    }

                    // Iterate over all outstanding requests until a match is found
                    foreach (DictionaryEntry entry in outstandingExternalRequests)
                    {
                        BuildRequest[] externalRequests = (BuildRequest[])entry.Value;
                        for (int i = 0; i < externalRequests.Length && !foundParent; i++)
                        {
                            if (handleId == externalRequests[i].HandleId &&
                                requestId == externalRequests[i].RequestId &&
                                nodeIndex == externalRequests[i].NodeIndex)
                            {
                                // Verify that the project name is the same
                                ErrorUtilities.VerifyThrow(
                                    String.Compare(buildRequest.ProjectFileName, externalRequests[i].ProjectFileName, StringComparison.OrdinalIgnoreCase) == 0,
                                    "The two requests should have the same project name");

                                // Link the two graph nodes together
                                GraphNode parentNode = (GraphNode)dependencyGraph[entry.Key];
                                parentNode.children.Add(node);

                                parentsForBuildRequests[j] = parentNode.targetState.TargetId;

                                foundParent = true;
                            }
                        }

                        if (foundParent)
                        {
                            break;
                        }
                    }
                }
                node.targetState.ParentTargetsForBuildRequests = parentsForBuildRequests;
            }
        }