public void Initialize()
        {
            // Create some items and place them in a dictionary
            // Add some include information so that when we check the final 
            // item spec we can verify that the item was recreated properly
            BuildItem buildItem1 = new BuildItem("BuildItem1", "Item1");
            buildItem1.Include = "TestInclude1";
            BuildItem[] buildItems = new BuildItem[1];
            buildItems[0] = buildItem1;
            Dictionary<object, object> dictionary = new Dictionary<object, object>();
            dictionary.Add("TaskItems", buildItems);

            Hashtable resultByTargetSuccess = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultByTargetSuccess.Add("TaskItems", Target.BuildState.CompletedSuccessfully);
            Hashtable resultByTargetFailure = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultByTargetFailure.Add("TaskItems", Target.BuildState.CompletedUnsuccessfully);
            Hashtable resultByTargetSkipped = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultByTargetSkipped.Add("TaskItems", Target.BuildState.Skipped);

            resultWithOutputs = new BuildResult(dictionary, resultByTargetSuccess, true, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0);
            failedResult = new BuildResult(dictionary, resultByTargetFailure, false, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0);
            uncacheableResult = new BuildResult(dictionary, resultByTargetSkipped, true, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0);

            cacheScope = new CacheScope("temp.proj", new BuildPropertyGroup(), "3.5");
        }
示例#2
0
        public void Initialize()
        {
            // Create some items and place them in a dictionary
            // Add some include information so that when we check the final 
            // item spec we can verify that the item was recreated properly
            BuildItem[] buildItems = new BuildItem[1];
            buildItems[0] = new BuildItem("BuildItem1", "Item1");
            Dictionary<object, object> dictionary1 = new Dictionary<object, object>();
            dictionary1.Add("Target1", buildItems);
            Hashtable resultsByTarget1 = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultsByTarget1.Add("Target1", Target.BuildState.CompletedSuccessfully);

            Dictionary<object, object> dictionary2 = new Dictionary<object, object>();
            dictionary2.Add("Target2", buildItems);
            dictionary2.Add("Target3", null);
            Hashtable resultsByTarget2 = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultsByTarget2.Add("Target2", Target.BuildState.CompletedSuccessfully);
            resultsByTarget2.Add("Target3", Target.BuildState.CompletedSuccessfully);

            Dictionary<object, object> dictionary3 = new Dictionary<object, object>();
            dictionary3.Add("Target4", buildItems);
            Hashtable resultsByTarget3 = new Hashtable(StringComparer.OrdinalIgnoreCase);
            resultsByTarget3.Add("Target4", Target.BuildState.Skipped);

            resultWith0Outputs = new BuildResult(new Hashtable(), new Hashtable(StringComparer.OrdinalIgnoreCase), true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
            resultWith1Outputs = new BuildResult(dictionary1, resultsByTarget1, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
            resultWith2Outputs = new BuildResult(dictionary2, resultsByTarget2, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
            uncacheableResult = new BuildResult(dictionary3, resultsByTarget3, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
        }
示例#3
0
        public void TestConstructorsAndProperties()
        {
            BuildResult resultWithOutputsFromBuildResult = new BuildResult(resultWithOutputs, false /* shallow copy */);
            Assert.IsNotNull(resultWithOutputsFromBuildResult.OutputsByTarget, "Exepcted resultWithOutputsFromBuildResult.OutputsByTarget to not be null");
            Assert.IsTrue(resultWithOutputsFromBuildResult.EvaluationResult, "Expected resultWithOutputsFromBuildResult.EvaluationResult to be true");
            Assert.AreEqual(0, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 0");
            Assert.AreEqual(1, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 1");
            Assert.AreEqual(2, resultWithOutputsFromBuildResult.ProjectId, "Expected resultWithOutputsFromBuildResult.ProjectId to be 1");

            // Test some setters which are not set otherwise during the tests
            resultWithOutputsFromBuildResult.HandleId = 3;
            resultWithOutputsFromBuildResult.RequestId = 4;
            Assert.AreEqual(3, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 3");
            Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4");

            resultWithOutputsFromBuildResult = new BuildResult(resultWithOutputs, true /* deep copy */);
            Assert.IsNotNull(resultWithOutputsFromBuildResult.OutputsByTarget, "Exepcted resultWithOutputsFromBuildResult.OutputsByTarget to not be null");
            Assert.IsTrue(resultWithOutputsFromBuildResult.EvaluationResult, "Expected resultWithOutputsFromBuildResult.EvaluationResult to be true");
            Assert.AreEqual(0, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 0");
            Assert.AreEqual(1, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 1");
            Assert.AreEqual(2, resultWithOutputsFromBuildResult.ProjectId, "Expected resultWithOutputsFromBuildResult.ProjectId to be 1");
            
            // Test some setters which are not set otherwise during the tests
            resultWithOutputsFromBuildResult.HandleId = 3;
            resultWithOutputsFromBuildResult.RequestId = 4;
            Assert.AreEqual(3, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 3");
            Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4");
            
            // Test the setting of RequestId
            resultWithOutputsFromBuildResult.RequestId = 4;
            Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4");
        }
示例#4
0
        /// <summary>
        /// Copy constructor
        /// </summary>
        internal BuildResult
            (BuildResult buildResultToCopy, bool deepCopy)
        {
            ErrorUtilities.VerifyThrowArgumentNull(buildResultToCopy, "Cannot have a null build result passed in");
            this.flags = buildResultToCopy.flags;
            this.handleId = buildResultToCopy.handleId;
            this.requestId = buildResultToCopy.requestId;
            this.projectId = buildResultToCopy.projectId;
            this.outputsByTarget = new Hashtable();
            this.defaultTargets = buildResultToCopy.defaultTargets;
            this.initialTargets = buildResultToCopy.initialTargets;
            this.resultByTarget = new Hashtable(buildResultToCopy.resultByTarget, StringComparer.OrdinalIgnoreCase);

            if (buildResultToCopy.outputsByTarget == null)
            {
                return;
            }

            if (deepCopy)
            {
                // Copy all the old data
                foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget)
                {
                    // Make deep copies of all the target outputs before
                    // passing them back
                    BuildItem[] originalArray = (BuildItem[])entry.Value;
                    BuildItem[] itemArray = new BuildItem[originalArray.Length];
                    for (int i = 0; i < originalArray.Length; i++)
                    {
                        if (!originalArray[i].IsUninitializedItem)
                        {
                            itemArray[i] = originalArray[i].Clone();
                            itemArray[i].CloneVirtualMetadata();
                        }
                        else
                        {
                            itemArray[i] = new BuildItem(null, originalArray[i].FinalItemSpecEscaped);
                        }
                    }
                    
                    this.outputsByTarget.Add(entry.Key, itemArray);
                }
            }
            else
            {
                // Create a new hashtable but point at the same data
                foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget)
                {
                    this.outputsByTarget.Add(entry.Key, entry.Value);
                }
            }
        }
示例#5
0
        public void Initialize()
        {
            // Create some items and place them in a dictionary
            // Add some include information so that when we check the final 
            // item spec we can verify that the item was recreated properly
            buildItem1.Include = "TestInclude1";
            buildItem2.Include = "TestInclude2";

            BuildItem[] taskItems = new BuildItem[2];
            taskItems[0] = buildItem1;
            taskItems[1] = buildItem2;

            Dictionary<object, object> dictionary = new Dictionary<object, object>();
            dictionary.Add("TaskItems", taskItems);
            resultNoOutputs = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
            resultWithOutputs = new BuildResult(dictionary, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
        }
示例#6
0
文件: Engine.cs 项目: nikson/msbuild
        /// <summary>
        /// Pretend we're actually building a project when really we're just retrieving the results from the cache.
        /// </summary>
        /// <param name="buildRequest"></param>
        /// <param name="projectFileInfo"></param>
        /// <param name="actuallyBuiltTargets"></param>
        /// <param name="cachedResult"></param>
        private void ProcessCachedResult
        (
            BuildRequest buildRequest, 
            FileInfo projectFileInfo, 
            ArrayList actuallyBuiltTargets, 
            BuildResult cachedResult
        )
        {
            buildRequest.InitializeFromCachedResult(cachedResult);

            if (Engine.debugMode)
            {
                Console.WriteLine("===Reusing cached result for " + buildRequest.GetTargetNamesList() + " in " +
                                   buildRequest.ProjectFileName + " result is " + buildRequest.BuildSucceeded + " EngineNodeID: " + this.nodeId);
            }

            BuildEventContext requestContext = buildRequest.ParentBuildEventContext;
            BuildEventContext currentContext = new BuildEventContext(this.nodeId, BuildEventContext.InvalidTargetId, GetNextProjectId(), BuildEventContext.InvalidTaskId);

            primaryLoggingServices.LogProjectStarted(cachedResult.ProjectId, requestContext, currentContext, projectFileInfo.FullName,
                buildRequest.GetTargetNamesList(),
                new BuildPropertyGroupProxy(new BuildPropertyGroup()),
                new BuildItemGroupProxy(new BuildItemGroup()));
            primaryLoggingServices.LogComment(currentContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", buildRequest.ToolsetVersion);

            for (int i = 0; i < actuallyBuiltTargets.Count; i++)
            {
                string builtTargetName = EscapingUtilities.UnescapeAll((string)actuallyBuiltTargets[i]);
                Target.BuildState buildState = (Target.BuildState)cachedResult.ResultByTarget[builtTargetName];
                buildRequest.ResultByTarget[builtTargetName] = buildState;

                primaryLoggingServices.LogComment(currentContext,
                    ((buildState == Target.BuildState.CompletedSuccessfully) ? "TargetAlreadyCompleteSuccess" : "TargetAlreadyCompleteFailure"),
                    builtTargetName);

                if (buildState == Target.BuildState.CompletedUnsuccessfully)
                {
                    break;
                }
            }

            primaryLoggingServices.LogProjectFinished(currentContext, projectFileInfo.FullName, cachedResult.EvaluationResult);

            if (!buildRequest.IsGeneratedRequest)
            {
                CheckForBuildCompletion();
            }
            else
            {
                Router.PostDoneNotice(buildRequest);
            }
        }
示例#7
0
文件: Node.cs 项目: nikson/msbuild
        /// <summary>
        /// This method lets the engine provide node with results of an evaluation it was waiting on.
        /// </summary>
        internal void PostBuildResult(BuildResult buildResult)
        {
            ErrorUtilities.VerifyThrow(localEngine != null, "Local engine should be initialized");

            // Figure out the local handle id
            NodeRequestMapping nodeRequestMapping = null;
            try
            {
                lock (requestToLocalIdMapping)
                {
                    nodeRequestMapping = (NodeRequestMapping)requestToLocalIdMapping[buildResult.RequestId];
                    requestToLocalIdMapping.Remove(buildResult.RequestId);
                }

                if (Engine.debugMode)
                {
                    Console.WriteLine(nodeId + ": Got result for Request Id " + buildResult.RequestId);
                    Console.WriteLine(nodeId + ": Received result for HandleId " + buildResult.HandleId + ":" + buildResult.RequestId + " mapped to " + nodeRequestMapping.HandleId + ":" + nodeRequestMapping.RequestId);
                }

                buildResult.HandleId = nodeRequestMapping.HandleId;
                buildResult.RequestId = nodeRequestMapping.RequestId;
                nodeRequestMapping.AddResultToCache(buildResult);
                
                // posts the result to the inproc node
                localEngine.Router.PostDoneNotice(0, buildResult);
            }
            catch (Exception ex)
            {
                ReportUnhandledError(ex);
            }
        }
示例#8
0
 private static void CompareBuildResult(BuildResult result1, BuildResult result2)
 {
     Assert.AreEqual(result1.HandleId, result2.HandleId, "Expected HandleId to Match");
     Assert.AreEqual(result1.RequestId, result2.RequestId, "Expected RequestId to Match");
     Assert.AreEqual(result1.ProjectId, result2.ProjectId, "Expected ProjectId to Match");
     Assert.AreEqual(result1.UseResultCache, result2.UseResultCache, "Expected UseResultCache to Match");
     Assert.IsTrue(string.Compare(result1.InitialTargets, result2.InitialTargets, StringComparison.OrdinalIgnoreCase) == 0, "Expected InitialTargets to Match");
     Assert.IsTrue(string.Compare(result1.DefaultTargets, result2.DefaultTargets, StringComparison.OrdinalIgnoreCase) == 0, "Expected DefaultTargets to Match");
 }
示例#9
0
 public void TestUncacheableProperty()
 {
     BuildResult resultCacheable = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, false, string.Empty, string.Empty, 0, 0, 0);
     Assert.IsFalse(resultCacheable.UseResultCache, "Expected resultCacheable.UseResultCache to be false");
     BuildResult resultUncacheable = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0);
     Assert.IsTrue(resultUncacheable.UseResultCache, "Expected resultUncacheable.UseResultCache to be true");
 }
示例#10
0
        /// <summary>
        /// This method is used by the child node to post results of a build request back to the
        /// parent node. The parent node then decides if need to re-route the results to another node
        /// that requested the evaluation or if it will consume the result locally
        /// </summary>
        /// <param name="buildResult"></param>
        public void PostBuildResultToHost(BuildResult buildResult)
        {
            RequestRoutingContext routingContext = GetRoutingContextFromHandleId(buildResult.HandleId);
            ErrorUtilities.VerifyThrow(routingContext.CacheScope != null, "Cache scope should be created for this context");

            // Cache the results
            routingContext.CacheScope.AddCacheEntryForBuildResults(buildResult);
            
            if (Engine.debugMode)
            {
                Console.WriteLine("Received result for HandleId " + buildResult.HandleId + ":" + buildResult.RequestId + " mapped to " + routingContext.ParentHandleId + ":" + routingContext.ParentRequestId);
            }

            // Update the results with the original handle id and request id, so that 
            buildResult.HandleId = routingContext.ParentHandleId;
       
            // If the build result is created from a generated build request a done notice should be posted as other targets could be waiting for this target to finish
            if (buildResult.HandleId != invalidEngineHandle)
            {
                buildResult.RequestId = routingContext.ParentRequestId;
                parentEngine.Router.PostDoneNotice(routingContext.ParentNodeIndex, buildResult);
            }
            else // The build results need to be stored into the build request so they can be sent back to the host that requested the build
            {
                routingContext.TriggeringBuildRequest.OutputsByTarget = buildResult.OutputsByTarget;
                routingContext.TriggeringBuildRequest.BuildSucceeded = buildResult.EvaluationResult;
                routingContext.TriggeringBuildRequest.BuildCompleted = true;
                parentEngine.PostEngineCommand(new HostBuildRequestCompletionEngineCommand());
            }
            
            // At this point the execution context we created for the execution of this build request can be deleted
            lock (freedContexts)
            {
                freedContexts.Add(routingContext);
            }
        }
示例#11
0
 internal LocalCallDescriptorForPostBuildResult(BuildResult buildResult)
     : base(LocalCallType.PostBuildResult)
 {
     this.buildResult = buildResult;
 }
        internal virtual ReferenceNode CreateReferenceNode(string referenceType, ProjectElement element, BuildResult buildResult)
        {
            ReferenceNode node = null;
            if (referenceType == ProjectFileConstants.COMReference)
            {
                node = this.CreateComReferenceNode(element);
            }
            else if (referenceType == ProjectFileConstants.Reference)
            {
                node = this.CreateAssemblyReferenceNode(element, buildResult);
            }
            else if (referenceType == ProjectFileConstants.ProjectReference)
            {
                node = this.CreateProjectReferenceNode(element);
                EnableCachingForProjectReferencesInBatchUpdate(node);
            }

            return node;
        }
示例#13
0
 internal void AddResultToCache(BuildResult buildResult)
 {
     resultsCache.AddCacheEntryForBuildResults(buildResult);
 }
示例#14
0
 internal static BuildResult CreateFromStream(BinaryReader reader)
 {
     BuildResult buildResult = new BuildResult();
     #region OutputsByTarget
     if (reader.ReadByte() == 0)
     {
         buildResult.outputsByTarget = null;
     }
     else
     {
         int numberOfElements = reader.ReadInt32();
         buildResult.outputsByTarget = new Hashtable(numberOfElements, StringComparer.OrdinalIgnoreCase);
         for (int i = 0; i < numberOfElements; i++)
         {
             string key = reader.ReadString();
             BuildItem[] value = null;
             if (reader.ReadByte() != 0)
             {
                 int sizeOfArray = reader.ReadInt32();
                 value = new BuildItem[sizeOfArray];
                 for (int j = 0; j < sizeOfArray; j++)
                 {
                     BuildItem itemToAdd = null;
                     if (reader.ReadByte() != 0)
                     {
                         itemToAdd = new BuildItem(null, string.Empty);
                         itemToAdd.CreateFromStream(reader);
                     }
                     value[j] = itemToAdd;
                 }
             }
             buildResult.outputsByTarget.Add(key, value);
         }
     }
     #endregion
     #region ResultsByTarget
     //Write Number of HashItems
     int numberOfHashKeyValuePairs = reader.ReadInt32();
     buildResult.resultByTarget = new Hashtable(numberOfHashKeyValuePairs, StringComparer.OrdinalIgnoreCase);
     for (int i = 0; i < numberOfHashKeyValuePairs; i++)
     {
         string key = reader.ReadString();
         int value = reader.ReadInt32();
         buildResult.resultByTarget.Add(key, (Target.BuildState)value);
     }
     #endregion
     buildResult.flags = reader.ReadByte();
     buildResult.handleId = reader.ReadInt32();
     buildResult.requestId = reader.ReadInt32();
     buildResult.projectId = reader.ReadInt32();
     #region DefaultTargets
     if (reader.ReadByte() == 0)
     {
         buildResult.defaultTargets = null;
     }
     else
     {
         buildResult.defaultTargets = reader.ReadString();
     }
     #endregion
     #region InitialTargets
     if (reader.ReadByte() == 0)
     {
         buildResult.initialTargets = null;
     }
     else
     {
         buildResult.initialTargets = reader.ReadString();
     }
     #endregion
     #region Timing data
     buildResult.totalTime = reader.ReadInt32();
     buildResult.engineTime = reader.ReadInt32();
     buildResult.taskTime = reader.ReadInt32();
     #endregion
     return buildResult;
 }
示例#15
0
 /// <summary>
 /// Initialize this build request with a cached build result
 /// </summary>
 /// <param name="cachedResult"></param>
 internal void InitializeFromCachedResult(BuildResult cachedResult)
 {
     this.OutputsByTarget = cachedResult.OutputsByTarget;
     this.BuildSucceeded = cachedResult.EvaluationResult;
     this.BuildCompleted = true;
     this.DefaultTargets = cachedResult.DefaultTargets;
     this.InitialTargets = cachedResult.InitialTargets;
     this.projectId = cachedResult.ProjectId;
     this.restoredFromCache = true;
 }
示例#16
0
        /// <summary>
        /// This method adds cached results for each target results for which are contained inside
        /// the build result. This method is thread safe.
        /// </summary>
        internal void AddCacheEntryForBuildResults(BuildResult buildResult)
        {
            ErrorUtilities.VerifyThrow(buildResult != null, "Expect a non-null build result");

            // Don't cache results if they are marked as uncacheable
            if (!buildResult.UseResultCache)
            {
                return;
            }

            cacheScopeReaderWriterLock.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (!ContainsCacheEntry(Constants.defaultTargetCacheName))
                {
                    // If the project file is malformed the build may fail without initializing the initialtargets or
                    // the default targests fields. The retrieval code expects non-null values
                    // so it is necessary to replace null with empty string
                    ErrorUtilities.VerifyThrow(buildResult.EvaluationResult == false || buildResult.InitialTargets != null &&
                                               buildResult.DefaultTargets != null,
                                               "Expect initial targets to be non-null for successful builds");
                    string             defaultTargets           = buildResult.DefaultTargets == null ? String.Empty : buildResult.DefaultTargets;
                    PropertyCacheEntry defaultTargetsCacheEntry = new PropertyCacheEntry(Constants.defaultTargetCacheName, defaultTargets);
                    AddCacheEntryInternal(defaultTargetsCacheEntry);

                    string             initialTargets           = buildResult.InitialTargets == null ? String.Empty : buildResult.InitialTargets;
                    PropertyCacheEntry initialTargetsCacheEntry = new PropertyCacheEntry(Constants.initialTargetCacheName, initialTargets);
                    AddCacheEntryInternal(initialTargetsCacheEntry);
                }

                if (!ContainsCacheEntry(Constants.projectIdCacheName))
                {
                    PropertyCacheEntry projectIdCacheEntry = new PropertyCacheEntry(Constants.projectIdCacheName, buildResult.ProjectId.ToString(CultureInfo.InvariantCulture));
                    AddCacheEntryInternal(projectIdCacheEntry);
                }

                IDictionary outputsByTargetName = buildResult.OutputsByTarget;

                //Create single entry for each target in the request
                foreach (DictionaryEntry entry in buildResult.ResultByTarget)
                {
                    Target.BuildState buildState = (Target.BuildState)entry.Value;

                    // Only cache successful and failed targets
                    if ((buildState == Target.BuildState.CompletedSuccessfully) ||
                        (buildState == Target.BuildState.CompletedUnsuccessfully))
                    {
                        BuildItem[] targetOutputs = null;

                        // Only cache output items for successful targets
                        if (buildState == Target.BuildState.CompletedSuccessfully)
                        {
                            ErrorUtilities.VerifyThrow(buildResult.OutputsByTarget.Contains(entry.Key),
                                                       "We must have build results for successful targets");

                            BuildItem[] outputItems = (BuildItem[])buildResult.OutputsByTarget[entry.Key];

                            // It's essential that we clear out any pointers to the project from the BuildItem;
                            // otherwise the cache will hold onto the project, and not save any memory.
                            if (outputItems != null)
                            {
                                for (int i = 0; i < outputItems.Length; i++)
                                {
                                    outputItems[i] = outputItems[i].VirtualClone(true /* remove references to minimise transitive size */);
                                }
                            }

                            targetOutputs = (BuildItem[])buildResult.OutputsByTarget[entry.Key];
                        }

                        BuildResultCacheEntry cacheEntry = new BuildResultCacheEntry((string)entry.Key, targetOutputs,
                                                                                     (buildState == Target.BuildState.CompletedSuccessfully));

                        if (Engine.debugMode)
                        {
                            Console.WriteLine("+++Adding cache entry for " + (string)entry.Key + " in " +
                                              this.ScopeName + " result: " + (buildState == Target.BuildState.CompletedSuccessfully));
                        }

                        AddCacheEntryInternal(cacheEntry);
                    }
                }
            }
            finally
            {
                cacheScopeReaderWriterLock.ReleaseWriterLock();
            }
        }
示例#17
0
        public virtual void Refresh()
        {
            // Let MSBuild know which configuration we are working with
            project.SetConfiguration(projectCfg.ConfigCanonicalName);


            var result = new BuildResult(MSBuildResult.Failed, null);
            if (project.ProjectMgr.BuildProject.Targets.ContainsKey(ProjectFileConstants.AllProjectOutputGroups))
            {
                result = project.InvokeMsBuild(ProjectFileConstants.AllProjectOutputGroups, false /*isBeingCalledByComputeSourcesAndFlags*/);
                if (!result.IsSuccessful)
                {
                    // we could not compute it, probably because there is a real build going on right now
                    project.SetCurrentConfiguration();
                    return;
                }
            }

            // Rebuild the content of our list of output
            string outputType = this.targetName + "Output";
            this.outputs.Clear();
            foreach (Microsoft.Build.Execution.ProjectItemInstance assembly in result.ProjectInstance.GetItems(outputType))
            {
                Output output = new Output(project, assembly);
                this.outputs.Add(output);

                // See if it is our key output
                if (String.Compare(MSBuildItem.GetMetadataValue(assembly, "IsKeyOutput"), true.ToString(), StringComparison.OrdinalIgnoreCase) == 0)
                    keyOutput = output;
            }

            project.SetCurrentConfiguration();

            // Now that the group is built we have to check if it is invalidated by a property
            // change on the project.
            project.OnProjectPropertyChanged += new EventHandler<ProjectPropertyChangedArgs>(OnProjectPropertyChanged);
        }
		protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration)
		{
			DotNetProject project = Project;
			
			bool hasBuildableFiles = false;
			foreach (ProjectFile pf in project.Files) {
				if (pf.BuildAction == BuildAction.Compile || pf.BuildAction == BuildAction.EmbeddedResource) {
					hasBuildableFiles = true;
					break;
				}
			}
			if (!hasBuildableFiles)
				return new BuildResult ();
			
			if (project.LanguageBinding == null) {
				BuildResult langres = new BuildResult ();
				string msg = GettextCatalog.GetString ("Unknown language '{0}'. You may need to install an additional add-in to support this language.", project.LanguageName);
				langres.AddError (msg);
				monitor.ReportError (msg, null);
				return langres;
			}

			BuildResult refres = null;
			HashSet<ProjectItem> itemsToExclude = new HashSet<ProjectItem> ();
			
			foreach (ProjectReference pr in project.References) {
				
				if (pr.ReferenceType == ReferenceType.Project) {
					// Ignore non-dotnet projects
					Project p = project.ParentSolution != null ? project.ParentSolution.FindProjectByName (pr.Reference) : null;
					if (p != null && !(p is DotNetProject))
						continue;

					if (p == null || pr.GetReferencedFileNames (configuration).Length == 0) {
						if (refres == null)
							refres = new BuildResult ();
						string msg = GettextCatalog.GetString ("Referenced project '{0}' not found in the solution.", pr.Reference);
						monitor.ReportWarning (msg);
						refres.AddWarning (msg);
					}
				}
				
				if (!pr.IsValid) {
					if (refres == null)
						refres = new BuildResult ();
					string msg;
					if (!pr.IsExactVersion && pr.SpecificVersion) {
						msg = GettextCatalog.GetString ("Reference '{0}' not found on system. Using '{1}' instead.", pr.StoredReference, pr.Reference);
						monitor.ReportWarning (msg);
						refres.AddWarning (msg);
					}
					else {
						bool errorsFound = false;
						foreach (string asm in pr.GetReferencedFileNames (configuration)) {
							if (!File.Exists (asm)) {
								msg = GettextCatalog.GetString ("Assembly '{0}' not found. Make sure that the assembly exists in disk. If the reference is required to build the project you may get compilation errors.", Path.GetFileName (asm));
								refres.AddWarning (msg);
								monitor.ReportWarning (msg);
								errorsFound = true;
								itemsToExclude.Add (pr);
							}
						}
						msg = null;
						if (!errorsFound) {
							msg = GettextCatalog.GetString ("The reference '{0}' is not valid for the target framework of the project.", pr.StoredReference, pr.Reference);
							monitor.ReportWarning (msg);
							refres.AddWarning (msg);
							itemsToExclude.Add (pr);
						}
					}
				}
			}
			
			DotNetProjectConfiguration conf = (DotNetProjectConfiguration) project.GetConfiguration (configuration);

			// Create a copy of the data needed to compile the project.
			// This data can be modified by extensions.
			// Also filter out items whose condition evaluates to false
			
			BuildData buildData = new BuildData ();
			ProjectParserContext ctx = new ProjectParserContext (project, conf);
		
			buildData.Items = new ProjectItemCollection ();
			foreach (ProjectItem item in project.Items) {
				if (!itemsToExclude.Contains (item) && (string.IsNullOrEmpty (item.Condition) || ConditionParser.ParseAndEvaluate (item.Condition, ctx)))
					buildData.Items.Add (item);
			}
			buildData.Configuration = (DotNetProjectConfiguration) conf.Clone ();
			buildData.Configuration.SetParentItem (project);
			buildData.ConfigurationSelector = configuration;

			return ProjectExtensionUtil.Compile (monitor, project, buildData, delegate {
				ProjectItemCollection items = buildData.Items;
				BuildResult res = BuildResources (buildData.Configuration, ref items, monitor);
				if (res != null)
					return res;
	
				res = project.LanguageBinding.Compile (items, buildData.Configuration, buildData.ConfigurationSelector, monitor);
				if (refres != null) {
					refres.Append (res);
					return refres;
				}
				else
					return res;
			});
		}		
        /// <summary>
        /// Creates an assembly refernce node from a project element.
        /// </summary>
        internal virtual AssemblyReferenceNode CreateAssemblyReferenceNode(ProjectElement element, BuildResult buildResult)
        {
            AssemblyReferenceNode node = null;
            try
            {
                node = AssemblyReferenceNode.CreateFromProjectFile(this.ProjectMgr, element, buildResult);
            }
            catch (ArgumentNullException e)
            {
                Trace.WriteLine("Exception : " + e.Message);
            }
            catch (FileNotFoundException e)
            {
                Trace.WriteLine("Exception : " + e.Message);
            }
            catch (BadImageFormatException e)
            {
                Trace.WriteLine("Exception : " + e.Message);
            }
            catch (FileLoadException e)
            {
                Trace.WriteLine("Exception : " + e.Message);
            }
            catch (System.Security.SecurityException e)
            {
                Trace.WriteLine("Exception : " + e.Message);
            }

            return node;
        }
示例#20
0
 internal override void CreateFromStream(BinaryReader reader)
 {
     base.CreateFromStream(reader);
     buildResult = BuildResult.CreateFromStream(reader);
 }
示例#21
0
        private static BuildResult CreateBuildResult()
        {
            BuildItem buildItem1 = new BuildItem(null, "Item1");
            BuildItem buildItem2 = new BuildItem("BuildItem2", "Item2");
            BuildItem buildItem3 = BuildItem_Tests.GetXmlBackedItemWithDefinitionLibrary(); // default metadata m=m1 and o=o1
            buildItem1.Include = "TestInclude1";
            buildItem2.Include = "TestInclude2";
            buildItem1.SetMetadata("m", "m1");
            buildItem1.SetMetadata("n", "n1");
            buildItem3.SetMetadata("n", "n1");
            buildItem3.SetMetadata("o", "o2");
            BuildItem[] taskItems = new BuildItem[3];
            taskItems[0] = buildItem1;
            taskItems[1] = buildItem2;
            taskItems[2] = buildItem3;

            Dictionary<object, object> dictionary = new Dictionary<object, object>();
            dictionary.Add("TaskItems", taskItems);

            BuildResult resultWithOutputs = new BuildResult(dictionary, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, "Foo", "Fighter", 1, 2, 3);
            resultWithOutputs.ResultByTarget.Add("ONE", Target.BuildState.CompletedSuccessfully);
            resultWithOutputs.HandleId = 0;
            resultWithOutputs.RequestId = 1;
            return resultWithOutputs;
        }
示例#22
0
 public void TestNullParameterInConstructor()
 {
     BuildResult shouldFail = new BuildResult(null, false /* shallow copy */);
 }
示例#23
0
        /// <summary>
        /// This function implements the callback via the IBuildEngine interface
        /// </summary>
        /// <returns>result of call to engine</returns>
        virtual internal bool BuildProjectFile
        (
            int handleId, 
            string[] projectFileNames, 
            string[] targetNames, 
            IDictionary[] globalPropertiesPerProject,
            IDictionary[] targetOutputsPerProject,
            EngineLoggingServices loggingServices,
            string [] toolsVersions,
            bool useResultsCache,
            bool unloadProjectsOnCompletion, 
            BuildEventContext taskContext
        )
        {
            if (projectFileNames.Length == 0)
            {
                // Nothing to do, just return success
                return true;
            }

            string currentDir = FileUtilities.GetCurrentDirectoryStaticBuffer(currentDirectoryBuffer);

            if (Engine.debugMode)
            {
                string targetName = targetNames == null ? "null" : targetNames[0];

                bool remoteNode = false;
                for (int r = 0; r < projectFileNames.Length; r++)
                {
                    string fullProjectName = projectFileNames[r] != null ?
                       projectFileNames[r] : "null";
                    Console.WriteLine("RemoteNode: " + remoteNode + " Project " + fullProjectName + " T:" + targetName + " NodeProdyId# " + handleId + " Time " + DateTime.Now.ToLongTimeString());
                    if (globalPropertiesPerProject[r] != null)
                    {
                        foreach (DictionaryEntry entry in globalPropertiesPerProject[r])
                        {
                            Console.WriteLine(currentDir + " :GLOBAL " + entry.Key + "=" + entry.Value.ToString());
                        }
                    }
                }
            }

            BuildRequest[] buildRequests = new BuildRequest[projectFileNames.Length];
            for (int i = 0; i < buildRequests.Length; i++)
            {
                // We need to get the full path to the project before we call back
                // into the engine which has no control over current path
                string fullProjectName = projectFileNames[i] != null ?
                    Path.GetFullPath(projectFileNames[i]) : null;

                buildRequests[i] = new BuildRequest(handleId, fullProjectName, targetNames, globalPropertiesPerProject[i],
                                                    toolsVersions[i], i, useResultsCache, unloadProjectsOnCompletion);
                ErrorUtilities.VerifyThrow(buildRequests[i].IsGeneratedRequest == true, "Should not be sending non generated requests from TEM to engine");
                buildRequests[i].ParentBuildEventContext = taskContext;
            }

            BuildResult[] buildResultsLocal = new BuildResult[projectFileNames.Length];

            if (moduleMode == TaskExecutionModuleMode.SingleProcMode)
            {
                for (int i = 0; i < projectFileNames.Length; i++)
                {
                    // If we are running in a single threaded mode we need to
                    // re-enter the main build loop on the current thread in order
                    // to build the requested project, because the main build is below
                    // us on the stack
                    engineCallback.PostBuildRequestsToHost(new BuildRequest[] { buildRequests[i] });
                    buildResultsLocal[i] = engineCallback.GetParentEngine().EngineBuildLoop(buildRequests[i]);
                    buildResultsLocal[i].ConvertToTaskItems();
                }
            }
            else
            {
                WaitForBuildResults(handleId, buildResultsLocal, buildRequests);
            }

            // Store the outputs in the hashtables provided by the caller
            bool overallResult = true;
            for (int i = 0; i < buildResultsLocal.Length; i++)
            {
                // Users of the Object Model can pass in null targetOutputs for projects they do not want outputs for
                // therefore we need to make sure that there are targetoutputs and the users want the results
                if (buildResultsLocal[i] != null)
                {
                    if (buildResultsLocal[i].OutputsByTarget != null && targetOutputsPerProject[i] != null)
                    {
                        foreach (DictionaryEntry entry in buildResultsLocal[i].OutputsByTarget)
                        {
                            targetOutputsPerProject[i].Add(entry.Key, entry.Value);
                        }
                        overallResult = overallResult && buildResultsLocal[i].EvaluationResult;
                    }
                }
                else
                {
                    // The calculation was terminated prior to receiving the result
                    overallResult = false;
                }
            }

            // We're now returning from an IBuildEngine callback;
            // set the current directory back to what the tasks expect
            if (Directory.GetCurrentDirectory() != currentDir)
            {
                Directory.SetCurrentDirectory(currentDir);
            }

            if (Engine.debugMode)
            {
                bool remoteNode = false;
                string targetName = targetNames == null ? "null" : targetNames[0];
                Console.WriteLine("RemoteNode: " + remoteNode + " T:" + targetName + " HandleId# " + handleId + " Result " + overallResult);
            }

            return overallResult;
        }
示例#24
0
        public void CustomSerialization()
        {
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);
            BinaryReader reader = new BinaryReader(stream);
            try
            {
                stream.Position = 0;
                BuildResult result1 = new BuildResult(resultWithOutputs, false /* shallow copy */);
                result1.HandleId = 2;
                result1.RequestId = 3;
                result1.WriteToStream(writer);

                BuildResult result2 = new BuildResult(resultWithOutputs, true /* deep copy */);
                result2.HandleId = 2;
                result2.RequestId = 3;
                result2.WriteToStream(writer);

                BuildResult result3 = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, null, null, 0, 0, 0);
                result3.HandleId = 2;
                result3.RequestId = 3;
                result3.WriteToStream(writer);

                BuildResult result4 = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, "DefaultTarget", "InitialTarget", 0, 0, 0);
                result4.HandleId = 2;
                result4.RequestId = 3;
                result4.ResultByTarget.Add("ONE", Target.BuildState.CompletedSuccessfully);
                result4.WriteToStream(writer);
                long streamWriteEndPosition = stream.Position;
                stream.Position = 0;

                BuildResult result5 = BuildResult.CreateFromStream(reader);
                BuildResult result6 = BuildResult.CreateFromStream(reader);
                BuildResult result7 = BuildResult.CreateFromStream(reader);
                BuildResult result8 = BuildResult.CreateFromStream(reader);
                long streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream end positions should be equal");
                CompareBuildResult(result1, result5);
                CompareBuildResult(result2, result6);
                CompareBuildResult(result3, result7);
                CompareBuildResult(result4, result8);
                Assert.IsTrue(result8.ResultByTarget.Count == 1);
                Assert.IsTrue(((Target.BuildState)result8.ResultByTarget["ONE"]) == Target.BuildState.CompletedSuccessfully);
                BuildItem[] buildItemArray = ((BuildItem[])result1.OutputsByTarget["TaskItems"]);
                Assert.IsTrue(buildItemArray.Length == 2);
                Assert.IsTrue(string.Compare(buildItemArray[0].Include, buildItem1.Include, StringComparison.OrdinalIgnoreCase)==0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Include, buildItem2.Include, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Name, buildItem2.Name, StringComparison.OrdinalIgnoreCase) == 0);
            }
            finally
            {
                reader.Close();
                writer = null;
                stream = null;
            }
        }
示例#25
0
       /// <summary>
       /// Once the buildRequests from the EngineCallback have been created they are sent to this method which will
       /// post the build requests to the parent engine and then wait on the results to come back.
       /// This method uses either a breadthFirst or depthFirst traversal strategy when sending buildRequests to the parent engine.
       /// This method will start in breadthFirst traversal. It will continue to use this strategy until one of two events occur:
       ///     1. The parent node sents a message indicating the TEM should switch to depthFirst traversal. 
       ///     2. The number of buildRequests is larger than the batchRequestSize.
       /// In both of these cases the system will go from a breadthFirstTraversal to a depthFirst Traversal. In the second case
       /// a message will be sent to the parent engine to switch the system to depthFirst traversal as the system is starting to 
       /// be overloaded with work.
       /// In a depth first strategy the buildRequests will be sent to the parent engine one at a time and waiting for results for
       /// each buildRequest sent. In a breadthFirst traversal strategy some number of the buildrequests will be sent to the parent engine
       /// in a batch of requests. The system will then wait on the results of ALL the build requests sent before continuing
       /// to send more build requests.
       /// </summary>
       private void WaitForBuildResults(int handleId, BuildResult[] buildResultsLocal, BuildRequest[] buildRequests)
        {
            // If the traversal strategy is breadth first and the number of requests is less than the batchRequestSize
            // or if there is only 1 build request then send ALL build requests to the parent engine and wait on the results.
            if ((breadthFirstTraversal == true && buildRequests.Length < batchRequestSize) || buildRequests.Length == 1)
            {
                engineCallback.PostBuildRequestsToHost(buildRequests);
                workerThread.WaitForResults(handleId, buildResultsLocal, buildRequests);
            }
            else
            {
                int currentRequestIndex = 0; // Which build request is being processed
                int numberOfRequestsToSend = 0; // How many buildRequests are going to be sent based on the number of buildRequests remaining and the build request batch size.
                
                // Arrays that will be used to partion the buildRequests array when sending batches of builds requests at a time.
                BuildRequest[] wrapperArrayBreadthFirst = new BuildRequest[batchRequestSize];
                BuildResult[] resultsArrayBreadthFirst = new BuildResult[batchRequestSize];

                // Pre allocate these arrays as they will always be only one element in size. They are assigned to and filled when doing a depth first traversal.
                BuildRequest[] wrapperArrayDepthFirst = new BuildRequest[1];
                BuildResult[] resultsArrayDepthFirst = new BuildResult[1];

                // While there are still requests to send
                while (currentRequestIndex < buildRequests.Length)
                {
                    // If there is a breadth first traversal and there are more than batchRequestSize build requests, send the first batchRequestSize, then do the rest depth first
                    if (breadthFirstTraversal == true)
                    {
                        // Figure out how many requests to send, either the full batch size or only part of a batch
                        numberOfRequestsToSend = (buildRequests.Length - currentRequestIndex) <batchRequestSize ? (buildRequests.Length - currentRequestIndex) : batchRequestSize;

                        // Initialize the wrapper array to how many requests are going to be sent
                        if (numberOfRequestsToSend != wrapperArrayBreadthFirst.Length)
                        {
                            wrapperArrayBreadthFirst = new BuildRequest[numberOfRequestsToSend];
                            resultsArrayBreadthFirst = new BuildResult[numberOfRequestsToSend];
                        }
                        
                        // Fill the wrapper array with one batch of build requests
                        for (int i = 0; i < numberOfRequestsToSend; i++)
                        {
                            wrapperArrayBreadthFirst[i] = buildRequests[currentRequestIndex + i];
                            wrapperArrayBreadthFirst[i].RequestId = i;
                            resultsArrayBreadthFirst[i] = null;
                        }

                        engineCallback.PostBuildRequestsToHost(wrapperArrayBreadthFirst);
                        
                        // Only switch from breadth to depth if there are more thanbatchRequestSize items
                        if ((buildRequests.Length - currentRequestIndex) > batchRequestSize)
                        {
                            engineCallback.PostStatus(nodeId, new NodeStatus(false /* use depth first traversal*/), false /* don't block waiting on the send */);
                            breadthFirstTraversal = false;
                        }
                        
                        workerThread.WaitForResults(handleId, resultsArrayBreadthFirst, wrapperArrayBreadthFirst);
                        Array.Copy(resultsArrayBreadthFirst, 0, buildResultsLocal, currentRequestIndex, numberOfRequestsToSend);
                        currentRequestIndex += numberOfRequestsToSend;
                    }

                    // Proceed with depth first traversal
                    while ((currentRequestIndex < buildRequests.Length) && !breadthFirstTraversal)
                    {
                        wrapperArrayDepthFirst[0] = buildRequests[currentRequestIndex];
                        buildRequests[currentRequestIndex].RequestId = 0;
                        resultsArrayDepthFirst[0] = null;

                        engineCallback.PostBuildRequestsToHost(wrapperArrayDepthFirst);
                        workerThread.WaitForResults(handleId, resultsArrayDepthFirst, wrapperArrayDepthFirst);
                        //Copy the result from an intermediate array to the full array
                        buildResultsLocal[currentRequestIndex] = resultsArrayDepthFirst[0];
                        //Check if the call failed (null result was returned)
                        if (buildResultsLocal[currentRequestIndex] == null)
                        {
                            return;
                        }

                        //Move to the next request
                        currentRequestIndex++;
                    }
                }
            }
        }
示例#26
0
        /// <summary>
        /// This method lets the engine provide node with results of an evaluation it was waiting on.
        /// </summary>
        /// <param name="buildResult"></param>
        internal void PostBuildResults(BuildResult buildResult)
        {
            // Do nothing in the single proc mode
            if (moduleMode == TaskExecutionModuleMode.SingleProcMode)
            {
                return;
            }

            buildResult.ConvertToTaskItems();
            workerThread.PostBuildResult(buildResult);
        }
示例#27
0
 private void BuildCoda(BuildResult result, IVsOutputWindowPane output, bool shouldRepaintReferences)
 {
     try
     {
         // Now repaint references if that is needed. 
         // We hardly rely here on the fact the ResolveAssemblyReferences target has been run as part of the build.
         // One scenario to think at is when an assembly reference is renamed on disk thus becomming unresolvable, 
         // but msbuild can actually resolve it.
         // Another one if the project was opened only for browsing and now the user chooses to build or rebuild.
         if (shouldRepaintReferences && (result.IsSuccessful))
         {
             this.RefreshReferences(result);
         }
     }
     finally
     {
         try
         {
             ErrorHandler.ThrowOnFailure(output.FlushToTaskList());
         }
         finally
         {
             NotifyBuildEnd(result.IsSuccessful);
         }
     }
 }
示例#28
0
 void INodeProvider.PostBuildResultToNode(int nodeIndex, BuildResult buildResultToPost)
 {
     if (nodeIndex > nodeDescriptions.Count)
     {
         throw new ArgumentException("Node index is out of range");
     }
     buildResultsSubmittedToProvider.Add(buildResultToPost);
 }
示例#29
0
 internal void AddResultToCache(BuildResult buildResult)
 {
     resultsCache.AddCacheEntryForBuildResults(buildResult);
 }
示例#30
0
文件: Node.cs 项目: nikson/msbuild
 /// <summary>
 /// This method posts outputs of a build to the node that made the request
 /// </summary>
 /// <param name="buildResult"></param>
 internal void PostBuildResultToHost(BuildResult buildResult)
 {
     try
     {
         outProcLoggingService.ProcessPostedLoggingEvents();
         parentCallback.PostBuildResultToHost(buildResult);
     }
     catch (Exception e)
     {
         ReportUnhandledError(e);
     }
 }
示例#31
0
 /// <summary>
 /// Post a build result to a node, the node index is an index into the list of nodes provided by all node providers
 /// registered to the node manager, the 0 in index is a local call to taskexecutionmodule
 /// </summary>
 /// <param name="nodeIndex"></param>
 /// <param name="buildResult"></param>
 internal void PostBuildResultToNode(int nodeIndex, BuildResult buildResult)
 {
     ErrorUtilities.VerifyThrow(nodeIndex <= nodeList.Count, "Should not pass a node index higher then the number of nodes in nodeManager");
     if (nodeIndex != 0)
     {
         nodeList[nodeIndex-1].NodeProvider.PostBuildResultToNode(nodeList[nodeIndex-1].NodeIndex, buildResult);
     }
     else
     {
         taskExecutionModule.PostBuildResults(buildResult);
     }
 }
示例#32
0
 /// <summary>
 /// Refreshes references and redraws them correctly.
 /// </summary>
 private void RefreshReferences(BuildResult buildResult)
 {
     // Refresh the reference container node for assemblies that could be resolved.
     IReferenceContainer referenceContainer = this.config.ProjectMgr.GetReferenceContainer();
     foreach (ReferenceNode referenceNode in referenceContainer.EnumReferences())
     {
         referenceNode.RefreshReference(buildResult);
     }
 }
示例#33
0
        /// <summary>
        /// This is the loop for all active threads. Depending on the current execution mode the thread
        /// will listen to different events. There is only one thread at the time that owns the workitem
        /// queue and listens for tasks to be executed. There is also only one thread at a time that is
        /// execution a task. That thread owns the current directory and the environment block.
        /// </summary>
        /// <param name="executionMode"></param>
        /// <param name="nodeProxyId"></param>
        /// <param name="requestResults"></param>
        private void NodeActionLoop(NodeLoopExecutionMode executionMode, int nodeProxyId, BuildResult [] requestResults)
        {
            // Create an array of event to the node thread responds
            WaitHandle[] waitHandles = GetHandlesArray(executionMode);

            int resultCount = 0;

            // A thread that is waiting for a done notification is no longer
            // actively executing a task so the active cound needs to be decreased
            if (executionMode != NodeLoopExecutionMode.BaseActiveThread)
            {
                Interlocked.Decrement(ref activeThreadCount);
                threadCountEvent.Set();
            }

            bool continueExecution = true;

            while (continueExecution)
            {
                int eventType = WaitHandle.WaitAny(waitHandles);

                if (Environment.GetEnvironmentVariable("MSBUILDDEBUG") == "1")
                {
                    Console.WriteLine("NodeProxy :" + nodeProxyId + " waking up due " + eventType);
                }

                // Node exit event - all threads need to exit
                if (eventType == 0)
                {
                    continueExecution = false;
                }
                // New work item has appeared in the queue
                else if (eventType == 1 && executionMode != NodeLoopExecutionMode.WaitingPassiveThread)
                {
                    ErrorUtilities.VerifyThrow(
                        executionMode == NodeLoopExecutionMode.WaitingActiveThread ||
                        executionMode == NodeLoopExecutionMode.BaseActiveThread,
                        "Only active threads should receive work item events");

                    if (executionMode == NodeLoopExecutionMode.BaseActiveThread)
                    {
                        TaskExecutionState taskToExecute = null;
                        lock (workItemQueue)
                        {
                            taskToExecute = workItemQueue.Dequeue();
                            // We may get a single event for multiple messages so only reset the event
                            // if the queue is empty
                            if (workItemQueue.Count == 0)
                            {
                                workItemInsertionEvent.Reset();
                            }
                        }

                        // Execute the task either directly or on a child thread
                        ErrorUtilities.VerifyThrow(taskToExecute != null, "Expected a workitem");

                        // Wait until all there are no other active threads, we
                        // always transition from 0 to 1 atomically before executing the task
                        while (Interlocked.CompareExchange(ref activeThreadCount, 1, 0) != 0)
                        {
                            threadCountEvent.WaitOne();
                            threadCountEvent.Reset();
                        }

                        proxyIdToWorkerThread[taskToExecute.NodeProxyId] = this;

                        // Actually execute the task
                        taskToExecute.ExecuteTask();

                        proxyIdToWorkerThread.Remove(taskToExecute.NodeProxyId);

                        // Indicate that this thread is no longer active
                        Interlocked.Decrement(ref activeThreadCount);
                        threadCountEvent.Set();
                    }
                    else
                    {
                        // Change the thread execution mode since it will no longer be
                        // listening to the work item queue
                        executionMode = NodeLoopExecutionMode.WaitingPassiveThread;
                        threadActive  = false;
                        waitHandles   = GetHandlesArray(executionMode);

                        TaskWorkerThread workerThread = null;
                        lock (workerThreadQueue)
                        {
                            if (workerThreadQueue.Count != 0)
                            {
                                //Console.WriteLine("REUSING a thread");
                                workerThread = workerThreadQueue.Dequeue();
                            }
                        }
                        if (workerThread == null)
                        {
                            //Console.WriteLine("CREATING a thread");
                            workerThread = new TaskWorkerThread();
                        }

                        workerThread.ActivateThread();
                    }
                }
                else if (eventType == 1 && executionMode == NodeLoopExecutionMode.WaitingPassiveThread ||
                         eventType == 2 && executionMode == NodeLoopExecutionMode.WaitingActiveThread)
                {
                    // There maybe multiple results in the list so we need to loop over it
                    // and store the results
                    int originalResultCount = resultCount;
                    lock (targetEvaluationResults)
                    {
                        //Console.WriteLine("Worker thread for: " + nodeProxyId + " Got results");
                        LinkedListNode <BuildResult> currentNode = targetEvaluationResults.First;
                        while (currentNode != null)
                        {
                            BuildResult buildResult = currentNode.Value;
                            ErrorUtilities.VerifyThrow(
                                buildResult.RequestId < requestResults.Length,
                                "The request ids should be inside the array");
                            requestResults[buildResult.RequestId] = buildResult;
                            // Increment the result count to indicate that we got another result
                            resultCount++;
                            // Go to the next entry in the list (most of the time there will be just one entry)
                            currentNode = currentNode.Next;
                        }
                        targetEvaluationResults.Clear();
                        // Reset the handle now that we done with the events
                        int handleIndex = executionMode == NodeLoopExecutionMode.WaitingPassiveThread ? 1 : 2;
                        ((ManualResetEvent)waitHandles[handleIndex]).Reset();
                    }
                    ErrorUtilities.VerifyThrow(originalResultCount < resultCount, "We should have found at least 1 result");
                    // If we received results for all the requests we need to exit
                    if (resultCount == requestResults.Length)
                    {
                        continueExecution = false;
                    }
                }
                // Check if we need to update the state
                if (executionMode == NodeLoopExecutionMode.BaseActiveThread && !threadActive)
                {
                    continueExecution = false;
                }
            }

            ErrorUtilities.VerifyThrow
                (resultCount == 0 || executionMode != NodeLoopExecutionMode.BaseActiveThread,
                "The base thread should never return a value");

            // If a thread exits this loop it is back to actively executing the task,
            // so the active thread count has to be increased
            if (executionMode != NodeLoopExecutionMode.BaseActiveThread)
            {
                while (Interlocked.CompareExchange(ref activeThreadCount, 1, 0) != 0)
                {
                    threadCountEvent.WaitOne();
                    threadCountEvent.Reset();
                }
            }
        }