コード例 #1
0
        /// <summary>
        /// Populates the module specific mount expanders from modules in the module configurations
        /// </summary>
        /// <param name="modules">the module configurations</param>
        /// <param name="moduleMountTables">the module mounts tables</param>
        /// <returns>true if the operations were performed successfully</returns>
        public bool PopulateModuleMounts(IEnumerable <IModuleConfiguration> modules, out IDictionary <ModuleId, MountsTable> moduleMountTables)
        {
            moduleMountTables = new Dictionary <ModuleId, MountsTable>();
            bool success = true;

            foreach (var module in modules)
            {
                if (module.Mounts.Count != 0)
                {
                    MountsTable moduleMountsTable = new MountsTable(this, module.ModuleId);
                    foreach (var mount in module.Mounts)
                    {
                        moduleMountsTable.AddResolvedMount(mount);
                    }

                    moduleMountTables[module.ModuleId] = moduleMountsTable;
                    success &= moduleMountsTable.CompleteInitialization();
                }
            }

            if (!success)
            {
                moduleMountTables = null;
            }

            return(success);
        }
コード例 #2
0
        private IPipGraphBuilder CreatePipGraphBuilder(
            LoggingContext loggingContext,
            MountsTable mountsTable,
            [CanBeNull] GraphReuseResult reuseResult)
        {
            var builder = new PipGraph.Builder(
                EngineSchedule.CreateEmptyPipTable(Context),
                Context,
                Scheduler.Tracing.Logger.Log,
                loggingContext,
                Configuration,
                mountsTable.MountPathExpander,
                fingerprintSalt: Configuration.Cache.CacheSalt,
                directoryMembershipFingerprinterRules: new Scheduler.DirectoryMembershipFingerprinterRuleSet(Configuration, Context.StringTable));

            PatchablePipGraph patchableGraph = null;

            if (Configuration.FrontEnd.UseGraphPatching() && reuseResult?.IsPartialReuse == true)
            {
                Logger.Log.UsingPatchableGraphBuilder(loggingContext);
                patchableGraph = new PatchablePipGraph(
                    oldPipGraph: reuseResult.PipGraph.DataflowGraph,
                    oldPipTable: reuseResult.PipGraph.PipTable,
                    graphBuilder: builder,
                    maxDegreeOfParallelism: Configuration.FrontEnd.MaxFrontEndConcurrency());
            }

            return((IPipGraphBuilder)patchableGraph ?? builder);
        }
コード例 #3
0
 private void AddConfigurationMounts(MountsTable mountsTable)
 {
     // Add configuration mounts
     foreach (var mount in Configuration.Mounts)
     {
         mountsTable.AddResolvedMount(mount, new LocationData(Configuration.Layout.PrimaryConfigFile, 0, 0));
     }
 }
コード例 #4
0
        private bool CompleteInitialization(LoggingContext loggingContext, MountsTable mountsTable)
        {
            if (!mountsTable.CompleteInitialization())
            {
                Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.CompleteInitialization()");
                return(false);
            }

            return(true);
        }
コード例 #5
0
        /// <summary>
        /// Private constructor. Please use CreateAndRegister factory method.
        /// </summary>
        private MountsTable(LoggingContext loggingContext, BuildXLContext context, MountPathExpander mountPathExpander = null)
        {
            m_parent          = null;
            m_loggingContext  = loggingContext;
            m_context         = context;
            MountPathExpander = mountPathExpander ?? new MountPathExpander(context.PathTable);

            m_mountMapBuilder             = new ConcurrentDictionary <AbsolutePath, IMount>();
            m_mountsByName                = new ConcurrentDictionary <string, IMount>(StringComparer.OrdinalIgnoreCase);
            m_mountPathIdentifiersByMount = new ConcurrentDictionary <IMount, PathAtom>();
            m_mountLocationsByMount       = new ConcurrentDictionary <IMount, LocationData>();
            m_alternativeRoots            = new ConcurrentDictionary <AbsolutePath, IMount>();
        }
コード例 #6
0
        /// <summary>
        /// Creates a default mount table with the regular system and configuration defined mounts and sets it.
        /// </summary>
        public bool TryPopulateWithDefaultMountsTable(LoggingContext loggingContext, BuildXLContext buildXLContext, IConfiguration configuration, IReadOnlyDictionary <string, string> properties)
        {
            var mountsTable = MountsTable.CreateAndRegister(loggingContext, buildXLContext, configuration, properties);

            if (!mountsTable.CompleteInitialization())
            {
                return(false);
            }

            SetMountsTable(mountsTable);

            return(true);
        }
コード例 #7
0
        private static void RegisterRedirectedMount(
            BuildXLContext context,
            IReadOnlyDictionary <string, string> properties,
            MountsTable table,
            string mountName,
            string envVariable        = null,
            bool allowCreateDirectory = false)
        {
            envVariable = envVariable ?? mountName.ToCanonicalizedEnvVar();

            if (!properties.TryGetValue(envVariable, out string redirectedPath))
            {
                Contract.Assert(false, $"Failed to register a redirected mount ('{mountName}') using a path defined by '{envVariable}' environment variable. The variable was not specified.");
            }

            table.AddStaticSystemMount(mountName, redirectedPath, allowCreateDirectory);

            // We don't need to add the real path of redirected mount into alternative roots.
            // Internally inside BuildXL itself, all accesses to user-related paths should go through the redirected paths by querying the mount table,
            // e.g. in DScript, one should use Context.getMount(...) to get user-related paths.
            // For any executed tool, if the tool accesses a user-related path, then the directory translation will translate that path into the redirected one.
            // We also don't want to add the real paths to the mount table because those paths will also go to the path expander that is part of the cached graph.
            // If the graph is used across builds, then the real user-related paths are not guaranteed to be the same.
        }
コード例 #8
0
        public static MountsTable CreateAndRegister(
            LoggingContext loggingContext,
            BuildXLContext context,
            IConfiguration configuration,
            [CanBeNull] IReadOnlyDictionary <string, string> properties)
        {
            Contract.Requires(context != null);
            Contract.Requires(configuration != null);
            Contract.Requires(loggingContext != null);

            ILayoutConfiguration layout = configuration.Layout;
            IReadOnlyList <IResolverSettings> resolverSettings = configuration.Resolvers;

            var table = new MountsTable(loggingContext, context);

            // If any resolver settings allows for a writable source directory, then the source directory is writable
            var writableSourceRoot = resolverSettings.Any(resolverSetting => resolverSetting.AllowWritableSourceDirectory);

            table.AddStaticMount("BuildEnginePath", layout.BuildEngineDirectory, isWriteable: false);
            table.AddStaticMount("SourceRoot", layout.SourceDirectory, isWriteable: writableSourceRoot);
            table.AddStaticMount("ObjectRoot", layout.ObjectDirectory, isWriteable: true, isScrubbable: true);
            table.AddStaticMount(
                "LogsDirectory",
                configuration.Logging.RedirectedLogsDirectory.IsValid
                ? configuration.Logging.RedirectedLogsDirectory
                : configuration.Logging.LogsDirectory,
                isWriteable: true,
                allowCreateDirectory: true);

            if (layout.FrontEndDirectory.IsValid)
            {
                // This location is used only for storing nuget packages and generated specs so far.
                table.AddStaticMount("FrontEnd", layout.FrontEndDirectory, isWriteable: true, isScrubbable: false);
            }
            if (layout.TempDirectory.IsValid)
            {
                table.AddStaticMount("TempRoot", layout.TempDirectory, isWriteable: true, isScrubbable: true);
            }

            // Cross Plat supported MountPoints
            table.AddStaticSystemMount("ProgramData", Environment.SpecialFolder.CommonApplicationData);
            table.AddStaticSystemMount("ProgramFiles", Environment.SpecialFolder.ProgramFiles, trackSourceFileChanges: true);
            table.AddStaticSystemMount("System", Environment.SpecialFolder.System);
            if (!layout.RedirectedUserProfileJunctionRoot.IsValid)
            {
                table.AddStaticSystemMount("UserProfile", Environment.SpecialFolder.UserProfile);
                table.AddStaticSystemMount("AppData", Environment.SpecialFolder.ApplicationData, allowCreateDirectory: true);
                table.AddStaticSystemMount("LocalAppData", Environment.SpecialFolder.LocalApplicationData, allowCreateDirectory: true);
            }
            else
            {
                // User profile is redirected; need to use the paths specified in the env block.
                Contract.Assert(properties != null);
                RegisterRedirectedMount(context, properties, table, "UserProfile");
                RegisterRedirectedMount(context, properties, table, "AppData", allowCreateDirectory: true);
                RegisterRedirectedMount(context, properties, table, "LocalAppData", allowCreateDirectory: true);
            }

            if (!OperatingSystemHelper.IsUnixOS)
            {
                // Add system mounts that are Windows Only
                table.AddStaticSystemMount("Windows", Environment.SpecialFolder.Windows);
                table.AddStaticSystemMount("ProgramFilesX86", Environment.SpecialFolder.ProgramFilesX86, trackSourceFileChanges: true);
                table.AddStaticSystemMount("CommonProgramFiles", Environment.SpecialFolder.CommonProgramFiles, trackSourceFileChanges: true);
                table.AddStaticSystemMount("CommonProgramFilesX86", Environment.SpecialFolder.CommonProgramFilesX86, trackSourceFileChanges: true);

                if (!layout.RedirectedUserProfileJunctionRoot.IsValid)
                {
                    table.AddStaticSystemMount("InternetCache", Environment.SpecialFolder.InternetCache);
                    table.AddStaticSystemMount("InternetHistory", Environment.SpecialFolder.History);
                    table.AddStaticSystemMount("INetCookies", Environment.SpecialFolder.Cookies, allowCreateDirectory: true);
                    table.AddStaticSystemMount("LocalLow", FileUtilities.KnownFolderLocalLow);
                }
                else
                {
                    // User profile is redirected; need to use the paths specified in the env block.
                    Contract.Assert(properties != null);
                    RegisterRedirectedMount(context, properties, table, "InternetCache");
                    RegisterRedirectedMount(context, properties, table, "InternetHistory");
                    RegisterRedirectedMount(context, properties, table, "INetCookies", allowCreateDirectory: true);
                    RegisterRedirectedMount(context, properties, table, "LocalLow");
                }
            }
            else
            {
                table.AddStaticSystemMount("Applications", MacPaths.Applications, trackSourceFileChanges: true);
                table.AddStaticSystemMount("Bin", MacPaths.Bin, trackSourceFileChanges: true);
                table.AddStaticSystemMount("UsrBin", MacPaths.UsrBin, trackSourceFileChanges: true);
                table.AddStaticSystemMount("UsrInclude", MacPaths.UsrInclude, trackSourceFileChanges: true);
                table.AddStaticSystemMount("UsrLib", MacPaths.UsrLib, trackSourceFileChanges: true);
                table.AddStaticSystemMount("Library", MacPaths.Library, trackSourceFileChanges: true);
                table.AddStaticSystemMount("UserProvisioning", MacPaths.UserProvisioning, trackSourceFileChanges: true);
            }

            return(table);
        }
コード例 #9
0
 /// <summary>
 /// Private constructor used for creating module specific mount tables
 /// </summary>
 private MountsTable(MountsTable parent, ModuleId moduleId)
     : this(parent.m_loggingContext, parent.m_context)
 {
     m_parent          = parent;
     MountPathExpander = parent.MountPathExpander.CreateModuleMountExpander(moduleId);
 }
コード例 #10
0
 /// <nodoc />
 public void SetMountsTable(MountsTable mountsTable)
 {
     m_mountsTable = mountsTable;
 }
コード例 #11
0
        private bool AddConfigurationMountsAndCompleteInitialization(LoggingContext loggingContext, MountsTable mountsTable)
        {
            // Add configuration mounts
            foreach (var mount in Configuration.Mounts)
            {
                mountsTable.AddResolvedMount(mount, new LocationData(Configuration.Layout.PrimaryConfigFile, 0, 0));
            }

            if (!mountsTable.CompleteInitialization())
            {
                Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.CompleteInitialization()");
                return(false);
            }

            return(true);
        }
コード例 #12
0
        private bool ConstructAndEvaluateGraph(
            LoggingContext loggingContext,
            FrontEndEngineAbstraction frontEndEngineAbstration,
            CacheInitializationTask engineCacheTask,
            MountsTable mountsTable,
            EvaluationFilter evaluationFilter,
            [CanBeNull] GraphReuseResult reuseResult,
            out PipGraph pipGraph)
        {
            Contract.Requires(frontEndEngineAbstration != null);
            Contract.Requires(engineCacheTask != null);
            Contract.Requires(mountsTable != null);

            pipGraph = null;
            IPipGraphBuilder pipGraphBuilder = null;

            if (!AddConfigurationMountsAndCompleteInitialization(loggingContext, mountsTable))
            {
                return(false);
            }

            IDictionary <ModuleId, MountsTable> moduleMountsTableMap;

            if (!mountsTable.PopulateModuleMounts(Configuration.ModulePolicies.Values, out moduleMountsTableMap))
            {
                Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.PopulateModuleMounts()");
                return(false);
            }

            m_visualization?.MountsTable.MakeAvailable(mountsTable);

            if ((Configuration.Engine.Phase & EnginePhases.Schedule) != 0)
            {
                pipGraphBuilder = CreatePipGraphBuilder(loggingContext, mountsTable, reuseResult);
            }

            // Have to do some horrible magic here to get to a proper Task<T> with the BuildXL cache since
            // someone updated the engine cache to be an await style pattern, and there is no way to get to the EngineCache
            // If the cache was fast to startup, but perhaps blocked itself on first access we wouldn't have to do all these hoops.
            Func <Task <Possible <EngineCache> > > getBuildCacheTask =
                async() =>
            {
                return((await engineCacheTask).Then(engineCache => engineCache.CreateCacheForContext()));
            };

            if (!FrontEndController.PopulateGraph(
                    getBuildCacheTask(),
                    pipGraphBuilder,
                    frontEndEngineAbstration,
                    evaluationFilter,
                    Configuration,
                    m_initialCommandLineConfiguration.Startup))
            {
                LogFrontEndStats(loggingContext);

                Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after FrontEndController.PopulateGraph()");
                return(false);
            }

            LogFrontEndStats(loggingContext);

            // Pip graph must become immutable now that evaluation is done (required to construct a scheduler).
            return(pipGraphBuilder == null || (pipGraph = pipGraphBuilder.Build()) != null);
        }
コード例 #13
0
        /// <summary>
        /// Check if pip graph can be reused.
        ///
        /// There are 3 opportunities to determine a graph match. The applicability of each depends on the distributed build roles.
        ///   (1) from engine cache,
        ///   (2) from content cache, and
        ///   (3) from master node (if running on a worker node in a distributed build)
        /// </summary>
        private GraphCacheCheckStatistics CheckGraphCacheReuse(
            LoggingContext outerLoggingContext,
            int maxDegreeOfParallelism,
            GraphFingerprint graphFingerprint,
            IReadOnlyDictionary <string, string> properties,
            CacheInitializationTask cacheInitializationTask,
            JournalState journalState,
            out EngineSerializer serializer,
            out InputTracker.InputChanges inputChanges)
        {
            serializer   = CreateEngineSerializer(outerLoggingContext);
            inputChanges = null;
            var cacheGraphStats = default(GraphCacheCheckStatistics);

            using (var timeBlock = TimedBlock <EmptyStruct, GraphCacheCheckStatistics> .Start(
                       outerLoggingContext,
                       Statistics.GraphCacheReuseCheck,
                       (context, emptyStruct) => Logger.Log.CheckingForPipGraphReuseStart(context),
                       default(EmptyStruct),
                       (loggingContext, stats) =>
            {
                Logger.Log.CheckingForPipGraphReuseComplete(loggingContext, stats);

                // On misses we want to give the user a message for why there was a miss
                if (!stats.WasHit)
                {
                    Contract.Assume(stats.MissReason != GraphCacheMissReason.NoMiss);
                    Logger.Log.GraphNotReusedDueToChangedInput(loggingContext, stats.MissMessageForConsole, stats.MissDescription);
                }

                m_enginePerformanceInfo.GraphCacheCheckDurationMs = stats.ElapsedMilliseconds;
                m_enginePerformanceInfo.GraphCacheCheckJournalEnabled = stats.JournalEnabled;
            },
                       () => cacheGraphStats))
            {
                var loggingContext = timeBlock.LoggingContext;
                var effectiveEnvironmentVariables = FrontEndEngineImplementation.PopulateFromEnvironmentAndApplyOverrides(properties);
                var availableMounts = MountsTable.CreateAndRegister(loggingContext, Context, Configuration, m_initialCommandLineConfiguration.Startup.Properties);

                if (!AddConfigurationMountsAndCompleteInitialization(loggingContext, availableMounts))
                {
                    return(cacheGraphStats);
                }

                cacheGraphStats.JournalEnabled = journalState.IsEnabled;

                // ************************************************************
                // 1. Engine cache check:
                // ************************************************************
                // * Single machine builds
                // Distributed builds rely on the graph being available via the cache for it to be shared between master
                // and workers. So even if the master could have had a hit from the engine cache, it must be ignored
                // since the workers would not be able to retrieve it.
                if (!HasExplicitlyLoadedGraph(Configuration.Cache) &&
                    !Configuration.Schedule.ForceUseEngineInfoFromCache &&
                    Configuration.Distribution.BuildRole == DistributedBuildRoles.None)
                {
                    Contract.Assume(
                        graphFingerprint != null,
                        "When looking up a cached graph on a distributed master or single-machine build, a graph fingerprint must be computed");

                    InputTracker.MatchResult engineCacheMatchResult = CheckIfAvailableInputsToGraphMatchPreviousRun(
                        loggingContext,
                        serializer,
                        graphFingerprint: graphFingerprint,
                        availableEnvironmentVariables: effectiveEnvironmentVariables,
                        availableMounts: availableMounts,
                        journalState: journalState,
                        maxDegreeOfParallelism: maxDegreeOfParallelism);
                    cacheGraphStats.ObjectDirectoryHit        = engineCacheMatchResult.Matches;
                    cacheGraphStats.ObjectDirectoryMissReason = engineCacheMatchResult.MissType;
                    cacheGraphStats.MissReason        = engineCacheMatchResult.MissType;
                    cacheGraphStats.MissDescription   = engineCacheMatchResult.FirstMissIdentifier;
                    cacheGraphStats.WasHit            = engineCacheMatchResult.Matches;
                    cacheGraphStats.InputFilesChecked = engineCacheMatchResult.FilesChecked;

                    // Checking the engine cache may have used a FileChangeTracker and provided information about
                    // files/ContentHash pairs that were unchanged from the previous run. Hold onto this information as it may
                    // be useful when eventually parsing files.
                    // The FileChangeTracker is now up to date. All changed files have been removed from it. It can be reused
                    // for a future build with the same fingerprint, though it may be tracking extra files, for example if
                    // a spec was removed since the previous build.
                    inputChanges = engineCacheMatchResult.InputChanges;
                }

                var shouldTryContentCache =
                    !cacheGraphStats.WasHit &&
                    Configuration.Distribution.BuildRole != DistributedBuildRoles.Worker &&
                    Configuration.Cache.AllowFetchingCachedGraphFromContentCache &&
                    !HasExplicitlyLoadedGraph(Configuration.Cache) &&
                    (!Configuration.FrontEnd.UseSpecPublicFacadeAndAstWhenAvailable.HasValue ||
                     !Configuration.FrontEnd.UseSpecPublicFacadeAndAstWhenAvailable.Value);

                // ************************************************************
                // 2. Content cache check:
                // ************************************************************
                // * Single machine builds that missed earlier
                // * Distributed masters
                // This is the only valid place for the master to get a hit since it must be in the cache for the
                // workers to get it.
                if (shouldTryContentCache)
                {
                    // Since an in-place match did not succeed, we need a readied cache to try again.
                    // TODO: This logs an error if it fails. We are assuming some later thing will ensure that, if failed,
                    //       the engine fails overall.
                    Possible <CacheInitializer> possibleCacheInitializerForFallback = cacheInitializationTask.GetAwaiter().GetResult();
                    if (possibleCacheInitializerForFallback.Succeeded)
                    {
                        CacheInitializer cacheInitializerForFallback = possibleCacheInitializerForFallback.Result;
                        using (EngineCache cacheForFallback = cacheInitializerForFallback.CreateCacheForContext())
                        {
                            var cacheGraphProvider = new CachedGraphProvider(
                                loggingContext,
                                Context,
                                cacheForFallback,
                                FileContentTable,
                                maxDegreeOfParallelism);

                            var cachedGraphDescriptor =
                                cacheGraphProvider.TryGetPipGraphCacheDescriptorAsync(graphFingerprint, effectiveEnvironmentVariables, availableMounts.MountsByName).Result;

                            if (cachedGraphDescriptor == null)
                            {
                                // There was no matching fingerprint in the cache. Record the status for logging before returning.
                                cacheGraphStats.CacheMissReason = GraphCacheMissReason.FingerprintChanged;
                                SetMissReasonIfUnset(ref cacheGraphStats, cacheGraphStats.CacheMissReason);
                                return(cacheGraphStats);
                            }

                            var fetchEngineScheduleContent = EngineSchedule.TryFetchFromCacheAsync(
                                loggingContext,
                                Context,
                                cacheForFallback,
                                cachedGraphDescriptor,
                                serializer,
                                FileContentTable,
                                m_tempCleaner).Result;

                            if (!fetchEngineScheduleContent)
                            {
                                cacheGraphStats.CacheMissReason = GraphCacheMissReason.NoPreviousRunToCheck;
                                SetMissReasonIfUnset(ref cacheGraphStats, cacheGraphStats.CacheMissReason);
                                return(cacheGraphStats);
                            }

                            // If a distributed master, take note of the graph fingerprint
                            if (Configuration.Distribution.BuildRole == DistributedBuildRoles.Master)
                            {
                                Contract.Assert(cachedGraphDescriptor != null);
                                m_masterService.CachedGraphDescriptor = cachedGraphDescriptor;
                            }

                            Logger.Log.FetchedSerializedGraphFromCache(outerLoggingContext);

                            cacheGraphStats.CacheMissReason = GraphCacheMissReason.NoMiss;
                            cacheGraphStats.MissReason      = cacheGraphStats.CacheMissReason;
                            cacheGraphStats.WasHit          = true;
                        }
                    }
                    else
                    {
                        cacheGraphStats.CacheMissReason = GraphCacheMissReason.CacheFailure;
                        SetMissReasonIfUnset(ref cacheGraphStats, cacheGraphStats.CacheMissReason);
                        return(cacheGraphStats);
                    }
                }

                // ************************************************************
                // 3. Query distributed master
                // ************************************************************
                // * Distributed workers only
                if (Configuration.Distribution.BuildRole == DistributedBuildRoles.Worker)
                {
                    Contract.Assume(
                        graphFingerprint == null,
                        "Distributed workers should request a graph fingerprint from the master (not compute one locally)");
                    Possible <CacheInitializer> possibleCacheInitializerForWorker = cacheInitializationTask.GetAwaiter().GetResult();
                    Contract.Assume(possibleCacheInitializerForWorker.Succeeded, "Workers must have a valid cache");
                    CacheInitializer cacheInitializerForWorker = possibleCacheInitializerForWorker.Result;

                    using (EngineCache cacheForWorker = cacheInitializerForWorker.CreateCacheForContext())
                    {
                        PipGraphCacheDescriptor schedulerStateDescriptor;
                        if (!m_workerService.TryGetBuildScheduleDescriptor(out schedulerStateDescriptor) ||
                            !EngineSchedule.TryFetchFromCacheAsync(
                                outerLoggingContext,
                                Context,
                                cacheForWorker,
                                schedulerStateDescriptor,
                                serializer,
                                FileContentTable,
                                m_tempCleaner).Result)
                        {
                            cacheGraphStats.CacheMissReason = GraphCacheMissReason.NoFingerprintFromMaster;
                            cacheGraphStats.MissReason      = cacheGraphStats.CacheMissReason;
                            return(cacheGraphStats);
                        }

                        AsyncOut <AbsolutePath> symlinkFileLocation = new AsyncOut <AbsolutePath>();
                        if (!SymlinkDefinitionFileProvider.TryFetchWorkerSymlinkFileAsync(
                                outerLoggingContext,
                                Context.PathTable,
                                cacheForWorker,
                                Configuration.Layout,
                                m_workerService,
                                symlinkFileLocation).Result)
                        {
                            cacheGraphStats.CacheMissReason = GraphCacheMissReason.NoFingerprintFromMaster;
                            cacheGraphStats.MissReason      = cacheGraphStats.CacheMissReason;
                            return(cacheGraphStats);
                        }

                        m_workerSymlinkDefinitionFile = symlinkFileLocation.Value;

                        // Success. Populate the stats
                        cacheGraphStats.WasHit          = true;
                        cacheGraphStats.WorkerHit       = true;
                        cacheGraphStats.MissReason      = GraphCacheMissReason.NoMiss;
                        cacheGraphStats.CacheMissReason = GraphCacheMissReason.NoMiss;
                    }
                }
            }

            return(cacheGraphStats);
        }
コード例 #14
0
        /// <summary>
        /// Creates an instance of <see cref="FrontEndEngineImplementation"/>.
        /// </summary>
        public FrontEndEngineImplementation(
            LoggingContext loggingContext,
            PathTable pathTable,
            IConfiguration configuration,
            IStartupConfiguration startupConfiguration,
            MountsTable mountsTable,
            InputTracker inputTracker,
            SnapshotCollector snapshotCollector,
            DirectoryTranslator directoryTranslator,
            Func <FileContentTable> getFileContentTable,
            int timerUpdatePeriod,
            bool isPartialReuse,
            IEnumerable <IFrontEnd> registeredFrontends)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(pathTable != null);
            Contract.Requires(configuration != null);
            Contract.Requires(startupConfiguration != null);
            Contract.Requires(mountsTable != null);
            Contract.Requires(inputTracker != null);
            Contract.Requires(getFileContentTable != null);
            Contract.Requires(registeredFrontends != null);

            m_loggingContext                  = loggingContext;
            PathTable                         = pathTable;
            m_mountsTable                     = mountsTable;
            m_inputTracker                    = inputTracker;
            m_getFileContentTable             = getFileContentTable;
            m_isPartialReuse                  = isPartialReuse;
            m_frontendsEnvironmentRestriction = registeredFrontends.ToDictionary(frontend => frontend.Name, frontEnd => frontEnd.ShouldRestrictBuildParameters);
            m_snapshotCollector               = snapshotCollector;
            GetTimerUpdatePeriod              = timerUpdatePeriod;
            Layout = configuration.Layout;

            if (ShouldUseSpecCache(configuration))
            {
                m_specCache = new FileCombiner(
                    loggingContext,
                    Path.Combine(configuration.Layout.EngineCacheDirectory.ToString(PathTable), SpecCacheFileName),
                    FileCombiner.FileCombinerUsage.SpecFileCache,
                    configuration.FrontEnd.LogStatistics);
            }

            m_allBuildParameters = new ConcurrentDictionary <string, TrackedValue>(StringComparer.OrdinalIgnoreCase);

            foreach (var kvp in PopulateFromEnvironmentAndApplyOverrides(loggingContext, startupConfiguration.Properties).ToDictionary())
            {
                m_allBuildParameters.TryAdd(kvp.Key, new TrackedValue(kvp.Value, false));
            }

            m_localDiskContentStore = new LocalDiskContentStore(
                loggingContext,
                PathTable,
                m_getFileContentTable(),
                m_inputTracker.FileChangeTracker,
                directoryTranslator,
                vfsCasRoot: configuration.Cache.VfsCasRoot);

            m_localDiskContentStoreConcurrencyLimiter = new ActionBlockSlim <MaterializeFileRequest>(
                Environment.ProcessorCount,
                request =>
            {
                var requestCompletionSource = request.CompletionSource;

                try
                {
                    var materializeResult = m_localDiskContentStore.TryMaterializeAsync(
                        request.Cache,
                        request.FileRealizationModes,
                        request.Path,
                        request.ContentHash,
                        trackPath: request.TrackPath,
                        recordPathInFileContentTable: request.RecordPathInFileContentTable).GetAwaiter().GetResult();

                    requestCompletionSource.SetResult(materializeResult);
                }
                catch (TaskCanceledException)
                {
                    requestCompletionSource.SetCanceled();
                }
                catch (Exception e)
                {
                    requestCompletionSource.SetException(e);
                }
            });
        }
コード例 #15
0
 /// <nodoc />
 public void SetMountsTable(MountsTable mountsTable)
 {
     m_customMountsTable = mountsTable.AllMountsSoFar.ToDictionary(mount => mount.Name.ToString(m_pathTable.StringTable), mount => mount);
 }