Exemple #1
0
        public static void JobError(string jobName, string message, ProgressRecorder progressRecorder, List<TransferDetail> failedFiles, List<TransferDetail> skippedFiles)
        {
            log.WriteLine("Error for Job: " + jobName);
            log.WriteLine("Error: " + message);
            log.WriteLine("WebJobs will make 5 attempts to rerun and complete");
            log.WriteLine(progressRecorder.ToString());

            if(failedFiles.Count > 0)
            { 
                log.WriteLine("Detailed File Transfer Errors");
                foreach (TransferDetail td in failedFiles)
                {
                    log.WriteLine("Source File: " + td.Source);
                    log.WriteLine("Destination File: " + td.Destination);
                    log.WriteLine("Error Message: " + td.Error);
                }
            }

            if (skippedFiles.Count > 0)
            {
                log.WriteLine("Skipped File Details");
                foreach (TransferDetail td in skippedFiles)
                {
                    log.WriteLine("Source File: " + td.Source);
                    log.WriteLine("Destination File: " + td.Destination);
                    log.WriteLine("Error Message: " + td.Error);
                }
            }
        }
        private static void CopyContainer(CloudBlobDirectory sourceDirectory, CloudBlobDirectory destDirectory)
        {
            // This function copies an entire Storage container using the data movement library.
            // See https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.storage.datamovement.copydirectoryoptions?view=azure-dotnet for the API
            // and https://docs.microsoft.com/en-us/azure/storage/common/storage-use-data-movement-library for a general overview.

            ProgressRecorder recorder  = new ProgressRecorder();
            Stopwatch        stopWatch = Stopwatch.StartNew();

            CopyDirectoryOptions copyDirectoryOptions = new CopyDirectoryOptions
            {
                // Needs to be true to copy the contents of the directory / container.  If this is false the contents will
                // not be copied.
                Recursive = true
            };
            // Copy all files under root folder
            DirectoryTransferContext context = new DirectoryTransferContext
            {
                ProgressHandler = recorder
            };

            TransferStatus copyStatus = TransferManager.CopyDirectoryAsync(sourceDirectory, destDirectory, CopyMethod.ServiceSideAsyncCopy, copyDirectoryOptions, context).Result;

            stopWatch.Stop();
            // Get the elapsed time as a TimeSpan value.
            TimeSpan ts = stopWatch.Elapsed;

            // Format and display the TimeSpan value.
            string elapsedTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                               ts.Hours, ts.Minutes, ts.Seconds,
                                               ts.Milliseconds / 10);

            Console.WriteLine($"Elapsed:{elapsedTime} T File transferred: {copyStatus.NumberOfFilesTransferred} total bytes:{copyStatus.BytesTransferred}, failed: {copyStatus.NumberOfFilesFailed}, skipped:{copyStatus.NumberOfFilesSkipped}");
        }
Exemple #3
0
        /// <summary>
        /// Download data from Azure storage.
        ///   1. Download a CloudBlob to a Stream instance
        ///   2. Download the same CloudBlob with step #1 to a different Stream instance
        ///   3. Download another CloudBlob to a different stream with content MD5 validation disabled
        ///   4. Show the overall progress of all transfers
        /// </summary>
        private static async Task BlobDownloadToStreamSample()
        {
            string sourceBlobName1 = "azure_blockblob.png";
            string sourceBlobName2 = "azure_blockblob2.png";

            // Create the source CloudBlob instances
            CloudBlob sourceBlob1 = await Util.GetCloudBlobAsync(ContainerName, sourceBlobName1, BlobType.BlockBlob);

            CloudBlob sourceBlob2 = await Util.GetCloudBlobAsync(ContainerName, sourceBlobName2, BlobType.BlockBlob);

            // Create a TransferContext shared by both transfers
            SingleTransferContext sharedTransferContext = new SingleTransferContext();

            // Record the overall progress
            ProgressRecorder recorder = new ProgressRecorder();

            sharedTransferContext.ProgressHandler = recorder;

            MemoryStream memoryStream1_1 = new MemoryStream();
            MemoryStream memoryStream1_2 = new MemoryStream();
            MemoryStream memoryStream2   = new MemoryStream();

            try
            {
                // Start the blob download
                Task task1 = TransferManager.DownloadAsync(sourceBlob1, memoryStream1_1, null /* options */, sharedTransferContext);

                // Start to download the same blob to another Stream
                // Please note, DataMovement Library will download blob once for each of downloads.
                // For example, if you start two downloads from the same source blob to two different Stream instance,
                // DataMovement Library will download the blob content twice.
                Task task2 = TransferManager.DownloadAsync(sourceBlob1, memoryStream1_2, null /* options */, sharedTransferContext);

                // Create a DownloadOptions to disable md5 check after data is downloaded. Otherwise, data movement
                // library will check the md5 checksum stored in the ContentMD5 property of the source CloudFile/CloudBlob
                // You can uncomment following codes, enable ContentMD5Validation and have a try.
                //   sourceBlob2.Properties.ContentMD5 = "WrongMD5";
                //   sourceBlob2.SetProperties();
                DownloadOptions options = new DownloadOptions();
                options.DisableContentMD5Validation = true;

                // Start the download
                Task task3 = TransferManager.DownloadAsync(sourceBlob2, memoryStream2, options, sharedTransferContext);

                // Wait for all transfers to finish
                await task1;
                await task2;
                await task3;

                // Print out the final transfer state
                Console.WriteLine("Final transfer state: {0}", recorder.ToString());
            }
            finally
            {
                memoryStream1_1.Dispose();
                memoryStream1_2.Dispose();
                memoryStream2.Dispose();
            }
        }
Exemple #4
0
        public virtual void before_each()
        {
            autoSubstitute = new AutoSubstitute();

            testExecutionRecorder = autoSubstitute.Resolve <ITestExecutionRecorder>();

            recorder = autoSubstitute.Resolve <ProgressRecorder>();
        }
Exemple #5
0
        public static async Task JobCompleteAsync(string jobName, ProgressRecorder progressRecorder, List<TransferDetail> skippedFiles)
        {
            await log.WriteLineAsync("Job Complete: " + jobName);
            await log.WriteLineAsync(progressRecorder.ToString());

            if (skippedFiles.Count > 0)
            {
                log.WriteLine("Skipped File Details");
                foreach (TransferDetail td in skippedFiles)
                {
                    await log.WriteLineAsync("Source File: " + td.Source);
                    await log.WriteLineAsync("Destination File: " + td.Destination);
                    await log.WriteLineAsync("Error Message: " + td.Error);
                }
            }
        }
        public async Task UploadFileToBlobAsync(string sourceFilePath, BlobOptions options)
        {
            Validate.BlobContainerName(options.ContainerName, "containerName");
            Validate.BlobName(options.BlobName, "blobName");

            var destinationBlob = DataManagerUtility.GetCloudBlob(options);
            TransferManager.Configurations.ParallelOperations = 64;

            var context = new TransferContext
            {
                OverwriteCallback = (path, destinationPath) => options.OverwriteDestination
            };

            ProgressRecorder = new ProgressRecorder();
            context.ProgressHandler = ProgressRecorder;

            await TransferManager.UploadAsync(sourceFilePath, destinationBlob, null, context, CancellationToken.None);
        }
Exemple #7
0
        /// <summary>
        /// Copy data between Azure storage.
        ///   1. Copy a CloudBlobDirectory
        ///   2. Cancel the transfer before it finishes with a CancellationToken
        ///   3. Store the transfer checkpoint into a file after transfer being cancelled
        ///   4. Reload checkpoint from the file
        ///   4. Resume the transfer with the loaded checkpoint
        /// </summary>
        private static async Task BlobDirectoryCopySample()
        {
            CloudBlobDirectory sourceBlobDir = await Util.GetCloudBlobDirectoryAsync(ContainerName, "blobdir");

            CloudBlobDirectory destBlobDir = await Util.GetCloudBlobDirectoryAsync(ContainerName, "blobdir2");

            // When source is CloudBlobDirectory:
            //   1. If recursive is set to true, data movement library matches the source blob name against SearchPattern as prefix.
            //   2. Otherwise, data movement library matches the blob with the exact name specified by SearchPattern.
            //
            // You can also replace the source directory with a CloudFileDirectory instance to copy data from Azure File Storage. If so:
            //   1. If recursive is set to true, SearchPattern is not supported. Data movement library simply transfer all azure files
            //      under the source CloudFileDirectory and its sub-directories.
            //   2. Otherwise, data movement library matches the azure file with the exact name specified by SearchPattern.
            //
            // In the following case, data movement library will copy all blobs with the prefix "azure" in source blob directory.
            CopyDirectoryOptions options = new CopyDirectoryOptions()
            {
                SearchPattern = "azure",
                Recursive     = true,
            };

            DirectoryTransferContext context = new DirectoryTransferContext();

            context.FileTransferred += FileTransferredCallback;
            context.FileFailed      += FileFailedCallback;
            context.FileSkipped     += FileSkippedCallback;

            // Create CancellationTokenSource used to cancel the transfer
            CancellationTokenSource cancellationSource = new CancellationTokenSource();

            TransferCheckpoint checkpoint    = null;
            TransferStatus     trasferStatus = null;

            try
            {
                Task <TransferStatus> task = TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, false /* isServiceCopy */, options, context, cancellationSource.Token);

                // Sleep for 1 seconds and cancel the transfer.
                // It may fail to cancel the transfer if transfer is done in 1 second. If so, no file will be copied after resume.
                Thread.Sleep(1000);
                Console.WriteLine("Cancel the transfer.");
                cancellationSource.Cancel();

                trasferStatus = await task;
            }
            catch (Exception e)
            {
                Console.WriteLine("The transfer is cancelled: {0}", e.Message);
            }

            // Store the transfer checkpoint
            checkpoint = context.LastCheckpoint;

            // Serialize the checkpoint into a file
#if DOTNET5_4
            var formatter = new DataContractSerializer(typeof(TransferCheckpoint));
#else
            IFormatter formatter = new BinaryFormatter();
#endif

            string tempFileName = Guid.NewGuid().ToString();
            using (var stream = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                formatter.Serialize(stream, checkpoint);
            }

            // Deserialize the checkpoint from the file
            using (var stream = new FileStream(tempFileName, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                checkpoint = formatter.Deserialize(stream) as TransferCheckpoint;
            }

            File.Delete(tempFileName);

            // Create a new TransferContext with the store checkpoint
            DirectoryTransferContext resumeContext = new DirectoryTransferContext(checkpoint);
            resumeContext.FileTransferred += FileTransferredCallback;
            resumeContext.FileFailed      += FileFailedCallback;
            resumeContext.FileSkipped     += FileSkippedCallback;

            // Record the overall progress
            ProgressRecorder recorder = new ProgressRecorder();
            resumeContext.ProgressHandler = recorder;

            // Resume transfer from the stored checkpoint
            Console.WriteLine("Resume the cancelled transfer.");
            trasferStatus = await TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, false /* isServiceCopy */, options, resumeContext);

            // Print out the final transfer state
            Console.WriteLine("Final transfer state: {0}", TransferStatusToString(trasferStatus));
        }
Exemple #8
0
        /// <summary>
        /// Download data from Azure storage.
        ///   1. Download a CloudBlob to an exsiting local file
        ///   2. Query the user to overwrite the local file or not in the OverwriteCallback
        ///   3. Download another CloudBlob to local with content MD5 validation disabled
        ///   4. Show the overall progress of both transfers
        /// </summary>
        private static async Task BlobDownloadSample()
        {
            string sourceBlobName1      = "azure_blockblob.png";
            string sourceBlobName2      = "azure_blockblob2.png";
            string destinationFileName1 = "azure.png";
            string destinationFileName2 = "azure_new.png";

            // Create the source CloudBlob instances
            CloudBlob sourceBlob1 = await Util.GetCloudBlobAsync(ContainerName, sourceBlobName1, BlobType.BlockBlob);

            CloudBlob sourceBlob2 = await Util.GetCloudBlobAsync(ContainerName, sourceBlobName2, BlobType.BlockBlob);

            // Create a TransferContext shared by both transfers
            SingleTransferContext sharedTransferContext = new SingleTransferContext();

            // Show overwrite prompt in console when OverwriteCallback is triggered
            sharedTransferContext.ShouldOverwriteCallbackAsync = async(source, destination) =>
            {
                Console.WriteLine("{0} already exists. Do you want to overwrite it with {1}? (Y/N)", destination, source);

                while (true)
                {
                    ConsoleKeyInfo keyInfo = Console.ReadKey(true);
                    char           key     = keyInfo.KeyChar;

                    if (key == 'y' || key == 'Y')
                    {
                        Console.WriteLine("User choose to overwrite the destination.");
                        return(true);
                    }
                    else if (key == 'n' || key == 'N')
                    {
                        Console.WriteLine("User choose NOT to overwrite the destination.");
                        return(false);
                    }

                    Console.WriteLine("Please press 'y' or 'n'.");
                }
            };

            // Record the overall progress
            ProgressRecorder recorder = new ProgressRecorder();

            sharedTransferContext.ProgressHandler = recorder;

            // Start the blob download
            Task task1 = TransferManager.DownloadAsync(sourceBlob1, destinationFileName1, null /* options */, sharedTransferContext);

            // Create a DownloadOptions to disable md5 check after data is downloaded. Otherwise, data movement
            // library will check the md5 checksum stored in the ContentMD5 property of the source CloudFile/CloudBlob
            // You can uncomment following codes, enable ContentMD5Validation and have a try.
            //   sourceBlob2.Properties.ContentMD5 = "WrongMD5";
            //   sourceBlob2.SetProperties();
            DownloadOptions options = new DownloadOptions();

            options.DisableContentMD5Validation = true;

            // Start the download
            Task task2 = TransferManager.DownloadAsync(sourceBlob2, destinationFileName2, options, sharedTransferContext);

            // Wait for both transfers to finish
            try
            {
                await task1;
            }
            catch (Exception e)
            {
                // Data movement library will throw a TransferException when user choose to not overwrite the existing destination
                Console.WriteLine(e.Message);
            }

            await task2;

            // Print out the final transfer state
            Console.WriteLine("Final transfer state: {0}", recorder.ToString());
        }
        public async static Task ProcessMessage([QueueTrigger("backupqueue")] CopyItem copyItem, TextWriter log, CancellationToken cancelToken)
        {
            // Copy TextWrite into Log Helper class
            Logger.log = log;

            // Log Job Start
            await Logger.JobStartAsync(copyItem.JobName);

            // This class accumulates transfer data during the copy
            ProgressRecorder progressRecorder = new ProgressRecorder();

            try
            {
                // OpContext to track PreCopy Retries on Azure Storage
                // DML has its own context object and retry
                _opContext = new OperationContext();
                _opContext.Retrying += StorageRequest_Retrying;

                // Define Blob Request Options
                _blobRequestOptions = new BlobRequestOptions
                {
                    // Defined Exponential Retry Policy above
                    RetryPolicy = _retryPolicy
                };

                // Set the number of parallel tasks in DML. 
                // This allows it to copy multiple items at once when copying a container or directory
                // The best (and default value) is Environment.ProcessorCount * 8
                int parallelTasks = Environment.ProcessorCount * 8;
                TransferManager.Configurations.ParallelOperations = parallelTasks;

                // Set the number of connections. 
                // This should match ParallelOperations so each DML copy task has its own connection to Azure Storage
                ServicePointManager.DefaultConnectionLimit = parallelTasks;

                // Short circuit additional request round trips. We are not chunking and
                // uploading large amounts of data where we'd send 100's so set to false
                ServicePointManager.Expect100Continue = false;

                // User Agent for tracing
                TransferManager.Configurations.UserAgentPrefix = "AzureDmlBackup";

                // CancellationTokenSource used to cancel the transfer
                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

                // Open connections to both storage accounts
                CloudStorageAccount sourceAccount = GetAccount(copyItem.SourceAccountToken);
                CloudStorageAccount destinationAccount = GetAccount(copyItem.DestinationAccountToken);

                // Represents a checkpoint from which a transfer may be resumed and continued.
                // This is initalized as null first time then hydrated within CopyDirectoryAsync().
                // However if this job is being resumed from a previous failure this function will hydrate
                // from a serialized checkpoint saved to blob storage.
                TransferCheckpoint transferCheckpoint = await GetTransferCheckpoint(copyItem.JobId);

                
                // Context object for the transfer, provides additional runtime information about its execution
                // If this is a resumed copy operation then pass the checkpoint to the TransferContext so it can resume the copy
                TransferContext transferContext = new TransferContext(transferCheckpoint)
                {
                    // Pipe transfer progress data to ProgressRecorder
                    // ProgressRecorder is used to log the results of the copy operation
                    ProgressHandler = progressRecorder,

                    // If the destination already exists this delegate is called. 
                    // Return true to overwrite or false to skip the file during the transfer
                    OverwriteCallback = (source, destination) =>
                    {
                        return OverwriteFile(source, destination, sourceAccount, destinationAccount, copyItem.IsIncremental);
                    }
                };

                // This event is used to log files skipped during the transfer
                transferContext.FileSkipped += TransferContext_FileSkipped;
                
                // This event is used to catch exceptions for files that fail during a transfer
                transferContext.FileFailed += TransferContext_FileFailed;

                // Set Options for copying the container such as search patterns, recursive, etc.
                CopyDirectoryOptions copyDirectoryOptions = new CopyDirectoryOptions
                {
                    IncludeSnapshots = true,
                    Recursive = true
                };

                // Get the root source and destination directories for the two containers to be copied
                CloudBlobDirectory sourceDirectory = await GetDirectoryAsync(sourceAccount, copyItem.SourceContainer, copyItem.SourceDirectory);
                CloudBlobDirectory destinationDirectory = await GetDirectoryAsync(destinationAccount, copyItem.DestinationContainer, copyItem.DestinationDirectory);


                // Copy the container
                await CopyDirectoryAsync(copyItem.JobId, sourceDirectory, destinationDirectory, copyDirectoryOptions, transferContext, transferCheckpoint, cancellationTokenSource);


                // Check if any files failed during transfer
                if (_failedFiles.Count > 0)
                {
                    // Save a Checkpoint so we can restart the transfer
                    transferCheckpoint = transferContext.LastCheckpoint;
                    SaveTransferCheckpoint(copyItem.JobId, transferCheckpoint);
                    // Throw an exception to fail the job so WebJobs will rerun it
                    throw new Exception("One or more errors occurred during the transfer.");
                }

                // Log job completion
                await Logger.JobCompleteAsync(copyItem.JobName, progressRecorder, _skippedFiles);

            }
            catch (Exception ex)
            {
                // Log Job Error
                await Logger.JobErrorAsync(copyItem.JobName, ex.Message, progressRecorder, _failedFiles, _skippedFiles);
                // Rethrow the error to fail the web job
                throw ex;
            }
        }