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}");
        }
Example #2
0
        private static async Task BlobDirectoryCopySample()
        {
            var sourceBlobDir = await Util.GetCloudBlobDirectoryAsync("sourcecontainer", "dir1");

            var destBlobDir = await Util.GetCloudBlobDirectoryAsync("targetcontainer", "dir2");

            var options = new CopyDirectoryOptions()
            {
                Recursive = true,
            };

            var context = new DirectoryTransferContext();

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

            TransferManager.Configurations.ParallelOperations = 50;
            Console.WriteLine("Transfer started");

            try
            {
                Task  task = TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, false, options, context);
                await task;
            }
            catch (Exception e)
            {
                Console.WriteLine("The transfer is cancelled: {0}", e.Message);
            }

            Console.WriteLine("The transfer is completed.");
        }
Example #3
0
        private async static Task CopyDirectoryAsync(string jobId, CloudBlobDirectory sourceDirectory, CloudBlobDirectory destinationDirectory, CopyDirectoryOptions copyDirectoryOptions, TransferContext transferContext, TransferCheckpoint transferCheckpoint, CancellationTokenSource cancellationTokenSource)
        {
            // Start the transfer
            try
            {
                await TransferManager.CopyDirectoryAsync(
                    sourceBlobDir : sourceDirectory,
                    destBlobDir : destinationDirectory,
                    isServiceCopy : false,
                    options : copyDirectoryOptions,
                    context : transferContext,
                    cancellationToken : cancellationTokenSource.Token);

                // Store the transfer checkpoint to record the completed copy operation
                transferCheckpoint = transferContext.LastCheckpoint;
            }
            catch (TransferException)
            {
                // Swallow all transfer exceptions here. Files skipped in the OverwriteCallback throw an exception here
                // even in an Incremental copy where the source is skipped because it and destination are identical
                // Instead all exceptions from transfers are handled in the FileFailed event handler.
            }
            catch (Exception ex)
            {
                // Fatal or other exceptions resulting in the transfer being cancelled will still appear here

                // Save a Checkpoint so we can restart the transfer
                transferCheckpoint = transferContext.LastCheckpoint;
                SaveTransferCheckpoint(jobId, transferCheckpoint);

                throw new Exception("Error in CopyDirectoryAsync(): " + ex.Message);
            }
        }
Example #4
0
        private async static Task CopyDirectoryAsync(CloudBlobDirectory sourceDirectory, CloudBlobDirectory destinationDirectory, CopyDirectoryOptions copyDirectoryOptions, TransferContext transferContext, TransferCheckpoint transferCheckpoint, CancellationTokenSource cancellationTokenSource)
        {
            // Start the transfer
            try
            {
                await TransferManager.CopyDirectoryAsync(
                    sourceBlobDir : sourceDirectory,
                    destBlobDir : destinationDirectory,
                    isServiceCopy : true,
                    options : copyDirectoryOptions,
                    context : transferContext,
                    cancellationToken : cancellationTokenSource.Token);

                // Store the transfer checkpoint.
                transferCheckpoint = transferContext.LastCheckpoint;
            }
            catch (TransferException te)
            {
                // Swallow Exceptions from skipped files in Overwrite Callback
                // Log any other Transfer Exceptions
                if (te.ErrorCode != TransferErrorCode.SubTransferFails)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("Transfer Error: " + te.Message);
                    sb.AppendLine("Transfer Error Code: " + te.ErrorCode);
                    await _log.WriteLineAsync(sb.ToString());
                }
            }
        }
Example #5
0
        public void TestFileShareSnapshotsCopyToBase()
        {
            int fileCount = 3;

            string        snapshotFile   = "snapshotFile";
            DMLibDataInfo sourceDataInfo = new DMLibDataInfo(string.Empty);

            sourceDataInfo.IsFileShareSnapshot = true;
            DMLibDataHelper.AddMultipleFiles(sourceDataInfo.RootNode, snapshotFile, fileCount, 1024);

            SourceAdaptor.Cleanup();
            SourceAdaptor.CreateIfNotExists();
            SourceAdaptor.GenerateData(sourceDataInfo);

            CloudFileDataAdaptor fileAdaptor = (SourceAdaptor as CloudFileDataAdaptor);

            CloudFileDirectory SourceObject = SourceAdaptor.GetTransferObject(sourceDataInfo.RootPath, sourceDataInfo.RootNode) as CloudFileDirectory;
            CloudFileDirectory DestObject   = fileAdaptor.fileHelper.FileClient.GetShareReference(fileAdaptor.ShareName).GetRootDirectoryReference();


            // transfer File and finished succssfully
            Task <TransferStatus> task = TransferManager.CopyDirectoryAsync(
                SourceObject,
                DestObject,
                DMLibTestContext.IsAsync,
                new CopyDirectoryOptions()
            {
                Recursive = true
            },
                new DirectoryTransferContext()
            {
                ShouldOverwriteCallbackAsync = TransferContext.ForceOverwrite
            });

            Test.Assert(task.Wait(15 * 60 * 100), "Tansfer finished in time.");
            Test.Assert(task.Result.NumberOfFilesFailed == 0, "No Failed File.");
            Test.Assert(task.Result.NumberOfFilesSkipped == 0, "No Skipped File.");
            Test.Assert(task.Result.NumberOfFilesTransferred == fileCount, string.Format("Transferred file :{0} == {1}", task.Result.NumberOfFilesTransferred, fileCount));

            // verify that Files in Share Snapshot is transferred
            IEnumerable <IListFileItem> sourceFiles = SourceObject.ListFilesAndDirectories(HelperConst.DefaultFileOptions);

            foreach (IListFileItem item in sourceFiles)
            {
                if (item is CloudFile)
                {
                    CloudFile srcFile  = item as CloudFile;
                    CloudFile destFile = DestObject.GetFileReference(srcFile.Name);
                    srcFile.FetchAttributes();
                    destFile.FetchAttributes();
                    Test.Assert(srcFile.Properties.ContentMD5 == destFile.Properties.ContentMD5, string.Format("File {0} MD5 :{1} == {2}", srcFile.Name, srcFile.Properties.ContentMD5, destFile.Properties.ContentMD5));
                }
            }
        }
        public async Task <List <BlobInfo> > CopyDirectory(
            IBlobContainer sourceContainerName,
            string sourceDirectoryPath,
            IBlobContainer destinationContainerName,
            string destinationDirectoryPath,
            IBlobStorageService.CopyDirectoryOptions?options = null)
        {
            _logger.LogInformation(
                "Copying directory from {0}/{1} to {2}/{3}",
                sourceContainerName,
                sourceDirectoryPath,
                destinationContainerName,
                destinationDirectoryPath
                );

            var sourceContainer = await GetCloudBlobContainer(sourceContainerName);

            var destinationContainer = await GetCloudBlobContainer(
                destinationContainerName,
                connectionString : options?.DestinationConnectionString
                );

            var sourceDirectory      = sourceContainer.GetDirectoryReference(sourceDirectoryPath);
            var destinationDirectory = destinationContainer.GetDirectoryReference(destinationDirectoryPath);

            var copyDirectoryOptions = new CopyDirectoryOptions
            {
                Recursive = true
            };

            var filesTransferred = new List <BlobInfo>();

            var context = new DirectoryTransferContext();

            context.FileTransferred              += (sender, args) => FileTransferredCallback(sender, args, filesTransferred);
            context.FileFailed                   += FileFailedCallback;
            context.FileSkipped                  += FileSkippedCallback;
            context.SetAttributesCallbackAsync   += options?.SetAttributesCallbackAsync;
            context.ShouldTransferCallbackAsync  += options?.ShouldTransferCallbackAsync;
            context.ShouldOverwriteCallbackAsync += options?.ShouldOverwriteCallbackAsync;

            await TransferManager.CopyDirectoryAsync(
                sourceDirectory,
                destinationDirectory,
                CopyMethod.ServiceSideAsyncCopy,
                copyDirectoryOptions,
                context
                );

            return(filesTransferred);
        }
        private Task <TransferStatus> CopyDirectory(dynamic sourceObject, dynamic destObject, TransferItem item)
        {
            CopyDirectoryOptions     copyDirectoryOptions = item.Options as CopyDirectoryOptions;
            DirectoryTransferContext transferContext      = item.TransferContext as DirectoryTransferContext;
            CancellationToken        cancellationToken    = item.CancellationToken;

            if (cancellationToken == null || cancellationToken == CancellationToken.None)
            {
                return(TransferManager.CopyDirectoryAsync(sourceObject, destObject, item.IsServiceCopy, copyDirectoryOptions, transferContext));
            }
            else
            {
                return(TransferManager.CopyDirectoryAsync(sourceObject, destObject, item.IsServiceCopy, copyDirectoryOptions, transferContext, cancellationToken));
            }
        }
Example #8
0
        public void TestFileShareSnapshotsDest()
        {
            string failError1 = "Failed to validate destination";
            string failError2 = "Cannot perform this operation on a share representing a snapshot.";

            //Prepare Data
            string        snapshotFile   = "snapshotFile";
            DMLibDataInfo sourceDataInfo = new DMLibDataInfo(string.Empty);

            DMLibDataHelper.AddOneFile(sourceDataInfo.RootNode, snapshotFile, 1024);
            SourceAdaptor.GenerateData(sourceDataInfo);

            DMLibDataInfo DestDataInfo = new DMLibDataInfo(string.Empty);

            DestDataInfo.IsFileShareSnapshot = true;
            DestAdaptor.GenerateData(DestDataInfo);

            CloudBlobDirectory SourceObject = SourceAdaptor.GetTransferObject(sourceDataInfo.RootPath, sourceDataInfo.RootNode) as CloudBlobDirectory;
            CloudFileDirectory DestObject   = DestAdaptor.GetTransferObject(DestDataInfo.RootPath, DestDataInfo.RootNode) as CloudFileDirectory;

            // transfer File and failed with expected Error
            Task <TransferStatus> task = TransferManager.CopyDirectoryAsync(
                SourceObject,
                DestObject,
                DMLibTestContext.IsAsync,
                new CopyDirectoryOptions()
            {
                Recursive = true
            },
                new DirectoryTransferContext()
            {
                ShouldOverwriteCallbackAsync = TransferContext.ForceOverwrite
            });

            try
            {
                task.Wait(15 * 60 * 100);
            }
            catch (Exception e)
            {
                Test.Assert(e.InnerException.Message.Contains(failError1), "Tansfer Exception should contain:" + failError1);
                Test.Assert(e.InnerException.InnerException.Message.Contains(failError2), "Tansfer Exception should contain:" + failError2);
            }
        }
Example #9
0
        /// <summary>
        /// Moves a folder with its contents to the path given
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task <BlobDto> MoveFolder(BlobDto folder, string path)
        {
            var container = await GetContainer();

            if (path[path.Length - 1] != '/')
            {
                path = path + "/";
            }

            string newPath = $"{path}{folder.Name}";

            var sourceBlobDir = container.GetDirectoryReference(folder.Path);
            var destBlobDir   = container.GetDirectoryReference(newPath);

            TransferManager.Configurations.ParallelOperations = 64;
            // Setup the transfer context and track the upoload progress
            DirectoryTransferContext context = new DirectoryTransferContext
            {
                ProgressHandler = new Progress <TransferStatus>((progress) =>
                {
                    Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred);
                })
            };

            var copyDirOptions = new CopyDirectoryOptions
            {
                Recursive        = true,
                IncludeSnapshots = true
            };

            await TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, true, copyDirOptions, context);

            await DeleteFile(folder.Path);

            folder.Path         = newPath;
            folder.StoragePath  = destBlobDir.Uri.ToString();
            folder.DateModified = DateTime.UtcNow;

            return(folder);
        }
Example #10
0
        public async Task RunAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            var copyDirectoryOptions = new CopyDirectoryOptions
            {
                Recursive = true
            };

            var directoryTransferContext = new DirectoryTransferContext
            {
                //ProgressHandler = new Progress<TransferStatus>(progress => Log.Trace(() => $"Progress: transferred: {progress.NumberOfFilesTransferred}, failed: {progress.NumberOfFilesFailed}, skipped: {progress.NumberOfFilesSkipped}, bytes transferred: {progress.BytesTransferred}"))
            };

            directoryTransferContext.FileTransferred += (sender, args) => Log.Trace(() => $"Transferred {(args.Source as CloudFile)?.Name} -> {(args.Destination as CloudFile)?.Name}");
            directoryTransferContext.FileSkipped     += (sender, args) => Log.Trace(() => $"Skipped {(args.Source as CloudFile)?.Name} -> {(args.Destination as CloudFile)?.Name}");
            directoryTransferContext.FileFailed      += (sender, args) => Log.Error(() => $"Failed {(args.Source as CloudFile)?.Name} -> {(args.Destination as CloudFile)?.Name}");

            Log.Info(() => $"Starting server side copy from {this.sourceDirectory.Uri} to {this.targetDirectory.Uri}");

            var status = await TransferManager.CopyDirectoryAsync(sourceDirectory, targetDirectory, true, copyDirectoryOptions, directoryTransferContext, cancellationToken);

            Log.Info(() => $"Finished server side copy, transferred: {status.NumberOfFilesTransferred}, failed: {status.NumberOfFilesFailed}, skipped: {status.NumberOfFilesSkipped}, bytes transferred: {status.BytesTransferred}");
        }
Example #11
0
        static void Main(string[] args)
        {
            ServicePointManager.DefaultConnectionLimit = Environment.ProcessorCount * 8;
            ServicePointManager.Expect100Continue      = false;

            var storageAccount      = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("FileStorageConnectionString"));
            var cloudFileClient     = storageAccount.CreateCloudFileClient();
            var fileShare           = cloudFileClient.GetShareReference("myshare");
            var rootDirectory       = fileShare.GetRootDirectoryReference();
            var directory           = rootDirectory.GetDirectoryReference("sourcedir");
            var cloudStorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("BlobStorageConnectionString"));
            var cloudBlobClient     = cloudStorageAccount.CreateCloudBlobClient();
            var containerReference  = cloudBlobClient.GetContainerReference("myblobcontainer");
            var cloudBlobDirectory  = containerReference.GetDirectoryReference("targetdir");

            var stopwatch = Stopwatch.StartNew();

            TransferManager.CopyDirectoryAsync(directory, cloudBlobDirectory, true, new CopyDirectoryOptions {
                Recursive = true
            }, new DirectoryTransferContext()).Wait();
            stopwatch.Stop();
            Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Copy files took {stopwatch.ElapsedMilliseconds}ms");
            Console.ReadLine();
        }
Example #12
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));
        }
        /// <summary>
        /// Copies the content of one directory to another on the server side.
        /// Avoids having to download all items and reupload them to somewhere else on the client side.
        /// </summary>
        /// <param name="sourceDirectoryPath">The path to the directory containing the files to be transferred</param>
        /// <param name="destinationDirectoryPath">The path to the destination directory </param>
        /// <param name="transferEvent">Action callback for tracking progress of each file when transferring.</param>
        /// <returns>Result from the  server side transfer.</returns>
        public async Task <ITransferResult> CopyDirectory(string sourceDirectoryPath, string destinationDirectoryPath, Action <Core.TransferEventType, ITransferEvent> transferEvent = null)
        {
            var sourceContainerName      = GetContainerFromPath(sourceDirectoryPath);
            var destinationContainerName = GetContainerFromPath(destinationDirectoryPath);

            // Ensure destination folder exists if we've configured to create automatically.
            if (CreateFolderIfNotExists)
            {
                GetContainer(destinationContainerName, true);
            }

            var directoryTransferContext = new DirectoryTransferContext();

            // Subscribe to the transfer events if an action method was passed.
            if (transferEvent != null)
            {
                directoryTransferContext.FileTransferred += (fileTransferSender, fileTransferredEventArgs) =>
                {
                    ITransferEvent i = (TransferEvent)fileTransferredEventArgs;
                    transferEvent(Core.TransferEventType.Transferred, i);
                };

                directoryTransferContext.FileFailed += (fileFailedSender, fileTransferredEventArgs) =>
                {
                    ITransferEvent i = (TransferEvent)fileTransferredEventArgs;
                    transferEvent(Core.TransferEventType.Failed, i);
                };

                directoryTransferContext.FileSkipped += (fileSkippedSender, fileTransferredEventArgs) =>
                {
                    ITransferEvent i = (TransferEvent)fileTransferredEventArgs;
                    transferEvent(Core.TransferEventType.Skipped, i);
                };
            }

            directoryTransferContext.ShouldOverwriteCallbackAsync = (source, destination) => Task.FromResult(true);

            var copyOptions = new CopyDirectoryOptions {
                BlobType = BlobType.AppendBlob, Recursive = true
            };

            var sourceContainer   = CloudBlobClient.GetContainerReference(sourceContainerName);
            var sourceRelativeUrl = GetPathWithoutContainer(sourceDirectoryPath);
            var sourceDirectory   = sourceContainer.GetDirectoryReference(sourceRelativeUrl);

            var destinationContainer   = CloudBlobClient.GetContainerReference(destinationContainerName);
            var destinationRelativeUrl = GetPathWithoutContainer(destinationDirectoryPath);
            var destinationDirectory   = destinationContainer.GetDirectoryReference(destinationRelativeUrl);

            var transferTask = TransferManager.CopyDirectoryAsync(sourceDirectory, destinationDirectory, CopyMethod.ServiceSideSyncCopy, copyOptions, directoryTransferContext);
            var result       = await transferTask;

            // Output the result from the transfer.
            return(new TransferResult
            {
                BytesTransferred = result.BytesTransferred,
                NumberOfFilesFailed = result.NumberOfFilesFailed,
                NumberOfFilesSkipped = result.NumberOfFilesSkipped,
                NumberOfFilesTransferred = result.NumberOfFilesTransferred
            });
        }
Example #14
0
        async void RenameToolStripMenuItem_ClickAsync(object sender, EventArgs e)
        {
            TreeNode node = Containers.SelectedNode;

            if (node == null)
            {
                MessageBox.Show("Choose an item to rename first");
                return;
            }

            CloudBlobDirectory sourceDir;
            CloudBlobDirectory targetDir;
            var options = new CopyDirectoryOptions {
                Recursive = true
            };
            TreeNode parentNode = node.Parent;

            switch (node.ImageIndex)
            {
            case 0:
                new AskForm("Rename Container").ShowDialog();
                if (Answer == null)
                {
                    return;
                }

                if (!Answer.Any(n => n.IsLetter()))
                {
                    MessageBox.Show("Russian is not allowed");
                    return;
                }
                ProgressBar.Visible = true;

                CloudBlobContainer sourceC = Client.GetContainerReference(node.Text);
                CloudBlobContainer targetC = Client.GetContainerReference(Answer);
                await targetC.CreateIfNotExistsAsync();

                foreach (var blob in sourceC.ListBlobs())
                {
                    switch (blob)
                    {
                    case CloudBlobDirectory cbd:
                        sourceDir = sourceC.GetDirectoryReference(blob.Uri.Directory());
                        targetDir = targetC.GetDirectoryReference(blob.Uri.Directory());
                        await TransferManager.CopyDirectoryAsync(sourceDir, targetDir, true, options, null);

                        break;

                    case CloudBlob cb:
                        CloudBlob sourceBlob = sourceC.GetBlobReference(blob.Uri.File());
                        CloudBlob targetBlob = targetC.GetBlobReference(blob.Uri.File());
                        await TransferManager.CopyAsync(sourceBlob, targetBlob, true);

                        break;
                    }
                }
                await sourceC.DeleteIfExistsAsync();

                break;

            case 1:
                switch (parentNode.ImageIndex)
                {
                case 0:
                    CloudBlobContainer container = Client.GetContainerReference(parentNode.Text);
                    sourceDir = container.GetDirectoryReference(node.Text);

                    new AskForm("Rename Directory").ShowDialog();
                    if (Answer == null)
                    {
                        return;
                    }
                    ProgressBar.Visible = true;

                    targetDir = container.GetDirectoryReference(Answer);
                    await TransferManager.CopyDirectoryAsync(sourceDir, targetDir, true, options, null);
                    await DeleteDirectory(sourceDir);

                    break;

                case 1:
                    (TreeNode containerNode, int count, string[] hier) = GetContainerNode(parentNode);
                    Array.Reverse(hier);

                    container = Client.GetContainerReference(containerNode.Text);
                    sourceDir = container.GetDirectoryReference(hier[0]);

                    for (int i = 0; i < count; i++)
                    {
                        sourceDir = sourceDir.GetDirectoryReference(hier[i + 1]);
                    }
                    sourceDir = sourceDir.GetDirectoryReference(node.Text);

                    new AskForm("Rename Directory").ShowDialog();
                    if (Answer == null)
                    {
                        return;
                    }
                    ProgressBar.Visible = true;

                    targetDir = sourceDir.Parent.GetDirectoryReference(Answer);
                    await TransferManager.CopyDirectoryAsync(sourceDir, targetDir, true, options, null);
                    await DeleteDirectory(sourceDir);

                    break;
                }
                break;

            case 2:
                switch (parentNode.ImageIndex)
                {
                case 0:
                    CloudBlobContainer container  = Client.GetContainerReference(parentNode.Text);
                    CloudBlob          sourceBlob = container.GetBlobReference(node.Text);

                    new AskForm("Rename Cloud Blob").ShowDialog();
                    if (Answer == null)
                    {
                        return;
                    }
                    ProgressBar.Visible = true;

                    CloudBlob targetBlob = container.GetBlobReference(Answer);
                    await TransferManager.CopyAsync(sourceBlob, targetBlob, true);

                    await sourceBlob.DeleteIfExistsAsync();

                    break;

                case 1:
                    (TreeNode containerNode, int count, string[] hier) = GetContainerNode(parentNode);
                    Array.Reverse(hier);

                    container = Client.GetContainerReference(containerNode.Text);
                    sourceDir = container.GetDirectoryReference(hier[0]);

                    for (int i = 0; i < count; i++)
                    {
                        sourceDir = sourceDir.GetDirectoryReference(hier[i + 1]);
                    }
                    sourceBlob = sourceDir.GetBlobReference(node.Text);

                    new AskForm("Rename Cloud Blob").ShowDialog();
                    if (Answer == null)
                    {
                        return;
                    }
                    ProgressBar.Visible = true;

                    targetBlob = sourceDir.GetBlobReference(Answer);
                    await TransferManager.CopyAsync(sourceBlob, targetBlob, true);

                    await sourceBlob.DeleteIfExistsAsync();

                    break;
                }
                break;
            }
            RefreshAll();
            ProgressBar.Visible = false;
        }