private static Scheduler CreateInternal( PipExecutionContext context, PipGraph pipGraph, IPipQueue queue, EngineCache cache, IConfiguration configuration) { Contract.Requires(context != null); Contract.Requires(queue != null); Contract.Requires(cache != null); Contract.Requires(configuration != null); var fileContentTable = FileContentTable.CreateNew(); var fileAccessWhiteList = new FileAccessWhitelist(context); var testHooks = new SchedulerTestHooks(); return(new Scheduler( pipGraph, queue, context, fileContentTable, cache: cache, loggingContext: Events.StaticContext, configuration: configuration, fileAccessWhitelist: fileAccessWhiteList, testHooks: testHooks, buildEngineFingerprint: null, tempCleaner: new TestMoveDeleteCleaner(Path.Combine(Environment.GetEnvironmentVariable("TEMP"), "MoveDeletionTemp")))); }
private static Scheduler CreateInternal( PipExecutionContext context, PipGraph pipGraph, IPipQueue queue, EngineCache cache, IConfiguration configuration) { Contract.Requires(context != null); Contract.Requires(queue != null); Contract.Requires(cache != null); Contract.Requires(configuration != null); var fileContentTable = FileContentTable.CreateNew(); var fileAccessWhiteList = new FileAccessWhitelist(context); var testHooks = new SchedulerTestHooks(); return(new Scheduler( pipGraph, queue, context, fileContentTable, cache: cache, loggingContext: Events.StaticContext, configuration: configuration, fileAccessWhitelist: fileAccessWhiteList, testHooks: testHooks, buildEngineFingerprint: null)); }
public void WeightTestInDispatcher() { Configuration.Schedule.MaxProcesses = 4; var waitFile = ScheduleWaitingForFilePips(numberOfPips: 2, weight: 2); bool correctSlotsAndPips = false; var testHook = new SchedulerTestHooks() { GenerateSyntheticMachinePerfInfo = (loggingContext, scheduler) => { if (scheduler.MaxExternalProcessesRan == 2) { if (scheduler.PipQueue.GetNumAcquiredSlotsByKind(DispatcherKind.CPU) == 4 && scheduler.PipQueue.GetNumRunningPipsByKind(DispatcherKind.CPU) == 2) { correctSlotsAndPips = true; } // Ensure that the ongoing processes will now finish WriteSourceFile(waitFile); } return(default(PerformanceCollector.MachinePerfInfo)); } }; var schedulerResult = RunScheduler(testHooks: testHook, updateStatusTimerEnabled: true); schedulerResult.AssertSuccess(); AssertTrue(correctSlotsAndPips, "The number of running pips and slots is not correct."); }
/// <summary> /// Runs the scheduler using the instance member PipGraph and Configuration objects. This will also carry over /// any state from any previous run such as the cache /// </summary> public ScheduleRunResult RunScheduler(SchedulerTestHooks testHooks = null, SchedulerState schedulerState = null, RootFilter filter = null, TempCleaner tempCleaner = null) { if (m_graphWasModified || m_lastGraph == null) { m_lastGraph = PipGraphBuilder.Build(); XAssert.IsNotNull(m_lastGraph, "Failed to build pip graph"); } m_graphWasModified = false; return(RunSchedulerSpecific(m_lastGraph, testHooks, schedulerState, filter, tempCleaner)); }
public TestScheduler( PipGraph graph, TestPipQueue pipQueue, PipExecutionContext context, FileContentTable fileContentTable, EngineCache cache, IConfiguration configuration, FileAccessWhitelist fileAccessWhitelist, DirectoryMembershipFingerprinterRuleSet directoryMembershipFingerprinterRules = null, ITempCleaner tempCleaner = null, PipRuntimeTimeTable runningTimeTable = null, JournalState journalState = null, PerformanceCollector performanceCollector = null, string fingerprintSalt = null, PreserveOutputsInfo?previousInputsSalt = null, IEnumerable <Pip> successfulPips = null, IEnumerable <Pip> failedPips = null, LoggingContext loggingContext = null, IIpcProvider ipcProvider = null, DirectoryTranslator directoryTranslator = null, VmInitializer vmInitializer = null, SchedulerTestHooks testHooks = null) : base(graph, pipQueue, context, fileContentTable, cache, configuration, fileAccessWhitelist, loggingContext, null, directoryMembershipFingerprinterRules, tempCleaner, AsyncLazy <PipRuntimeTimeTable> .FromResult(runningTimeTable), performanceCollector, fingerprintSalt, previousInputsSalt, ipcProvider: ipcProvider, directoryTranslator: directoryTranslator, journalState: journalState, vmInitializer: vmInitializer, testHooks: testHooks) { m_testPipQueue = pipQueue; if (successfulPips != null) { foreach (var pip in successfulPips) { Contract.Assume(pip.PipId.IsValid, "Override results must be added after the pip has been added to the scheduler"); m_overridePipResults.Add(pip.PipId, PipResultStatus.Succeeded); } } if (failedPips != null) { foreach (var pip in failedPips) { Contract.Assume(pip.PipId.IsValid, "Override results must be added after the pip has been added to the scheduler"); m_overridePipResults.Add(pip.PipId, PipResultStatus.Failed); } } m_loggingContext = loggingContext; }
public void OutputDirectoryWithMembershipChange() { var outputDirectory = CreateUniqueObjPath("outputDir"); var outputFileA = CreateOutputFileArtifact(outputDirectory, "fileA"); var outputFileB = CreateOutputFileArtifact(outputDirectory, "fileB"); var outputFileC = CreateOutputFileArtifact(outputDirectory, "fileC"); var sourceFile = CreateSourceFile(); var builder = CreatePipBuilder( new[] { Operation.ReadFile(sourceFile), Operation.WriteFile(outputFileA, doNotInfer: true), Operation.WriteFile(outputFileB, doNotInfer: true), Operation.WriteFile(outputFileC, doNotInfer: true), }); builder.AddOutputDirectory(outputDirectory); var process = SchedulePipBuilder(builder); RunScheduler().AssertSuccess(); // Change membership of output directory by adding an extra file. File.WriteAllText(outputDirectory.Combine(Context.PathTable, "fileD").ToString(Context.PathTable), "foo"); RunScheduler() .AssertSuccess() .AssertScheduled(process.Process.PipId) .AssertCacheHit(process.Process.PipId); var testHooks = new SchedulerTestHooks(); var result = RunScheduler(testHooks: testHooks); if (Configuration.Schedule.IncrementalScheduling) { result.AssertNotScheduled(process.Process.PipId); // This assertion ensures that journal processing does not detect possibility of membership change. // If it detects so, then the jounral processing has to do extra enumeration to validate that possibility. XAssert.AreEqual( 0, testHooks.ScanningJournalResult.Stats.GetCounterValue( global::BuildXL.Storage.ChangeJournalService.Protocol.ReadJournalCounter.ExistentialChangesSuppressedAfterVerificationCount)); } else { result.AssertCacheHit(process.Process.PipId); } }
/// <summary> /// Runs the scheduler using the instance member PipGraph and Configuration objects. This will also carry over /// any state from any previous run such as the cache /// </summary> public ScheduleRunResult RunScheduler( SchedulerTestHooks testHooks = null, SchedulerState schedulerState = null, RootFilter filter = null, ITempCleaner tempCleaner = null, IEnumerable <(Pip before, Pip after)> constraintExecutionOrder = null,
/// <summary> /// Runs the scheduler allowing various options to be specifically set /// </summary> public ScheduleRunResult RunSchedulerSpecific( PipGraph graph, SchedulerTestHooks testHooks = null, SchedulerState schedulerState = null, RootFilter filter = null, TempCleaner tempCleaner = null) { var config = new CommandLineConfiguration(Configuration); // Populating the configuration may modify the configuration, so it should occur first. BuildXLEngine.PopulateLoggingAndLayoutConfiguration(config, Context.PathTable, bxlExeLocation: null, inTestMode: true); BuildXLEngine.PopulateAndValidateConfiguration(config, config, Context.PathTable, LoggingContext); FileAccessWhitelist whitelist = new FileAccessWhitelist(Context); whitelist.Initialize(config); IReadOnlyList <string> junctionRoots = Configuration.Engine.DirectoriesToTranslate?.Select(a => a.ToPath.ToString(Context.PathTable)).ToList(); var map = VolumeMap.TryCreateMapOfAllLocalVolumes(LoggingContext, junctionRoots); var optionalAccessor = TryGetJournalAccessor(map); // Although scan change journal is enabled, but if we cannot create an enabled journal accessor, then create a disabled one. m_journalState = map == null || !optionalAccessor.IsValid ? JournalState.DisabledJournal : JournalState.CreateEnabledJournal(map, optionalAccessor.Value); if (config.Schedule.IncrementalScheduling) { // Ensure that we can scan the journal when incremental scheduling is enabled. XAssert.IsTrue(m_journalState.IsEnabled, "Incremental scheduling requires that journal is enabled"); } // Seal the translator if not sealed DirectoryTranslator.Seal(); // ..................................................................................... // some dummy setup in order to get a PreserveOutputsSalt.txt file and an actual salt // ..................................................................................... string dummyCacheDir = Path.Combine(TemporaryDirectory, "Out", "Cache"); Directory.CreateDirectory(dummyCacheDir); // EngineSchedule tries to put the PreserveOutputsSalt.txt here ContentHash?previousOutputsSalt = EngineSchedule.PreparePreviousOutputsSalt(LoggingContext, Context.PathTable, config); Contract.Assert(previousOutputsSalt.HasValue); // ..................................................................................... testHooks = testHooks ?? new SchedulerTestHooks(); Contract.Assert(!(config.Engine.CleanTempDirectories && tempCleaner == null)); using (var queue = new PipQueue(config.Schedule)) using (var testQueue = new TestPipQueue(queue, LoggingContext, initiallyPaused: false)) using (var testScheduler = new TestScheduler( graph: graph, pipQueue: testQueue, context: Context, fileContentTable: FileContentTable, loggingContext: LoggingContext, cache: Cache, configuration: config, journalState: m_journalState, fileAccessWhitelist: whitelist, fingerprintSalt: Configuration.Cache.CacheSalt, directoryMembershipFingerprinterRules: new DirectoryMembershipFingerprinterRuleSet(Configuration, Context.StringTable), tempCleaner: tempCleaner, previousInputsSalt: previousOutputsSalt.Value, successfulPips: null, failedPips: null, ipcProvider: null, directoryTranslator: DirectoryTranslator, testHooks: testHooks)) { if (filter == null) { EngineSchedule.TryGetPipFilter(LoggingContext, Context, config, config, Expander.TryGetRootByMountName, out filter); } XAssert.IsTrue(testScheduler.InitForMaster(LoggingContext, filter, schedulerState), "Failed to initialized test scheduler"); testScheduler.Start(LoggingContext); bool success = testScheduler.WhenDone().GetAwaiter().GetResult(); testScheduler.SaveFileChangeTrackerAsync(LoggingContext).Wait(); return(new ScheduleRunResult { Graph = graph, Config = config, Success = success, PipResults = testScheduler.PipResults, PipExecutorCounters = testScheduler.PipExecutionCounters, PathSets = testScheduler.PathSets, ProcessPipCountersByFilter = testScheduler.ProcessPipCountersByFilter, ProcessPipCountersByTelemetryTag = testScheduler.ProcessPipCountersByTelemetryTag, SchedulerState = new SchedulerState(testScheduler) }); } }