Example #1
0
        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));
        }
Example #3
0
        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.");
        }
Example #4
0
        /// <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));
        }
Example #5
0
        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;
        }
Example #6
0
        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,
Example #8
0
        /// <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)
                        });
                    }
        }