Exemple #1
0
        private async Task UploadAndAssociateAsync(AssociationsStatus associateStatus, FileBlobDescriptor[] blobsForUpload)
        {
            int numMissing = associateStatus.Missing.Count();

            m_logger.Info("Uploading {0} missing files.", numMissing);

#if DEBUG
            // check that missing hashes reported in associateStatus match those provided in blobsForUpload
            var providedHashes        = new HashSet <BlobIdentifier>(blobsForUpload.Select(fb => fb.BlobIdentifier));
            var notFoundMissingHashes = associateStatus.Missing.Where(b => !providedHashes.Contains(b)).ToList();
            if (notFoundMissingHashes.Any())
            {
                throw new DaemonException("This many hashes not found in blobs to upload: " + notFoundMissingHashes.Count());
            }
#endif

            var startTime = DateTime.UtcNow;

            await m_dropClient.UploadAndAssociateAsync(
                DropName,
                blobsForUpload.ToList(),
                abortIfAlreadyExists : false,
                firstAssociationStatus : associateStatus,
                cancellationToken : Token).ConfigureAwait(false);

            Interlocked.Add(ref Stats.TotalUploadTimeMs, ElapsedMillis(startTime));
            Interlocked.Add(ref Stats.NumFilesUploaded, numMissing);
        }
 /// <inheritdoc />
 public Task UploadAndAssociateAsync(string dropName, List<FileBlobDescriptor> preComputedBlobIds, bool abortIfAlreadyExists, AssociationsStatus firstAssociationStatus, CancellationToken cancellationToken)
 {
     return RetryAsync(
         nameof(IDropServiceClient.UploadAndAssociateAsync),
         (client, ct) => client.UploadAndAssociateAsync(dropName, preComputedBlobIds, abortIfAlreadyExists, firstAssociationStatus, ct),
         cancellationToken);
 }
 Task IDropServiceClient.UploadAndAssociateAsync(string dropName, List <FileBlobDescriptor> preComputedBlobIds, bool abortIfAlreadyExists, AssociationsStatus firstAssociationStatus, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
Exemple #4
0
        /// <summary>
        ///     Sets completion results for <see cref="AddFileItem"/>s that were successfully associated
        ///     (as indicated by <paramref name="associateStatus"/>), and returns <see cref="AddFileItem"/>s
        ///     for those that are missing (<see cref="AssociationsStatus.Missing"/>).
        /// </summary>
        private static async Task <IReadOnlyList <AddFileItem> > SetResultForAssociatedNonMissingItemsAsync(AddFileItem[] batch, AssociationsStatus associateStatus, bool chunkDedup, CancellationToken cancellationToken)
        {
            var missingItems   = new List <AddFileItem>();
            var missingBlobIds = new HashSet <BlobIdentifier>(associateStatus.Missing);

            foreach (AddFileItem item in batch)
            {
                var itemFileBlobDescriptor = await item.FileBlobDescriptorForAssociateAsync(chunkDedup, cancellationToken);

                if (!missingBlobIds.Contains(itemFileBlobDescriptor.BlobIdentifier))
                {
                    item.TaskSource.SetResult(AddFileResult.Associated);
                }
                else
                {
                    missingItems.Add(item);
                }
            }

            return(missingItems);
        }
Exemple #5
0
        /// <summary>
        ///     Implements 'drop addfile' by first calling <see cref="IDropServiceClient.AssociateAsync"/>,
        ///     and then <see cref="IDropServiceClient.UploadAndAssociateAsync"/>.
        /// </summary>
        /// <remarks>
        ///     This method is called concurrently.
        /// </remarks>
        private async Task ProcessAddFilesAsync(AddFileItem[] batch)
        {
            Interlocked.Exchange(ref m_lastTimeProcessAddFileRanInTicks, DateTime.UtcNow.Ticks);

            int batchLength = batch.Length;

            if (batchLength == 0)
            {
                return;
            }

            Interlocked.Increment(ref Stats.NumBatches);
            if (batchLength == m_config.BatchSize)
            {
                Interlocked.Increment(ref Stats.NumCompleteBatches);
            }
            else
            {
                Interlocked.Increment(ref Stats.NumIncompleteBatches);
            }


            m_logger.Info("Processing a batch of {0} drop files.", batchLength);
            try
            {
                // compute blobs for associate
                var startTime = DateTime.UtcNow;
                FileBlobDescriptor[] blobsForAssociate = await Task.WhenAll(batch.Select(item => item.FileBlobDescriptorForAssociateAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForAssociateMs, ElapsedMillis(startTime));

                // run 'Associate' on all items from the batch; the result will indicate which files were associated and which need to be uploaded
                AssociationsStatus associateStatus = await AssociateAsync(blobsForAssociate);

                IReadOnlyList <AddFileItem> itemsLeftToUpload = await SetResultForAssociatedNonMissingItemsAsync(batch, associateStatus, m_config.EnableChunkDedup, Token);

                // compute blobs for upload
                startTime = DateTime.UtcNow;
                FileBlobDescriptor[] blobsForUpload = await Task.WhenAll(itemsLeftToUpload.Select(item => item.FileBlobDescriptorForUploadAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForUploadMs, ElapsedMillis(startTime));

                // run 'UploadAndAssociate' for the missing files.
                await UploadAndAssociateAsync(associateStatus, blobsForUpload);

                SetResultForUploadedMissingItems(itemsLeftToUpload);
                Interlocked.Add(ref Stats.TotalUploadSizeMb, blobsForUpload.Sum(b => b.FileSize ?? 0) >> 20);

                m_logger.Info("Done processing AddFile batch.");
            }
            catch (Exception e)
            {
                foreach (AddFileItem item in batch)
                {
                    if (!item.TaskSource.Task.IsCompleted)
                    {
                        item.TaskSource.SetException(e);
                    }
                }
            }
        }
Exemple #6
0
        /// <summary>
        ///     Implements 'drop addfile' by first calling <see cref="IDropServiceClient.AssociateAsync"/>,
        ///     and then <see cref="IDropServiceClient.UploadAndAssociateAsync"/>.
        /// </summary>
        /// <remarks>
        ///     This method is called concurrently.
        /// </remarks>
        private async Task ProcessAddFilesAsync(AddFileItem[] batch)
        {
            Interlocked.Exchange(ref m_lastTimeProcessAddFileRanInTicks, DateTime.UtcNow.Ticks);

            if (batch.Length == 0)
            {
                return;
            }

            Interlocked.Increment(ref Stats.NumBatches);
            if (batch.Length == m_config.BatchSize)
            {
                Interlocked.Increment(ref Stats.NumCompleteBatches);
            }
            else
            {
                Interlocked.Increment(ref Stats.NumIncompleteBatches);
            }

            FileBlobDescriptor[] blobsForAssociate = new FileBlobDescriptor[0];
            try
            {
                var dedupedBatch = SkipFilesWithTheSameDropPathAndContent(batch);
                var numSkipped   = batch.Length - dedupedBatch.Length;
                m_logger.Info("Processing a batch of {0} drop files after skipping {1} files.", dedupedBatch.Length, numSkipped);

                Task <HashSet <string> > registerFilesForBuildManifestTask = null;
                // Register files for Build Manifest
                if (m_dropDaemon.DropConfig.EnableBuildManifestCreation)
                {
                    BuildManifestEntry[] buildManifestEntries = dedupedBatch
                                                                .Where(dropItem => dropItem.BlobIdentifier != null)
                                                                .Select(dropItem => new BuildManifestEntry(dropItem.RelativeDropFilePath, dropItem.BlobIdentifier.ToContentHash(), dropItem.FullFilePath))
                                                                .ToArray();

                    registerFilesForBuildManifestTask = Task.Run(() => RegisterFilesForBuildManifestAsync(buildManifestEntries));
                }

                // compute blobs for associate
                var startTime = DateTime.UtcNow;
                blobsForAssociate = await Task.WhenAll(dedupedBatch.Select(item => item.FileBlobDescriptorForAssociateAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForAssociateMs, ElapsedMillis(startTime));

                // run 'Associate' on all items from the batch; the result will indicate which files were associated and which need to be uploaded
                AssociationsStatus associateStatus = await AssociateAsync(blobsForAssociate);

                IReadOnlyList <AddFileItem> itemsLeftToUpload = await SetResultForAssociatedNonMissingItemsAsync(dedupedBatch, associateStatus, m_config.EnableChunkDedup, Token);

                // compute blobs for upload
                startTime = DateTime.UtcNow;
                FileBlobDescriptor[] blobsForUpload = await Task.WhenAll(itemsLeftToUpload.Select(item => item.FileBlobDescriptorForUploadAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForUploadMs, ElapsedMillis(startTime));

                // run 'UploadAndAssociate' for the missing files.
                await UploadAndAssociateAsync(associateStatus, blobsForUpload);

                SetResultForUploadedMissingItems(itemsLeftToUpload);
                Interlocked.Add(ref Stats.TotalUploadSizeMb, blobsForUpload.Sum(b => b.FileSize ?? 0) >> 20);

                foreach (var file in dedupedBatch)
                {
                    RegisterFileForBuildManifestResult result = registerFilesForBuildManifestTask == null
                        ? RegisterFileForBuildManifestResult.Skipped
                        : (await registerFilesForBuildManifestTask).Contains(file.FullFilePath)
                            ? RegisterFileForBuildManifestResult.Failed
                            : RegisterFileForBuildManifestResult.Registered;
                    file.BuildManifestTaskSource.TrySetResult(result);
                }

                m_logger.Info("Done processing AddFile batch.");
            }
            catch (Exception e)
            {
                m_logger.Verbose($"Failed ProcessAddFilesAsync (batch size:{batch.Length}, blobsForAssociate size:{blobsForAssociate.Length}){Environment.NewLine}"
                                 + string.Join(
                                     Environment.NewLine,
                                     batch.Select(item => $"'{item.FullFilePath}', '{item.RelativeDropFilePath}', BlobId:'{item.BlobIdentifier?.ToString() ?? ""}', Task.IsCompleted:{item.DropResultTaskSource.Task.IsCompleted}")));

                foreach (AddFileItem item in batch)
                {
                    if (!item.DropResultTaskSource.Task.IsCompleted)
                    {
                        item.DropResultTaskSource.SetException(e);
                    }

                    // No exceptions are thrown by RegisterFilesForBuildManifestAsync
                    item.BuildManifestTaskSource.TrySetResult(RegisterFileForBuildManifestResult.Skipped);
                }
            }
        }
Exemple #7
0
        /// <summary>
        ///     Implements 'drop addfile' by first calling <see cref="IDropServiceClient.AssociateAsync"/>,
        ///     and then <see cref="IDropServiceClient.UploadAndAssociateAsync"/>.
        /// </summary>
        /// <remarks>
        ///     This method is called concurrently.
        /// </remarks>
        private async Task ProcessAddFilesAsync(AddFileItem[] batch)
        {
            Interlocked.Exchange(ref m_lastTimeProcessAddFileRanInTicks, DateTime.UtcNow.Ticks);

            int batchLength = batch.Length;

            if (batchLength == 0)
            {
                return;
            }

            Interlocked.Increment(ref Stats.NumBatches);
            if (batchLength == m_config.BatchSize)
            {
                Interlocked.Increment(ref Stats.NumCompleteBatches);
            }
            else
            {
                Interlocked.Increment(ref Stats.NumIncompleteBatches);
            }


            m_logger.Info("Processing a batch of {0} drop files.", batchLength);
            FileBlobDescriptor[] blobsForAssociate = new FileBlobDescriptor[0];
            try
            {
                var dedupedBatch = SkipFilesWithTheSameDropPathAndContent(batch);

                // compute blobs for associate
                var startTime = DateTime.UtcNow;
                blobsForAssociate = await Task.WhenAll(dedupedBatch.Select(item => item.FileBlobDescriptorForAssociateAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForAssociateMs, ElapsedMillis(startTime));

                // run 'Associate' on all items from the batch; the result will indicate which files were associated and which need to be uploaded
                AssociationsStatus associateStatus = await AssociateAsync(blobsForAssociate);

                IReadOnlyList <AddFileItem> itemsLeftToUpload = await SetResultForAssociatedNonMissingItemsAsync(dedupedBatch, associateStatus, m_config.EnableChunkDedup, Token);

                // compute blobs for upload
                startTime = DateTime.UtcNow;
                FileBlobDescriptor[] blobsForUpload = await Task.WhenAll(itemsLeftToUpload.Select(item => item.FileBlobDescriptorForUploadAsync(m_config.EnableChunkDedup, Token)));

                Interlocked.Add(ref Stats.TotalComputeFileBlobDescriptorForUploadMs, ElapsedMillis(startTime));

                // run 'UploadAndAssociate' for the missing files.
                await UploadAndAssociateAsync(associateStatus, blobsForUpload);

                SetResultForUploadedMissingItems(itemsLeftToUpload);
                Interlocked.Add(ref Stats.TotalUploadSizeMb, blobsForUpload.Sum(b => b.FileSize ?? 0) >> 20);

                m_logger.Info("Done processing AddFile batch.");
            }
            catch (Exception e)
            {
                m_logger.Verbose($"Failed ProcessAddFilesAsync (batch size:{batch.Length}, blobsForAssociate size:{blobsForAssociate.Length}){Environment.NewLine}"
                                 + string.Join(
                                     Environment.NewLine,
                                     batch.Select(item => $"'{item.FullFilePath}', '{item.RelativeDropFilePath}', BlobId:'{item.BlobIdentifier?.ToString() ?? ""}', Task.IsCompleted:{item.TaskSource.Task.IsCompleted}")));

                foreach (AddFileItem item in batch)
                {
                    if (!item.TaskSource.Task.IsCompleted)
                    {
                        item.TaskSource.SetException(e);
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        ///     Sets completion results for <see cref="AddFileItem"/>s that were successfully associated
        ///     (as indicated by <paramref name="associateStatus"/>), and returns <see cref="AddFileItem"/>s
        ///     for those that are missing (<see cref="AssociationsStatus.Missing"/>).
        /// </summary>
        private async Task <IReadOnlyList <AddFileItem> > SetResultForAssociatedNonMissingItemsAsync(AddFileItem[] batch, AssociationsStatus associateStatus, bool chunkDedup, CancellationToken cancellationToken)
        {
            var  missingItems               = new List <AddFileItem>();
            var  missingBlobIds             = new HashSet <BlobIdentifier>(associateStatus.Missing);
            long totalSizeOfAssociatedFiles = 0;

            foreach (AddFileItem item in batch)
            {
                var itemFileBlobDescriptor = await item.FileBlobDescriptorForAssociateAsync(chunkDedup, cancellationToken);

                if (!missingBlobIds.Contains(itemFileBlobDescriptor.BlobIdentifier))
                {
                    item.DropResultTaskSource.SetResult(AddFileResult.Associated);
                    totalSizeOfAssociatedFiles += item.PrecomputedFileLength;
                }
                else
                {
                    missingItems.Add(item);
                }
            }

            Interlocked.Add(ref Stats.TotalAssociateSizeBytes, totalSizeOfAssociatedFiles);
            return(missingItems);
        }