コード例 #1
0
        /// <summary>
        /// Checks if the given path is an output under a shared opaque by verifying whether <see cref="WellKnownTimestamps.OutputInSharedOpaqueTimestamp"/> is the creation time of the file
        /// </summary>
        /// <remarks>
        /// If the given path is a directory, it is always considered part of a shared opaque
        /// </remarks>
        public static bool IsSharedOpaqueOutput(string expandedPath)
        {
            // On Windows: FOLLOW symlinks
            //   - directory symlinks are not fully supported (e.g., producing directory symlinks)
            //   - other reparse points are at play (e.g., junctions, Helium containers) which necessitate
            //     that we transparently follow those reparse points
            // On non-Windows: NO_FOLLOW symlinks
            //   - directory symlinks are supported
            //   - all symlinks are treated uniformly as files
            //   - if 'expandedPath' is a symlink pointing to a non-existent file, 'expandedPath' should hence
            //     still be treated as an existent file
            //   - similarly, if 'expandedPath' is a symlink pointing to a directory, it should still be treated as a file
            bool followSymlink = !OperatingSystemHelper.IsUnixOS;

            // If the file is not there (the check may be happening against a reported write that later got deleted)
            // then there is nothing to do
            var maybeResult = FileUtilities.TryProbePathExistence(expandedPath, followSymlink);

            if (maybeResult.Succeeded && maybeResult.Result == PathExistence.Nonexistent)
            {
                return(true);
            }

            // We don't really track directories as part of shared opaques.
            // So we consider them all potential members and return true.
            // It is important to track directory symlinks, because they are considered files for sake of shared opaque scrubbing.
            if (maybeResult.Succeeded && maybeResult.Result == PathExistence.ExistsAsDirectory)
            {
                return(true);
            }

            return(OperatingSystemHelper.IsMacOS
                ? XattrBased.IsSharedOpaqueOutput(expandedPath)
                : TimestampBased.IsSharedOpaqueOutput(expandedPath));
        }
コード例 #2
0
        /// <summary>
        /// Marks a given path as "shared opaque output"
        /// </summary>
        /// <remarks>
        /// Retries are needed because: (Win|Unix).SetPathAsSharedOpaqueOutput does something like
        ///   - check if file has write access rights
        ///   - if it doesn't, give it those rights
        ///   - mark the file as shared opaque output
        ///   - ...
        /// There is a race between checking and setting access rights, so it is possible that
        /// here we check its rights, we see that it has the correct rights, then someone else
        /// (e.g., the cache) revokes those rights, and so we fail to mark the file as shared opaque output.
        /// </remarks>
        /// <exception cref="BuildXLException">When unsuccessful</exception>
        public static void SetPathAsSharedOpaqueOutput(string expandedPath)
        {
            int attempt = 0;

            while (true)
            {
                attempt += 1;

                // wait a bit between attempts
                if (attempt > 1)
                {
                    System.Threading.Thread.Sleep(Multiply(SleepDurationBetweenMarkingAttempts, attempt - 1));
                }

                try
                {
                    if (OperatingSystemHelper.IsMacOS)
                    {
                        XattrBased.SetPathAsSharedOpaqueOutput(expandedPath);
                    }
                    else
                    {
                        TimestampBased.SetPathAsSharedOpaqueOutput(expandedPath);
                    }

                    return;
                }
                catch (BuildXLException e)
                {
                    if (attempt >= MaxNumberOfAttemptsForMarkingSharedOpaqueOutputs)
                    {
                        throw new BuildXLException($"Exceeded max number of attempts ({MaxNumberOfAttemptsForMarkingSharedOpaqueOutputs}) to mark '{expandedPath}' as shared opaque output", e);
                    }
                }
            }
        }