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)); }
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); }