Beispiel #1
0
        private CacheScope GetCacheScopeIfExists(string scopeName, BuildPropertyGroup scopeProperties, string scopeToolsVersion, CacheContentType cacheContentType)
        {
            CacheScope cacheScope = null;

            // Default the version to the default engine version
            if (scopeToolsVersion == null)
            {
                scopeToolsVersion = defaultToolsVersion;
            }

            // Retrieve list of scopes by this name
            if (cacheContents[(int)cacheContentType].ContainsKey(scopeName))
            {
                List <CacheScope> scopesByName = (List <CacheScope>)cacheContents[(int)cacheContentType][scopeName];

                // If the list exists search for matching scope properties otherwise create the list
                if (scopesByName != null)
                {
                    lock (cacheManagerLock)
                    {
                        for (int i = 0; i < scopesByName.Count; i++)
                        {
                            if (scopesByName[i].ScopeProperties.IsEquivalent(scopeProperties) && (String.Equals(scopeToolsVersion, scopesByName[i].ScopeToolsVersion, StringComparison.OrdinalIgnoreCase)))
                            {
                                cacheScope = scopesByName[i];
                                break;
                            }
                        }
                    }
                }
            }

            return(cacheScope);
        }
Beispiel #2
0
        /// <summary>
        /// This method return a cache scope with particular name and properties. If the cache
        /// scope doesn't exist it will be created. This method is thread safe.
        /// </summary>
        internal CacheScope GetCacheScope(string scopeName, BuildPropertyGroup scopeProperties, string scopeToolsVersion, CacheContentType cacheContentType)
        {
            // If the version is not specified default to the engine version
            if (scopeToolsVersion == null)
            {
                scopeToolsVersion = defaultToolsVersion;
            }

            // Retrieve the cache scope if it exists
            CacheScope cacheScope = GetCacheScopeIfExists(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);

            // If the scope doesn't exist create it
            if (cacheScope == null)
            {
                lock (cacheManagerLock)
                {
                    cacheScope = GetCacheScopeIfExists(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);

                    if (cacheScope == null)
                    {
                        // If the list of scopes doesn't exist create it
                        if (!cacheContents[(int)cacheContentType].ContainsKey(scopeName))
                        {
                            cacheContents[(int)cacheContentType].Add(scopeName, new List <CacheScope>());
                        }
                        // Create the scope and add it to the list
                        List <CacheScope> scopesByName = (List <CacheScope>)cacheContents[(int)cacheContentType][scopeName];
                        cacheScope = new CacheScope(scopeName, scopeProperties, scopeToolsVersion);
                        scopesByName.Add(cacheScope);
                    }
                }
            }

            return(cacheScope);
        }
        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");
        }
Beispiel #4
0
        /// <summary>
        /// This method creates a BuildResult using the information contained in a completed build request and
        /// then routes it to the right node. On a child process, this means either consume the result localy,
        /// or send it to the parent node. On a parent node, this means either consume the result locally or
        /// send it to a child node
        /// </summary>
        internal void PostDoneNotice(BuildRequest buildRequest)
        {
            // Create a container with the results of the evaluation
            BuildResult buildResult = buildRequest.GetBuildResult();

            // If we're supposed to use caching and this request wasn't restored from cache, cache it
            if (buildRequest.UseResultsCache && !buildRequest.RestoredFromCache)
            {
                CacheScope cacheScope = parentEngine.CacheManager.GetCacheScope(buildRequest.ProjectFileName, buildRequest.GlobalProperties, buildRequest.ToolsetVersion, CacheContentType.BuildResults);
                cacheScope.AddCacheEntryForBuildResults(buildResult);
            }

            // an external request is any request that came from the parent engine, all requests to a child are external
            // unless the project was alredy loaded on the node itself
            if (buildRequest.IsExternalRequest)
            {
                // If the build request was send from outside the current process,
                // send the results to the parent engine
                parentNode.PostBuildResultToHost(buildResult);
            }
            else
            {
                // In the case of a child process, getting to this point means the request will be satisfied locally, the node index should be 0
                // on the parent engine however, the node index can be, 0 for the local node, or can be >0 which represents a child node
                PostDoneNotice(buildRequest.NodeIndex, buildResult);
            }
        }
Beispiel #5
0
        /// <summary>
        /// This method is called once the engine has decided to sent a build request to a child node.
        /// Route the given BuildRequest to the given node. If necessary a routing context is
        /// created to manage future communication with the node regarding the build request.
        /// </summary>
        internal void PostBuildRequest(BuildRequest currentRequest, int nodeIndex)
        {
            // if the request is to be sent to the parent node, post the request back to the host
            if (nodeIndex == EngineCallback.parentNode)
            {
                ParentNode.PostBuildRequestToHost(currentRequest);
            }
            else
            {
                // Dont create any contexts if the request was supposed to be processed on the current node
                if (nodeIndex != EngineCallback.inProcNode)
                {
                    // Get the cache scope for the request (possibly creating it). The cache scope will contain the taskoutputs of the build request
                    // which can be reused of the same project/toolsversion/globalproperties is asked for again.
                    CacheScope cacheScope = parentEngine.CacheManager.GetCacheScope(currentRequest.ProjectFileName, currentRequest.GlobalProperties, currentRequest.ToolsetVersion, CacheContentType.BuildResults);

                    // Create a routing context and update the request to refer to the new node handle id
                    int parentHandleId = currentRequest.HandleId;
                    currentRequest.HandleId =
                        parentEngine.EngineCallback.CreateRoutingContext
                            (nodeIndex, currentRequest.HandleId, currentRequest.NodeIndex,
                            currentRequest.RequestId, cacheScope, currentRequest, null);



                    // Check to see if we need to change the traversal strategy of the system
                    // parentHandleId and node index are not used in the function so it can be ignored
                    scheduler?.NotifyOfBuildRequest(nodeIndex, currentRequest, parentHandleId);


                    nodeManager.PostBuildRequestToNode(nodeIndex, currentRequest);
                }
            }
        }
Beispiel #6
0
 internal NodeRequestMapping
     (int handleId, int requestId, CacheScope resultsCache)
 {
     ErrorUtilities.VerifyThrow(resultsCache != null, "Expect a non-null build result");
     this.handleId     = handleId;
     this.requestId    = requestId;
     this.resultsCache = resultsCache;
 }
Beispiel #7
0
        /// <summary>
        /// Sets multiple cache entries for the given scope
        /// </summary>
        /// <param name="entries"></param>
        /// <param name="scopeName"></param>
        /// <param name="scopeProperties"></param>
        internal void SetCacheEntries(CacheEntry[] entries, string scopeName, BuildPropertyGroup scopeProperties, string scopeToolsVersion, CacheContentType cacheContentType)
        {
            // If the list exists search for matching scope properties otherwise create the list
            CacheScope cacheScope = GetCacheScope(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);

            // Add the entry to the right scope
            cacheScope.AddCacheEntries(entries);
        }
Beispiel #8
0
 internal NodeRequestMapping
     (int handleId, int requestId, CacheScope resultsCache )
 {
     ErrorUtilities.VerifyThrow(resultsCache != null, "Expect a non-null build result");
     this.handleId = handleId;
     this.requestId = requestId;
     this.resultsCache = resultsCache;
 }
Beispiel #9
0
        /// <summary>
        /// Gets multiple cache entries from the given scope.
        /// </summary>
        /// <param name="names"></param>
        /// <param name="scopeName"></param>
        /// <param name="scopeProperties"></param>
        /// <returns></returns>
        internal CacheEntry[] GetCacheEntries(string[] names, string scopeName, BuildPropertyGroup scopeProperties, string scopeToolsVersion, CacheContentType cacheContentType)
        {
            CacheScope cacheScope = GetCacheScopeIfExists(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);

            if (cacheScope != null)
            {
                return(cacheScope.GetCacheEntries(names));
            }

            return(new CacheEntry[names.Length]);
        }
Beispiel #10
0
        public void TestConstructor()
        {
            BuildPropertyGroup default_scope = new BuildPropertyGroup(new Project());
            Assertion.AssertNotNull(default_scope);

            CacheScope testScope = new CacheScope("Test.proj", default_scope, "2.0");
            Assert.AreEqual(testScope.ScopeProperties, default_scope, "Expected ScopeProperties to be set");

            // We should have detached the parent project from the property group, to avoid holding on to it in the cache
            Assertion.AssertEquals(null, testScope.ScopeProperties.ParentProject);
        }
Beispiel #11
0
        internal void PostBuildRequestToHost(BuildRequest currentRequest)
        {
            // Since this request is going back to the host the local node should not have a project object for it
            ErrorUtilities.VerifyThrow(currentRequest.ProjectToBuild == null, "Should not have a project object");
            // Add the request to the mapping hashtable so that we can recognize the outputs
            CacheScope         cacheScope         = localEngine.CacheManager.GetCacheScope(currentRequest.ProjectFileName, currentRequest.GlobalProperties, currentRequest.ToolsetVersion, CacheContentType.BuildResults);
            NodeRequestMapping nodeRequestMapping =
                new NodeRequestMapping(currentRequest.HandleId, currentRequest.RequestId, cacheScope);

            lock (requestToLocalIdMapping)
            {
                requestToLocalIdMapping.Add(lastRequestIdUsed, nodeRequestMapping);
                // Keep the request id local for this node
                currentRequest.RequestId = lastRequestIdUsed;
                lastRequestIdUsed++;
            }

            // Find the original external request that caused us to run this task
            TaskExecutionContext taskExecutionContext = localEngine.EngineCallback.GetTaskContextFromHandleId(currentRequest.HandleId);

            while (!taskExecutionContext.BuildContext.BuildRequest.IsExternalRequest)
            {
                ErrorUtilities.VerifyThrow(taskExecutionContext.BuildContext.BuildRequest.IsGeneratedRequest,
                                           "Must be a generated request");

                taskExecutionContext =
                    localEngine.EngineCallback.GetTaskContextFromHandleId(taskExecutionContext.BuildContext.BuildRequest.HandleId);
            }

            //Modify the request with the data that is expected by the parent engine
            currentRequest.HandleId  = taskExecutionContext.BuildContext.BuildRequest.HandleId;
            currentRequest.NodeIndex = taskExecutionContext.BuildContext.BuildRequest.NodeIndex;

            try
            {
                outProcLoggingService.ProcessPostedLoggingEvents();
                parentCallback.PostBuildRequestsToHost(new BuildRequest[] { currentRequest });
            }
            catch (Exception e)
            {
                ReportUnhandledError(e);
            }
        }
Beispiel #12
0
 /// <summary>
 /// Default constructor for a routing context
 /// </summary>
 internal RequestRoutingContext
 (
     int handleId,
     int nodeIndex,
     int parentHandleId,
     int parentNodeIndex,
     int parentRequestId, 
     CacheScope cacheScope,
     BuildRequest triggeringBuildRequest,
     BuildEventContext buildEventContext
 )
     :base(handleId, nodeIndex, buildEventContext)
 {
     this.parentHandleId = parentHandleId;
     this.parentNodeIndex = parentNodeIndex;
     this.parentRequestId = parentRequestId;
     this.cacheScope = cacheScope;
     this.triggeringBuildRequest = triggeringBuildRequest;
 }
Beispiel #13
0
 /// <summary>
 /// Default constructor for a routing context
 /// </summary>
 internal RequestRoutingContext
 (
     int handleId,
     int nodeIndex,
     int parentHandleId,
     int parentNodeIndex,
     int parentRequestId,
     CacheScope cacheScope,
     BuildRequest triggeringBuildRequest,
     BuildEventContext buildEventContext
 )
     : base(handleId, nodeIndex, buildEventContext)
 {
     this.parentHandleId         = parentHandleId;
     this.parentNodeIndex        = parentNodeIndex;
     this.parentRequestId        = parentRequestId;
     this.cacheScope             = cacheScope;
     this.triggeringBuildRequest = triggeringBuildRequest;
 }
Beispiel #14
0
 public void BasicCacheOperation()
 {
     BuildPropertyGroup default_scope = new BuildPropertyGroup();
     CacheScope testScope = new CacheScope("Test.proj", new BuildPropertyGroup(), "2.0");
     // First add a single entry and verify that it is in the cache
     CacheEntry cacheEntry = new BuildResultCacheEntry("TestEntry", null, true);
     testScope.AddCacheEntry(cacheEntry);
     Assert.IsTrue(testScope.ContainsCacheEntry("TestEntry"), "Expect entry in the cache");
     CacheEntry inCacheEntry = testScope.GetCacheEntry("TestEntry");
     Assert.IsNotNull(inCacheEntry, "Cache should have an entry");
     Assert.IsTrue(inCacheEntry.IsEquivalent(cacheEntry), "Expect entry to be the same");
     // Add a second entry and then remove the first entry. Verify that the first entry
     // is not in the cache while the second entry is still there
     cacheEntry = new BuildResultCacheEntry("TestEntry2", null, true);
     testScope.AddCacheEntry(cacheEntry);
     testScope.ClearCacheEntry("TestEntry");
     Assert.IsFalse(testScope.ContainsCacheEntry("TestEntry"), "Didn't expect entry in the cache");
     Assert.IsTrue(testScope.ContainsCacheEntry("TestEntry2"), "Expected entry in the cache");
     Assert.IsNull(testScope.GetCacheEntry("TestEntry"), "Cache should  not have an entry");
     Assert.IsNotNull(testScope.GetCacheEntry("TestEntry2"), "Cache should have an entry");
 }
Beispiel #15
0
        /// <summary>
        /// This method creates a new routing context. This method is not thread safe and must be called
        /// only from the engine thread.
        /// </summary>
        internal int CreateRoutingContext
        (
            int nodeIndex,
            int parentHandleId,
            int parentNodeIndex,
            int parentRequestId,
            CacheScope cacheScope,
            BuildRequest triggeringBuildRequest,
            BuildEventContext buildEventContext
        )
        {
            int handleId = nextContextId;

            nextContextId++;

            RequestRoutingContext executionContext =
                new RequestRoutingContext(handleId, nodeIndex, parentHandleId, parentNodeIndex, parentRequestId,
                                          cacheScope, triggeringBuildRequest, buildEventContext);

            executionContexts.Add(handleId, executionContext);

            return(handleId);
        }
Beispiel #16
0
        /// <summary>
        /// This method get a result from the cache if every target is cached.
        /// If any of the target are not present in the cache null is returned. This method is not thread safe.
        /// </summary>
        internal BuildResult GetCachedBuildResult(BuildRequest buildRequest, out ArrayList actuallyBuiltTargets)
        {
            actuallyBuiltTargets = null;

            if (!buildRequest.UseResultsCache)
            {
                return(null);
            }

            // Retrieve list of scopes by this name
            string projectName = buildRequest.ProjectToBuild == null ?
                                 buildRequest.ProjectFileName : buildRequest.ProjectToBuild.FullFileName;

            // If the list exists search for matching scope properties otherwise create the list
            CacheScope cacheScope = GetCacheScopeIfExists(projectName, buildRequest.GlobalProperties, buildRequest.ToolsetVersion, CacheContentType.BuildResults);

            // If there is no cache entry for this project return null
            if (cacheScope == null)
            {
                return(null);
            }

            return(cacheScope.GetCachedBuildResult(buildRequest, out actuallyBuiltTargets));
        }
Beispiel #17
0
        /// <summary>
        /// This method return a cache scope with particular name and properties. If the cache
        /// scope doesn't exist it will be created. This method is thread safe.
        /// </summary>
        internal CacheScope GetCacheScope(string scopeName, BuildPropertyGroup scopeProperties, string scopeToolsVersion, CacheContentType cacheContentType)
        {
            // If the version is not specified default to the engine version
            if (scopeToolsVersion == null)
            {
                scopeToolsVersion = defaultToolsVersion;
            }

            // Retrieve the cache scope if it exists
            CacheScope cacheScope = GetCacheScopeIfExists(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);
            // If the scope doesn't exist create it
            if (cacheScope == null)
            {
                lock (cacheManagerLock)
                {
                    cacheScope = GetCacheScopeIfExists(scopeName, scopeProperties, scopeToolsVersion, cacheContentType);
                    
                    if (cacheScope == null)
                    {
                        // If the list of scopes doesn't exist create it
                        if (!cacheContents[(int)cacheContentType].ContainsKey(scopeName))
                        {
                            cacheContents[(int)cacheContentType].Add(scopeName, new List<CacheScope>());
                        }
                        // Create the scope and add it to the list
                        List<CacheScope> scopesByName = (List<CacheScope>)cacheContents[(int)cacheContentType][scopeName];
                        cacheScope = new CacheScope(scopeName, scopeProperties, scopeToolsVersion);
                        scopesByName.Add(cacheScope);
                    }
                }
            }

            return cacheScope;
        }
Beispiel #18
0
        /// <summary>
        /// This method creates a new routing context. This method is not thread safe and must be called
        /// only from the engine thread.
        /// </summary>
        internal int CreateRoutingContext
        (
            int nodeIndex,
            int parentHandleId,
            int parentNodeIndex,
            int parentRequestId,
            CacheScope cacheScope,
            BuildRequest triggeringBuildRequest,
            BuildEventContext buildEventContext
        )
        {
            int handleId = nextContextId;
            nextContextId = nextContextId + 1;

            RequestRoutingContext executionContext =
                new RequestRoutingContext(handleId, nodeIndex, parentHandleId, parentNodeIndex, parentRequestId, 
                                          cacheScope, triggeringBuildRequest, buildEventContext);

            executionContexts.Add(handleId, executionContext);

            return handleId;
        }
Beispiel #19
0
 public void AddRemoveBuildResults()
 {
     BuildPropertyGroup default_scope = new BuildPropertyGroup();
     CacheScope testScope = new CacheScope("Test.proj", new BuildPropertyGroup(), "2.0");
     // First add a single empty result (expect no crash)
     testScope.AddCacheEntryForBuildResults(resultWith0Outputs);
     // Add a single result - expect to find target in the cache
     testScope.AddCacheEntryForBuildResults(resultWith1Outputs);
     Assert.IsTrue(testScope.ContainsCacheEntry("Target1"), "Expected entry in the cache");
     Assert.IsNotNull(testScope.GetCacheEntry("Target1"), "Cache should have an entry");
     // Add a double result expect both target in the entry
     testScope.AddCacheEntryForBuildResults(resultWith2Outputs);
     Assert.IsTrue(testScope.ContainsCacheEntry("Target2"), "Expected entry in the cache");
     Assert.IsNotNull(testScope.GetCacheEntry("Target2"), "Cache should have an entry");
     Assert.IsTrue(testScope.ContainsCacheEntry("Target3"), "Expected entry in the cache");
     Assert.IsNotNull(testScope.GetCacheEntry("Target3"), "Cache should have an entry");
     // Double add a result ( expect no crash since it is identical )
     testScope.AddCacheEntryForBuildResults(resultWith1Outputs);
     // Add an uncacheable result and verify that it is not in the cache
     testScope.AddCacheEntryForBuildResults(uncacheableResult);
     Assert.IsFalse(testScope.ContainsCacheEntry("Target4"), "Didn't expect entry in the cache");
     Assert.IsNull(testScope.GetCacheEntry("Target4"), "Cache should  not have an entry");
 }