/// <summary>
        /// Constructor.
        /// </summary>
        private FingerprintStoreExecutionLogTarget(
            LoggingContext loggingContext,
            PipExecutionContext context,
            PipTable pipTable,
            PipContentFingerprinter pipContentFingerprinter,
            FingerprintStore fingerprintStore,
            FingerprintStore cacheLookupFingerprintStore,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            CounterCollection <FingerprintStoreCounters> counters,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance)
        {
            m_context                   = context;
            m_pipTable                  = pipTable;
            LoggingContext              = loggingContext;
            PipContentFingerprinter     = pipContentFingerprinter;
            ExecutionFingerprintStore   = fingerprintStore;
            CacheLookupFingerprintStore = cacheLookupFingerprintStore;
            // Cache lookup store is per-build state and doesn't need to be garbage collected (vs. execution fignerprint store which is persisted build-over-build)
            CacheLookupFingerprintStore?.GarbageCollectCancellationToken.Cancel();
            m_pipCacheMissesQueue = new ConcurrentQueue <PipCacheMissInfo>();
            Counters                       = counters;
            FingerprintStoreMode           = configuration.Logging.FingerprintStoreMode;
            m_runtimeCacheMissAnalyzerTask = RuntimeCacheMissAnalyzer.TryCreateAsync(
                this,
                loggingContext,
                context,
                configuration,
                cache,
                graph,
                runnablePipPerformance);

            Contract.Assume(FingerprintStoreMode == FingerprintStoreMode.ExecutionFingerprintsOnly || CacheLookupFingerprintStore != null, "Unless /storeFingerprints flag is set to /storeFingerprints:ExecutionFingerprintsOnly, the cache lookup FingerprintStore must exist.");
        }
Example #2
0
 public FingerprintTextAnalyzer(AnalysisInput input)
     : base(input)
 {
     m_completedPips        = new HashSet <PipId>();
     m_contentFingerprinter = null;
     m_pathExpander         = input.CachedGraph.MountPathExpander;
 }
        /// <summary>
        /// Compute fingerprint for process pip.
        /// </summary>
        public static ContentFingerprint ComputeFingerprint(this PipContentFingerprinter fingerprinter, Process process)
        {
            Contract.Requires(fingerprinter != null);
            Contract.Requires(process != null);

            return(fingerprinter.ComputeWeakFingerprint(process));
        }
Example #4
0
 /// <summary>
 /// Constructor.
 /// </summary>
 private FingerprintStoreExecutionLogTarget(
     LoggingContext loggingContext,
     PipExecutionContext context,
     PipTable pipTable,
     PipContentFingerprinter pipContentFingerprinter,
     FingerprintStore fingerprintStore,
     IConfiguration configuration,
     EngineCache cache,
     IReadonlyDirectedGraph graph,
     IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance)
 {
     m_context  = context;
     m_pipTable = pipTable;
     PipContentFingerprinter        = pipContentFingerprinter;
     FingerprintStore               = fingerprintStore;
     m_pipCacheMissesQueue          = new ConcurrentQueue <PipCacheMissInfo>();
     m_runtimeCacheMissAnalyzerTask = RuntimeCacheMissAnalyzer.TryCreateAsync(
         this,
         loggingContext,
         context,
         configuration,
         cache,
         graph,
         runnablePipPerformance);
 }
Example #5
0
            public PipQueueTestExecutionEnvironment(BuildXLContext context, IConfiguration configuration, PipTable pipTable, string tempDirectory, ISandboxConnection SandboxConnection = null)
            {
                Contract.Requires(context != null);
                Contract.Requires(configuration != null);

                Context              = context;
                LoggingContext       = CreateLoggingContextForTest();
                Configuration        = configuration;
                FileContentTable     = FileContentTable.CreateNew();
                ContentFingerprinter = new PipContentFingerprinter(
                    context.PathTable,
                    artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                    ExtraFingerprintSalts.Default(),
                    pathExpander: PathExpander);
                PipTable            = pipTable;
                PipFragmentRenderer = this.CreatePipFragmentRenderer();
                IpcProvider         = IpcFactory.GetProvider();
                var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

                Cache = InMemoryCacheFactory.Create();
                LocalDiskContentStore = new LocalDiskContentStore(LoggingContext, context.PathTable, FileContentTable, tracker);

                m_sandboxConnectionKext  = SandboxConnection;
                m_expectedWrittenContent = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_wellKnownFiles         = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_producers      = new ConcurrentDictionary <FileArtifact, Pip>();
                m_filesystemView = new TestPipGraphFilesystemView(Context.PathTable);
                var fileSystemView = new FileSystemView(Context.PathTable, m_filesystemView, LocalDiskContentStore);

                TempCleaner = new TestMoveDeleteCleaner(tempDirectory);

                State = new PipExecutionState(
                    configuration,
                    cache: new PipTwoPhaseCache(LoggingContext, Cache, context, PathExpander),
                    unsafeConfiguration: configuration.Sandbox.UnsafeSandboxConfiguration,
                    preserveOutputsSalt: ContentHashingUtilities.CreateRandom(),
                    fileAccessWhitelist: FileAccessWhitelist,
                    directoryMembershipFingerprinter: this,
                    pathExpander: PathExpander,
                    executionLog: null,
                    fileSystemView: fileSystemView,
                    fileContentManager: new FileContentManager(this, new NullOperationTracker()),
                    directoryMembershipFinterprinterRuleSet: null);

                m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

                ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
            }
Example #6
0
        /// <summary>
        /// Creates a <see cref="FingerprintStoreExecutionLogTarget"/>.
        /// </summary>
        /// <returns>
        /// If successful, a <see cref="FingerprintStoreExecutionLogTarget"/> that logs to
        /// a <see cref="Tracing.FingerprintStore"/> at the provided directory;
        /// otherwise, null.
        /// </returns>
        public static FingerprintStoreExecutionLogTarget Create(
            PipExecutionContext context,
            PipTable pipTable,
            PipContentFingerprinter pipContentFingerprinter,
            string fingerprintStoreDirectory,
            LoggingContext loggingContext,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance = null,
            FingerprintStoreTestHooks testHooks = null)
        {
            var maxEntryAge   = new TimeSpan(hours: 0, minutes: configuration.Logging.FingerprintStoreMaxEntryAgeMinutes, seconds: 0);
            var possibleStore = FingerprintStore.Open(
                fingerprintStoreDirectory,
                maxEntryAge: maxEntryAge,
                mode: configuration.Logging.FingerprintStoreMode,
                loggingContext: loggingContext,
                testHooks: testHooks);

            if (possibleStore.Succeeded)
            {
                return(new FingerprintStoreExecutionLogTarget(
                           loggingContext,
                           context,
                           pipTable,
                           pipContentFingerprinter,
                           possibleStore.Result,
                           configuration,
                           cache,
                           graph,
                           runnablePipPerformance));
            }
            else
            {
                Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleStore.Failure.DescribeIncludingInnerFailures());
            }

            return(null);
        }
Example #7
0
        public PipContentFingerprinter GetFingerprinter(uint workerId)
        {
            if (m_contentFingerprinters.Length <= workerId)
            {
                Array.Resize(ref m_contentFingerprinters, (int)workerId + 1);
            }

            if (m_contentFingerprinters[workerId] == null)
            {
                m_contentFingerprinters[workerId] = new PipContentFingerprinter(
                    CachedGraph.Context.PathTable,
                    artifact => LookupHashFunction(workerId, artifact),
                    Salts,
                    pathExpander: CachedGraph.MountPathExpander,
                    pipDataLookup: CachedGraph.PipGraph.QueryFileArtifactPipData)
                {
                    FingerprintTextEnabled = true,
                };
            }

            return(m_contentFingerprinters[workerId]);
        }
Example #8
0
        private (Process process, ContentFingerprint contentFingerprint, string fingerprintText) GetFingerprintInfo(PipReference lazyPip)
        {
            // Make sure the extra event data has set the value properly here.
            Contract.Requires(m_fingerprintSalts.HasValue, "m_fingerprintSalts is not set.");

            Process pip = (Process)lazyPip.HydratePip();
            string  fingerprintText;

            // This checks for missing content info for pips.
            foreach (var dependency in pip.Dependencies)
            {
                if (!m_fileContentMap.ContainsKey(dependency))
                {
                    return(pip, ContentFingerprint.Zero, "FINGERPRINT CONTAINS UNKNOWN DEPENDENCIES");
                }
            }

            if (m_contentFingerprinter == null)
            {
                m_contentFingerprinter = new PipContentFingerprinter(
                    CachedGraph.Context.PathTable,
                    LookupHash,
                    m_fingerprintSalts.Value,
                    pathExpander: m_pathExpander,
                    pipDataLookup: CachedGraph.PipGraph.QueryFileArtifactPipData)
                {
                    FingerprintTextEnabled = true,
                };
            }

            // TODO: Allow specifying fingerprinting version on the command line
            ContentFingerprint fingerprint = m_contentFingerprinter.ComputeWeakFingerprint(
                pip,
                out fingerprintText);

            return(pip, fingerprint, fingerprintText);
        }
        /// <summary>
        /// Creates a <see cref="FingerprintStoreExecutionLogTarget"/>.
        /// </summary>
        /// <returns>
        /// If successful, a <see cref="FingerprintStoreExecutionLogTarget"/> that logs to
        /// a <see cref="Tracing.FingerprintStore"/> at the provided directory;
        /// otherwise, null.
        /// </returns>
        public static FingerprintStoreExecutionLogTarget Create(
            PipExecutionContext context,
            PipTable pipTable,
            PipContentFingerprinter pipContentFingerprinter,
            LoggingContext loggingContext,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            CounterCollection <FingerprintStoreCounters> counters,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance = null,
            FingerprintStoreTestHooks testHooks = null)
        {
            var fingerprintStorePathString            = configuration.Layout.FingerprintStoreDirectory.ToString(context.PathTable);
            var cacheLookupFingerprintStorePathString = configuration.Logging.CacheLookupFingerprintStoreLogDirectory.ToString(context.PathTable);

            try
            {
                FileUtilities.CreateDirectoryWithRetry(fingerprintStorePathString);
            }
            catch (BuildXLException ex)
            {
                Logger.Log.FingerprintStoreUnableToCreateDirectory(loggingContext, fingerprintStorePathString, ex.Message);
                throw new BuildXLException("Unable to create fingerprint store directory: ", ex);
            }

            var maxEntryAge            = new TimeSpan(hours: 0, minutes: configuration.Logging.FingerprintStoreMaxEntryAgeMinutes, seconds: 0);
            var possibleExecutionStore = FingerprintStore.Open(
                fingerprintStorePathString,
                maxEntryAge: maxEntryAge,
                mode: configuration.Logging.FingerprintStoreMode,
                loggingContext: loggingContext,
                counters: counters,
                testHooks: testHooks);

            Possible <FingerprintStore> possibleCacheLookupStore = new Failure <string>("No attempt to create a cache lookup fingerprint store yet.");

            if (configuration.Logging.FingerprintStoreMode != FingerprintStoreMode.ExecutionFingerprintsOnly)
            {
                try
                {
                    FileUtilities.CreateDirectoryWithRetry(cacheLookupFingerprintStorePathString);
                }
                catch (BuildXLException ex)
                {
                    Logger.Log.FingerprintStoreUnableToCreateDirectory(loggingContext, fingerprintStorePathString, ex.Message);
                    throw new BuildXLException("Unable to create fingerprint store directory: ", ex);
                }

                possibleCacheLookupStore = FingerprintStore.Open(
                    cacheLookupFingerprintStorePathString,
                    maxEntryAge: maxEntryAge,
                    mode: configuration.Logging.FingerprintStoreMode,
                    loggingContext: loggingContext,
                    counters: counters,
                    testHooks: testHooks);
            }

            if (possibleExecutionStore.Succeeded &&
                (possibleCacheLookupStore.Succeeded || configuration.Logging.FingerprintStoreMode == FingerprintStoreMode.ExecutionFingerprintsOnly))
            {
                return(new FingerprintStoreExecutionLogTarget(
                           loggingContext,
                           context,
                           pipTable,
                           pipContentFingerprinter,
                           possibleExecutionStore.Result,
                           possibleCacheLookupStore.Succeeded ? possibleCacheLookupStore.Result : null,
                           configuration,
                           cache,
                           graph,
                           counters,
                           runnablePipPerformance));
            }
            else
            {
                if (!possibleExecutionStore.Succeeded)
                {
                    Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleExecutionStore.Failure.DescribeIncludingInnerFailures());
                }

                if (!possibleCacheLookupStore.Succeeded)
                {
                    Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleCacheLookupStore.Failure.DescribeIncludingInnerFailures());
                }
            }

            return(null);
        }
Example #10
0
        /// <summary>
        /// Creates an execution environment for a single pip. To run pips incrementally, the <paramref name="fileContentTable"/> and <paramref name="pipCache"/> should be specified.
        /// </summary>
        public DummyPipExecutionEnvironment(
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration config,
            FileContentTable fileContentTable = null,
            EngineCache pipCache = null,
            SemanticPathExpander semanticPathExpander           = null,
            PipContentFingerprinter.PipDataLookup pipDataLookup = null,
            FileAccessWhitelist fileAccessWhitelist             = null,
            bool allowUnspecifiedSealedDirectories = false,
            PipTable pipTable        = null,
            IIpcProvider ipcProvider = null,
            IKextConnection sandboxedKextConnection = null)
        {
            Contract.Requires(context != null);
            Contract.Requires(config != null);

            LoggingContext = loggingContext;
            Context        = context;

            // Ensure paths visible when debugging
            PathTable.DebugPathTable = Context.PathTable;
            Configuration            = config;
            PipTable             = pipTable;
            PathExpander         = semanticPathExpander ?? SemanticPathExpander.Default;
            ContentFingerprinter = new PipContentFingerprinter(
                Context.PathTable,
                artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                new ExtraFingerprintSalts(config, PipFingerprintingVersion.TwoPhaseV2, fingerprintSalt: null, searchPathToolsHash: null),
                pathExpander: PathExpander,
                pipDataLookup: pipDataLookup);
            PipFragmentRenderer = this.CreatePipFragmentRenderer();
            IpcProvider         = ipcProvider ?? IpcFactory.GetProvider();

            FileContentTable    = fileContentTable ?? FileContentTable.CreateNew();
            Cache               = pipCache;
            FileAccessWhitelist = fileAccessWhitelist;
            m_allowUnspecifiedSealedDirectories = allowUnspecifiedSealedDirectories;
            m_sandboxedKextConnection           = sandboxedKextConnection;

            if (Cache == null)
            {
                Cache = InMemoryCacheFactory.Create(context);
            }

            var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

            LocalDiskContentStore = new LocalDiskContentStore(loggingContext, context.PathTable, FileContentTable, tracker);
            PipGraphView          = new TestPipGraphFilesystemView(Context.PathTable);
            m_operationTracker    = new OperationTracker(loggingContext);

            var fileSystemView = new FileSystemView(Context.PathTable, PipGraphView, LocalDiskContentStore);

            var preserveOutputsSalt = UnsafeOptions.PreserveOutputsNotUsed;

            if (config.Sandbox.UnsafeSandboxConfiguration.PreserveOutputs != PreserveOutputsMode.Disabled)
            {
                preserveOutputsSalt = ContentHashingUtilities.HashString(Guid.NewGuid().ToString());
            }

            State = new PipExecutionState(
                config,
                cache: new PipTwoPhaseCache(loggingContext, Cache, context, PathExpander),
                fileAccessWhitelist: FileAccessWhitelist,
                directoryMembershipFingerprinter: this,
                pathExpander: PathExpander,
                executionLog: ExecutionLogRecorder,
                fileSystemView: fileSystemView,
                fileContentManager: GetFileContentManager(),
                directoryMembershipFinterprinterRuleSet: null,
                unsafeConfiguration: config.Sandbox.UnsafeSandboxConfiguration,
                preserveOutputsSalt: preserveOutputsSalt,
                serviceManager: new DummyServiceManager());

            m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

            ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
        }