/// <summary>
 /// Serialize metadata to writer
 /// </summary>
 public static void WritePipCacheDescriptor(BuildXLWriter writer, PipCacheDescriptorV2Metadata metadata)
 {
     if (metadata != null)
     {
         writer.Write(true);
         var blob = BondExtensions.Serialize(metadata);
         writer.WriteCompact(blob.Count);
         writer.Write(blob.Array, blob.Offset, blob.Count);
     }
     else
     {
         writer.Write(false);
     }
 }
Exemplo n.º 2
0
        /// <summary>
        /// Store the fingerprint store directory to the cache
        /// </summary>
        public static async Task <Possible <long> > TrySaveFingerprintStoreAsync(
            this EngineCache cache,
            LoggingContext loggingContext,
            AbsolutePath path,
            PathTable pathTable,
            string key,
            string environment)
        {
            var           fingerprint = ComputeFingerprint(pathTable, key, environment);
            var           pathStr     = path.ToString(pathTable);
            BoxRef <long> size        = 0;

            SemaphoreSlim concurrencyLimiter = new SemaphoreSlim(8);
            var           tasks = new List <Task <Possible <StringKeyedHash, Failure> > >();

            FileUtilities.EnumerateDirectoryEntries(pathStr, (name, attr) =>
            {
                var task = Task.Run(async() =>
                {
                    using (await concurrencyLimiter.AcquireAsync())
                    {
                        var filePath    = path.Combine(pathTable, name);
                        var storeResult = await cache.ArtifactContentCache.TryStoreAsync(
                            FileRealizationMode.Copy,
                            filePath.Expand(pathTable));

                        if (storeResult.Succeeded)
                        {
                            Interlocked.Add(ref size.Value, new FileInfo(filePath.ToString(pathTable)).Length);
                        }

                        var result = storeResult.Then(result => new StringKeyedHash()
                        {
                            Key         = path.ExpandRelative(pathTable, filePath),
                            ContentHash = result.ToBondContentHash()
                        });

                        Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Saving fingerprint store to cache: Success='{storeResult.Succeeded}', FilePath='{filePath}' Key='{result.Result.Key}' Hash='{result.Result.ContentHash.ToContentHash()}'"));
                        return(result);
                    }
                });

                tasks.Add(task);
            });

            var storedFiles = await Task.WhenAll(tasks);

            var failure = storedFiles.Where(p => !p.Succeeded).Select(p => p.Failure).FirstOrDefault();

            Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Saving fingerprint store to cache: Success='{failure == null}', FileCount={storedFiles.Length} Size={size.Value}"));
            if (failure != null)
            {
                return(failure);
            }

            PackageDownloadDescriptor descriptor = new PackageDownloadDescriptor()
            {
                TraceInfo    = loggingContext.Session.Environment,
                FriendlyName = nameof(FingerprintStore),
                Contents     = storedFiles.Select(p => p.Result).ToList()
            };

            // Publish contents before saving the descriptor to make sure content exist before the descriptor exist to avoid fingerprintstore opening errors
            var storeDescriptorBuffer = BondExtensions.Serialize(descriptor);
            var storeDescriptorHash   = ContentHashingUtilities.HashBytes(
                storeDescriptorBuffer.Array,
                storeDescriptorBuffer.Offset,
                storeDescriptorBuffer.Count);

            var associatedFileHashes = descriptor.Contents.Select(s => s.ContentHash.ToContentHash()).ToArray().ToReadOnlyArray().GetSubView(0);
            var cacheEntry           = new CacheEntry(storeDescriptorHash, null, associatedFileHashes);
            var publishResult        = await cache.TwoPhaseFingerprintStore.TryPublishTemporalCacheEntryAsync(loggingContext, fingerprint, cacheEntry);

            Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Publishing fingerprint store to cache: Fingerprint='{fingerprint}' Hash={storeDescriptorHash} Success='{publishResult.Succeeded}'"));

            var storeDescriptorResult = await cache.ArtifactContentCache.TryStoreContent(storeDescriptorHash, storeDescriptorBuffer);

            Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Saving fingerprint store descriptor to cache: Success='{storeDescriptorResult.Succeeded}'"));
            if (!storeDescriptorResult.Succeeded)
            {
                return(storeDescriptorResult.Failure);
            }

            return(size.Value);
        }