コード例 #1
0
        /// <summary>
        /// Post-processing of copying (from XStore to SMB)
        /// </summary>
        /// <param name="task">The task to end.</param>
        private static void EndCopyFromXStoreToSMB(XStoreFileOperationTask task)
        {
            if (task.IsSucceeded)
            {
                // Step 3, 4 and 5 for atomic copy
                // 3. delete dstFolder.old
                // 4. rename dstFolder -> dstFolder.old
                // 5. rename dstFolder.new -> dstFolder

                // get the original destination path
                string newDstRootUri = task.DstUri + NewExtension;
                string oldDstRootUri = task.DstUri + OldExtension;

                // Step 3, 4 & 5
                if (FabricDirectory.Exists(oldDstRootUri))
                {
                    // delete dstFolder.old
                    FabricDirectory.Delete(oldDstRootUri, recursive: true, deleteReadOnlyFiles: true);
                }

                if (FabricDirectory.Exists(task.DstUri))
                {
                    // rename dstFolder -> dstFolder.old
                    RenameFolder(task.DstUri, oldDstRootUri);
                }

                // rename dstFolder.new -> dstFolder; and clean up
                RenameFolder(newDstRootUri, task.DstUri);
                if (FabricDirectory.Exists(oldDstRootUri))
                {
                    FabricDirectory.Delete(oldDstRootUri, recursive: true, deleteReadOnlyFiles: true);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Delete a file (blob) from XStore
        /// </summary>
        /// <param name="blobContainer">The container from which to delete.</param>
        /// <param name="task">The task to perform.</param>
        private static void DeleteFileFromXStore(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            var blob = blobContainer.GetBlockBlobReference(task.SrcUri);

#if !DotNetCoreClr
            blob.DeleteIfExists();
#else
            blob.DeleteIfExistsAsync().Wait();
#endif
        }
コード例 #3
0
 /// <summary>
 /// Retry the task
 /// </summary>
 /// <param name="task">The task to be performed.</param>
 private void RetryTask(XStoreFileOperationTask task)
 {
     // retrycount + 1 and enqueue again
     if (task.RetryCount + 1 > MaxRetryAttempts)
     {
         // Enqueue to endqueue
         task.IsSucceeded = false;
         this.xstoreTaskPool.AddTaskToEndTaskQueue(task);
     }
     else
     {
         task.RetryCount = task.RetryCount + 1;
         this.xstoreTaskPool.AddTaskToTaskQueue(task);
     }
 }
コード例 #4
0
        /// <summary>
        /// Post-processing of copying (from SMB to XStore)
        /// </summary>
        /// <param name="blobContainer">The blob container from which copy is happening.</param>
        /// <param name="task">The task to end.</param>
        private static void EndCopyFromSMBToXStore(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            if (task.IsSucceeded)
            {
                // Generate a manifest on the xstore for the copied folder - only need for atomic copy
                // When doing atomic copy we have following assumptions:
                // 1) only one writer
                // 2) we don't overwrite to the exisiting folder
                // 3) later this folder is copied to smb with the exact path, no sub folder or parent folder
                // therefore it is enough to only generate a manifest file on the folder only
                var blob = blobContainer.GetBlockBlobReference(XStoreCommon.GetXStoreFolderManifest(task.DstUri));
#if !DotNetCoreClr
                blob.UploadText(DateTime.Now.ToString());
#else
                blob.UploadTextAsync(DateTime.Now.ToString()).Wait();
#endif
            }
        }
コード例 #5
0
        /// <summary>
        /// Upload a file from SMB to xstore
        /// </summary>
        /// <param name="blobContainer">
        /// Blob container
        /// </param>
        /// <param name="task">
        /// Task object
        /// </param>
        private void TransferFileFromSMBToXStore(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            if (!this.ShouldCopy(task.SrcUri))
            {
                return;
            }

            Int64 size = FabricFile.GetSize(task.SrcUri);
            // Create the Blob and upload the file
            var blob        = blobContainer.GetBlockBlobReference(task.DstUri);
            var blobWrapper = new XStoreBlobWrapper(blob);

            if (task.TimeoutHelper != null)
            {
                //task.TimeoutHelper.ThrowIfExpired();
                blobWrapper.UploadFromFile(task.SrcUri, (int)size, task.TimeoutHelper.GetRemainingTime());
            }
            else
            {
                blobWrapper.UploadFromFile(task.SrcUri, (int)size, TimeSpan.MaxValue);
            }
        }
コード例 #6
0
        /// <summary>
        /// Worker thread to perform the file operations
        /// </summary>
        private void ThreadRunImpl()
        {
            // Initialize xstore blobcontainer and connection in the thread
            // This is to prevent we block the dispatcher

            // Connect to azure blob storage
            string connectionString = this.storeParams.ConnectionString;

            var             storageAccount = CloudStorageAccount.Parse(connectionString);
            CloudBlobClient blobClient     = storageAccount.CreateCloudBlobClient();

            blobClient.DefaultRequestOptions = new BlobRequestOptions();
            blobClient.DefaultRequestOptions.MaximumExecutionTime = new TimeSpan(0, 5, 0);

            // For large file copies set up a custom timeout period; and using parallel settings
            blobClient.DefaultRequestOptions.ParallelOperationThreadCount = XStoreCommon.ParallelOperationThreadCount;

            // Get and create the container
            CloudBlobContainer blobContainer = blobClient.GetContainerReference(this.storeParams.Container);

            while (WaitHandle.WaitAny(this.syncEvents.EventArray) != 1)
            {
                XStoreFileOperationTask task = this.xstoreTaskPool.GetTaskFromTaskQueue();

                if (null != task)
                {
                    // We have got valid task
                    if (task.RetryCount > 0)
                    {
                        // Sleep random time to prevent all worker threads do the next try at the same time
                        Random rand             = new Random(DateTime.Now.Millisecond + this.workerID);
                        int    timeoutInSeconds = rand.Next(MinRetryInSeconds, MaxRetryInSeconds);
                        traceSource.WriteError(
                            ClassName,
                            string.Format(CultureInfo.InvariantCulture, "[RETRY] sleep {0} seconds to work on {1}", timeoutInSeconds, task.SrcUri));

                        Thread.Sleep(timeoutInSeconds * 1000);
                    }

                    if (task.IsFolder &&
                        task.OpType != XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToSMB &&
                        task.OpType != XStoreFileOperationTask.XStoreTaskType.EndCopyFromSMBToXStore &&
                        task.OpType != XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToXStore)
                    {
                        try
                        {
                            this.HandleFolder(blobContainer, task);
                        }
                        catch (Exception e)
                        {
                            traceSource.WriteError(
                                ClassName,
                                string.Format(CultureInfo.InvariantCulture, "[{0}] [{1}] EXCEPTION = {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, e.Message));

                            if (e is TimeoutException)
                            {
                                throw;
                            }

                            if (e is StorageException && e.InnerException is TimeoutException)
                            {
                                throw new TimeoutException(e.InnerException.Message);
                            }

                            if (ExceptionHandler.IsFatalException(e))
                            {
                                throw;
                            }

                            this.RetryTask(task);
                        }
                        finally
                        {
                            this.xstoreTaskPool.DecrementTaskCount();
                        }
                    }
                    else
                    {
                        try
                        {
                            switch (task.OpType)
                            {
                            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
                                this.TransferFileFromXStoreToSMB(blobContainer, task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
                                this.TransferFileFromSMBToXStore(blobContainer, task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
                                this.TransferFileFromXStoreToXStore(blobContainer, task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.RemoveFromXStore:
                                DeleteFileFromXStore(blobContainer, task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.EndCopyFromSMBToXStore:
                                EndCopyFromSMBToXStore(blobContainer, task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToSMB:
                                EndCopyFromXStoreToSMB(task);
                                break;

                            case XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToXStore:
                                EndCopyFromXStoreToXStore(blobContainer, task);
                                break;

                            default:
                                break;
                            }
                        }
                        catch (Exception e)
                        {
                            traceSource.WriteError(
                                ClassName,
                                string.Format(CultureInfo.InvariantCulture, "[{0}] [{1}] EXCEPTION = {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, e.Message));

                            string extraTracing = task.GetExtraTracing();
                            if (!string.IsNullOrEmpty(extraTracing))
                            {
                                traceSource.WriteInfo(ClassName, extraTracing);
                            }

                            if (e is TimeoutException)
                            {
                                throw;
                            }

                            if (e is StorageException && e.InnerException is TimeoutException)
                            {
                                throw new TimeoutException(e.InnerException.Message);
                            }

                            if (ExceptionHandler.IsFatalException(e))
                            {
                                throw;
                            }

                            this.RetryTask(task);
                        }
                        finally
                        {
                            this.xstoreTaskPool.DecrementTaskCount();
                        }
                    }
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Processing folder
        /// </summary>
        /// <param name="blobContainer">The blob container.</param>
        /// <param name="task">The task to be performed.</param>
        private void HandleFolder(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            // expand the task and enqueue new tasks
            string[] files;
            string[] subFolders;

            // See if we need to handle the folder
            if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists && FabricDirectory.Exists(task.DstUri))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if ((task.FileCopyFlag == CopyFlag.AtomicCopy ||
                          task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists) &&
                         task.IsRoot)
                {
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToSMB,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;
                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);
                    task.DstUri = task.DstUri + NewExtension;

                    // step1: delete dstFolder.new
                    if (FabricDirectory.Exists(task.DstUri))
                    {
                        FabricDirectory.Delete(task.DstUri, recursive: true, deleteReadOnlyFiles: true);
                    }
                }
            }
            else if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists &&
                    XStoreCommon.XStoreFolderExists(blobContainer, task.DstUri, false, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if (task.IsRoot)
                {
                    // if this is the root uri of this operation
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromSMBToXStore,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;
                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);

                    // remove the manifest of this folder
                    var blob = blobContainer.GetBlockBlobReference(XStoreCommon.GetXStoreFolderManifest(task.DstUri));
#if !DotNetCoreClr
                    blob.DeleteIfExists(DeleteSnapshotsOption.None, null, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null);
#else
                    blob.DeleteIfExistsAsync(DeleteSnapshotsOption.None, null, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null, null).Wait();
#endif
                }
            }
            else if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists &&
                    XStoreCommon.XStoreFolderExists(blobContainer, task.DstUri, false, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if (task.IsRoot)
                {
                    // if this is the root uri of this operation
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToXStore,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;

                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);

                    // remove the manifest of this folder
                    var blob = blobContainer.GetBlockBlobReference(XStoreCommon.GetXStoreFolderManifest(task.DstUri));

#if !DotNetCoreClr
                    blob.DeleteIfExists(DeleteSnapshotsOption.None, null, task.TimeoutHelper == null ? null : GetRequestOptions(task.TimeoutHelper));
#else
                    blob.DeleteIfExistsAsync(DeleteSnapshotsOption.None, null, task.TimeoutHelper == null ? null : GetRequestOptions(task.TimeoutHelper), null).Wait();
#endif
                }
            }

            string dstUri = null;

            switch (task.OpType)
            {
            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
            case XStoreFileOperationTask.XStoreTaskType.RemoveFromXStore:
                this.GetFilesAndSubfoldersFromXStore(blobContainer, task.SrcUri, out files, out subFolders, task.TimeoutHelper);
                break;

            case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
            default:
                GetFilesAndSubfoldersFromSMB(task.SrcUri, out files, out subFolders);
                break;
            }

            Queue <XStoreFileOperationTask> tasks = new Queue <XStoreFileOperationTask>();
            foreach (var file in files)
            {
                switch (task.OpType)
                {
                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
                    dstUri = ConvertBlobReferenceToSMBPath(file, task.SrcUri, task.DstUri);
                    if (task.OperationId != null)
                    {
                        XStoreCommon.AddDownloadContentEntry(task.OperationId.GetValueOrDefault(), file, dstUri);
                    }
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
                    dstUri = ConvertSMBPathToBlobReference(file, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
                    dstUri = ConvertBlobReferenceToBlobReference(file, task.SrcUri, task.DstUri);
                    break;
                }

                XStoreFileOperationTask newTask = new XStoreFileOperationTask(task.OpType, file, dstUri, false, 0, task.TimeoutHelper, task.OperationId);
                newTask.FileCopyFlag = task.FileCopyFlag;
                tasks.Enqueue(newTask);
            }

            foreach (var folder in subFolders)
            {
                switch (task.OpType)
                {
                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
                    dstUri = ConvertBlobReferenceToSMBPath(folder, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
                    dstUri = ConvertSMBPathToBlobReference(folder, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
                    dstUri = ConvertBlobReferenceToBlobReference(folder, task.SrcUri, task.DstUri);
                    break;
                }

                XStoreFileOperationTask newTask = new XStoreFileOperationTask(task.OpType, folder, dstUri, true, 0, task.TimeoutHelper);
                newTask.FileCopyFlag = task.FileCopyFlag;
                tasks.Enqueue(newTask);
            }

            this.xstoreTaskPool.AddTaskToTaskQueue(tasks);
        }
コード例 #8
0
        /// <summary>
        /// Download file from XStore to SMB
        /// </summary>
        /// <param name="blobContainer">The blob container having the file.</param>
        /// <param name="task">The task to be performed.</param>
        private void TransferFileFromXStoreToSMB(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            if (!this.ShouldCopy(task.SrcUri))
            {
                return;
            }

            // download the file
            if (task.PartialID >= 0)
            {
                // This is already a divided work; let's go ahead and download
                string dstSMBPath = XStoreCommon.GetPartialFileName(task.DstUri, task.PartialID);

                // Delete the file if it exists
                string directoryName = FabricPath.GetDirectoryName(dstSMBPath);
                if (!FabricDirectory.Exists(directoryName))
                {
                    FabricDirectory.CreateDirectory(directoryName);
                }

                if (FabricFile.Exists(dstSMBPath))
                {
                    FabricFile.Delete(dstSMBPath, deleteReadonly: true);
                }

                var blob        = blobContainer.GetBlockBlobReference(task.SrcUri);
                var blobWrapper = new XStoreBlobWrapper(blob);
                if (task.TimeoutHelper != null)
                {
                    //task.TimeoutHelper.ThrowIfExpired();
                    blobWrapper.DownloadPartToFile(dstSMBPath, task.Offset, task.Length, task.TimeoutHelper.GetRemainingTime());
                }
                else
                {
                    blobWrapper.DownloadPartToFile(dstSMBPath, task.Offset, task.Length, TimeSpan.MaxValue);
                }
            }
            else
            {
                // we are going to download a file, which we don't know the size yet
                var blob = blobContainer.GetBlockBlobReference(task.SrcUri);
#if !DotNetCoreClr
                blob.FetchAttributes(null, this.defaultRequestOption);
#else
                blob.FetchAttributesAsync(null, this.defaultRequestOption, null).Wait();
#endif
                int blobLength = (int)blob.Properties.Length;

                // Delete the file if it exists
                string directoryName = FabricPath.GetDirectoryName(task.DstUri);
                if (!FabricDirectory.Exists(directoryName))
                {
                    FabricDirectory.CreateDirectory(directoryName);
                }

                if (FabricFile.Exists(task.DstUri))
                {
                    FabricFile.Delete(task.DstUri, deleteReadonly: true);
                }

                if (blobLength < DownloadSizeThreshold)
                {
                    var blobWrapper = new XStoreBlobWrapper(blob);
                    if (task.TimeoutHelper != null)
                    {
                        blobWrapper.DownloadToFile(task.DstUri, blobLength, task.TimeoutHelper.GetRemainingTime(), task.OperationContext);
                    }
                    else
                    {
                        blobWrapper.DownloadToFile(task.DstUri, blobLength, TimeSpan.MaxValue, task.OperationContext);
                    }

                    return;
                }
                else
                {
                    // For large files we divided the work to couple threads.
                    int numThreads = Math.Min(
                        blobLength / ParrallelDownloadSize,
                        ParrallelDownloadThreadCount);

                    // Create new tasks to parallel download
                    Queue <XStoreFileOperationTask> tasks = new Queue <XStoreFileOperationTask>();
                    int offset = 0;
                    for (int i = 0; i < numThreads; i++)
                    {
                        int length;
                        if (i < numThreads - 1)
                        {
                            length = blobLength / numThreads;
                        }
                        else
                        {
                            length = blobLength - offset;
                        }

                        XStoreFileOperationTask newTask = new XStoreFileOperationTask(
                            XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB,
                            task.SrcUri,
                            task.DstUri,
                            false,
                            0,
                            task.TimeoutHelper);

                        newTask.FileCopyFlag = task.FileCopyFlag;
                        newTask.Offset       = offset;
                        newTask.Length       = length;
                        newTask.PartialID    = i;

                        tasks.Enqueue(newTask);
                        offset += length;
                    }

                    // enqueue all divided tasks
                    this.xstoreTaskPool.AddTaskToTaskQueue(tasks);

                    // Add an EndTask to the endTaskQueue as well; to combine all downloads
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.CombinePartialFiles,
                        task.SrcUri,
                        task.DstUri,
                        false,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;
                    endTask.PartialID    = numThreads;
                    endTask.Content      = task.DstUri;
                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);
                }
            }
        }
コード例 #9
0
        /// <summary>
        /// Copy a file from xstore to xstore
        /// </summary>
        /// <param name="blobContainer">
        /// Blob container
        /// </param>
        /// <param name="task">
        /// Task object
        /// </param>
        private void TransferFileFromXStoreToXStore(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            if (!this.ShouldCopy(task.SrcUri))
            {
                return;
            }

            var destinationBlob = blobContainer.GetBlockBlobReference(task.DstUri);
            var sourceBlob      = blobContainer.GetBlockBlobReference(task.SrcUri);

#if !DotNetCoreClr
            sourceBlob.FetchAttributes();
#else
            sourceBlob.FetchAttributesAsync().Wait();
#endif
            int blobLength  = (int)sourceBlob.Properties.Length;
            var blobWrapper = new XStoreBlobWrapper(destinationBlob);
            blobWrapper.CopyFromXStore(sourceBlob, blobLength, task.TimeoutHelper != null ? task.TimeoutHelper.GetRemainingTime() : TimeSpan.MaxValue);
        }