/// <summary>
        /// Update all chunks if they exist. Returns success only if all chunks are found and extended.
        /// </summary>
        private async Task <PinResult> TryPinChunksAsync(Context context, IEnumerable <VstsDedupIdentifier> dedupIdentifiers, CancellationToken cts)
        {
            if (!dedupIdentifiers.Any())
            {
                return(PinResult.Success);
            }

            // TODO: Support batched TryKeepUntilReferenceChunkAsync in Artifact. (bug 1428612)
            var tryReferenceBlock = new TransformBlock <VstsDedupIdentifier, PinResult>(
                async dedupId => await TryPinChunkAsync(context, dedupId, cts),
                new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = DefaultMaxParallelism
            });

            tryReferenceBlock.PostAll(dedupIdentifiers);
            var pinResults = await Task.WhenAll(Enumerable.Range(0, dedupIdentifiers.ToList().Count).Select(i => tryReferenceBlock.ReceiveAsync()));

            tryReferenceBlock.Complete();

            foreach (var result in pinResults)
            {
                if (!result.Succeeded)
                {
                    return(result); // An error updating one of the chunks occured. Fail fast.
                }
            }

            return(PinResult.Success);
        }
        private async Task <IEnumerable <Task <Indexed <PinResult> > > > UpdateDedupStoreAsync(
            Context context, IReadOnlyList <ContentHash> contentHashes, CancellationToken cts)
        {
            if (!contentHashes.Any())
            {
                return((new List <Task <Indexed <PinResult> > >()).AsEnumerable());
            }

            var dedupIdentifiers = contentHashes.Select(c => ToVstsBlobIdentifier(c.ToBlobIdentifier()).ToDedupIdentifier());

            var tryReferenceBlock = new TransformBlock <Indexed <VstsDedupIdentifier>, Indexed <PinResult> >(
                async i =>
            {
                PinResult pinResult;

                if (i.Item.AlgorithmId == Hashing.ChunkDedupIdentifier.ChunkAlgorithmId)
                {
                    pinResult = await TryPinChunkAsync(context, i.Item, cts);
                }
                else
                {
                    pinResult = await TryPinNodeAsync(context, i.Item, cts);
                }

                if (pinResult.Succeeded)
                {
                    BackingContentStoreExpiryCache.Instance.AddExpiry(new ContentHash(HashType.DedupNodeOrChunk, i.Item.Value), EndDateTime);
                }

                return(pinResult.WithIndex(i.Index));
            },
                new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = DefaultMaxParallelism
            });

            tryReferenceBlock.PostAll(dedupIdentifiers.AsIndexed());
            var results = await Task.WhenAll(Enumerable.Range(0, dedupIdentifiers.ToList().Count).Select(i => tryReferenceBlock.ReceiveAsync()));

            tryReferenceBlock.Complete();

            return(results.AsTasks().ToList());
        }
示例#3
0
        public async Task <IEnumerable <Task <Indexed <PlaceFileResult> > > > FetchThenPutBulkAsync(OperationContext context, IReadOnlyList <ContentHashWithPath> args, IContentSession contentSession)
        {
            var putFilesBlock =
                new TransformBlock <Indexed <ContentHashWithPath>, Indexed <PlaceFileResult> >(
                    async indexed =>
            {
                return(new Indexed <PlaceFileResult>(await CreateTempAndPutAsync(context, indexed.Item.Hash, contentSession), indexed.Index));
            },
                    new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = _maxParallelPlaces
            });

            putFilesBlock.PostAll(args.AsIndexed());

            var copyFilesLocally =
                await Task.WhenAll(
                    Enumerable.Range(0, args.Count).Select(i => putFilesBlock.ReceiveAsync(context.Token)));

            putFilesBlock.Complete();

            return(copyFilesLocally.AsTasks());
        }