예제 #1
0
        private GraphReuseResult ReloadEngineSchedule(
            EngineSerializer serializer,
            CacheInitializationTask cacheInitializationTask,
            JournalState journalState,
            LoggingContext loggingContext,
            EngineState engineState,
            InputTracker.InputChanges inputChanges,
            string buildEngineFingerprint)
        {
            Tuple <EngineSchedule, EngineContext, IConfiguration> t = null;

            try
            {
                t = EngineSchedule.LoadAsync(
                    Context,
                    serializer,
                    cacheInitializationTask,
                    FileContentTable,
                    journalState,
                    Configuration,
                    loggingContext,
                    m_collector,
                    m_directoryTranslator,
                    engineState,
                    tempCleaner: m_tempCleaner,
                    buildEngineFingerprint).GetAwaiter().GetResult();
            }
            catch (BuildXLException e)
            {
                Logger.Log.FailedReloadPipGraph(loggingContext, e.ToString());
            }

            if (t == null)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            // Invalidate the old context to ensure nothing uses it anymore
            // Update engine state to deserialized state
            Context.Invalidate();
            Context = t.Item2;

            // Update configuration state to deserialized state
            Configuration = t.Item3;

            // Copy the graph files to the session output
            if (Configuration.Distribution.BuildRole != DistributedBuildRoles.Worker)
            {
                // No need to link these files to the logs directory on workers since they are redundant with what's on the orchestrator
                m_executionLogGraphCopy  = TryCreateHardlinksToScheduleFilesInSessionFolder(loggingContext, serializer);
                m_previousInputFilesCopy = TryCreateHardlinksToPreviousInputFilesInSessionFolder(loggingContext, serializer);
            }

            return(GraphReuseResult.CreateForFullReuse(t.Item1, inputChanges));
        }
예제 #2
0
        private GraphReuseResult ReloadPipGraphOnly(
            EngineSerializer serializer,
            LoggingContext loggingContext,
            EngineState engineState,
            InputTracker.InputChanges inputChanges)
        {
            Tuple <PipGraph, EngineContext> t = null;

            try
            {
                t = EngineSchedule.LoadPipGraphAsync(
                    Context,
                    serializer,
                    Configuration,
                    loggingContext,
                    engineState).GetAwaiter().GetResult();
            }
            catch (BuildXLException e)
            {
                Logger.Log.FailedReloadPipGraph(loggingContext, e.ToString());
            }

            if (t == null)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            var newContext = t.Item2;

            if (!ShouldReuseReloadedEngineContextGivenHistoricData(loggingContext, newContext.NextHistoricTableSizes))
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            var newPathTable = newContext.PathTable;
            var pathRemapper = new PathRemapper(Context.PathTable, newPathTable);

            Configuration = new ConfigurationImpl(Configuration, pathRemapper);

            m_initialCommandLineConfiguration = new CommandLineConfiguration(m_initialCommandLineConfiguration, pathRemapper);

            // Invalidate the old context to ensure nothing uses it anymore
            // Update engine state to deserialized state
            Context.Invalidate();
            Context = newContext;

            // Additionally recreate front end controller, because the old one uses the invalidated context.
            //   - to fully initialize the front end, we have to go through all the steps that have already been
            //     executed on the old controller; those steps are (1) InitializeHost, and (2) ParseConfig
            FrontEndController = m_frontEndControllerFactory.Create(Context.PathTable, Context.SymbolTable);
            FrontEndController.InitializeHost(Context.ToFrontEndContext(loggingContext), m_initialCommandLineConfiguration);
            FrontEndController.ParseConfig(m_initialCommandLineConfiguration);

            return(GraphReuseResult.CreateForPartialReuse(t.Item1, inputChanges));
        }
예제 #3
0
        private GraphReuseResult ReloadEngineSchedule(
            EngineSerializer serializer,
            CacheInitializationTask cacheInitializationTask,
            JournalState journalState,
            LoggingContext loggingContext,
            EngineState engineState,
            InputTracker.InputChanges inputChanges,
            string buildEngineFingerprint)
        {
            Tuple <EngineSchedule, EngineContext, IConfiguration> t = EngineSchedule.LoadAsync(
                Context,
                serializer,
                cacheInitializationTask,
                FileContentTable,
                journalState,
                Configuration,
                loggingContext,
                m_collector,
                m_directoryTranslator,
                engineState,
                symlinkDefinitionFile: IsDistributedWorker ?
                m_workerSymlinkDefinitionFile.Value :
                Configuration.Layout.SymlinkDefinitionFile,
                tempCleaner: m_tempCleaner,
                buildEngineFingerprint).GetAwaiter().GetResult();

            if (t == null)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            // Invalidate the old context to ensure nothing uses it anymore
            // Update engine state to deserialized state
            Context.Invalidate();
            Context = t.Item2;

            // Update configuration state to deserialized state
            Configuration = t.Item3;

            // Copy the graph files to the session output
            m_executionLogGraphCopy  = TryCreateHardlinksToScheduleFilesInSessionFolder(loggingContext, serializer);
            m_previousInputFilesCopy = TryCreateHardlinksToPreviousInputFilesInSessionFolder(loggingContext, serializer);

            return(GraphReuseResult.CreateForFullReuse(t.Item1, inputChanges));
        }
예제 #4
0
        /// <summary>
        /// Attempt to reuse the pip graph from a previous run
        /// </summary>
        private GraphReuseResult AttemptToReuseGraph(
            LoggingContext outerLoggingContext,
            int maxDegreeOfParallelism,
            GraphFingerprint graphFingerprint,
            IReadOnlyDictionary <string, string> properties,
            CacheInitializationTask cacheInitializationTask,
            JournalState journalState,
            EngineState engineState)
        {
            Contract.Ensures(Contract.Result <GraphReuseResult>() != null);

            GraphCacheCheckStatistics cacheGraphStats = CheckGraphCacheReuse(
                outerLoggingContext,
                maxDegreeOfParallelism,
                graphFingerprint,
                properties,
                cacheInitializationTask,
                journalState,
                out var serializer,
                out var inputChanges);

            // There are 3 cases in which we should reload the graph
            //   - we have a graph cache hit
            //   - the build is configured to reload the graph no matter what
            //   - graph patching is enabled and the reason for cache miss was 'SpecFileChanges'
            var shouldReload =
                cacheGraphStats.WasHit ||
                Configuration.Cache.CachedGraphPathToLoad.IsValid ||
                PartialReloadCondition(Configuration.FrontEnd, cacheGraphStats);

            if (!shouldReload)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            bool fullReload = !PartialReloadCondition(Configuration.FrontEnd, cacheGraphStats);

            // Now we actually reload the graph
            var reloadStats = default(GraphCacheReloadStatistics);

            using (var tb = TimedBlock <EmptyStruct, GraphCacheReloadStatistics> .Start(
                       outerLoggingContext,
                       Statistics.GraphCacheReload,
                       (context, emptyStruct) =>
            {
                if (fullReload)
                {
                    Logger.Log.ReloadingPipGraphStart(context);
                }
                else
                {
                    Logger.Log.PartiallyReloadingEngineState(context);
                }
            },
                       default(EmptyStruct),
                       (context, graphCacheCheckStatistics) =>
            {
                Logger.Log.PartiallyReloadingEngineStateComplete(context, graphCacheCheckStatistics);
                m_enginePerformanceInfo.GraphReloadDurationMs = graphCacheCheckStatistics.ElapsedMilliseconds;
            },
                       () => reloadStats))
            {
                var reuseResult = fullReload
                    ? ReloadEngineSchedule(
                    serializer,
                    cacheInitializationTask,
                    journalState,
                    tb.LoggingContext,
                    engineState,
                    inputChanges,
                    graphFingerprint?.ExactFingerprint.BuildEngineHash.ToString())
                    : ReloadPipGraphOnly(serializer, tb.LoggingContext, engineState, inputChanges);

                // Set telemetry statistics
                reloadStats.SerializedFileSizeBytes = serializer.BytesDeserialized;
                reloadStats.Success = !reuseResult.IsNoReuse;

                return(reuseResult);
            }
        }