private void UpdateProgress() { try { long total = 0, done = 0; int length = this.ProgressInfoList.Count; for (int i = 0; i < length; i++) { ProgressInfo p = this.ProgressInfoList.Values.ElementAt(i); total += p.Total; done += p.Transferred; } if (total == 0) { return; } int percentComplete = (int)(done * 100 / total); ProgressRecord progress = new ProgressRecord(1, string.Format("Copying '{0}'", this.folderName), string.Format("{0}% of {1}", percentComplete, GetSize(total))); progress.PercentComplete = percentComplete; //progress.CurrentOperation = "Downloading files"; //progress.StatusDescription = done + "/" + total; //progress.StatusDescription = string.Format("{0}% of {1}", percentComplete, GetSize(total)); this.CmdLetObj.WriteProgress(progress); } catch { } }
void IAction.CopyFileItem(ProgressInfo progressInfo) { string fileName = System.IO.Path.Combine(target.FullName, child.FileName); bool duplicateFile = File.Exists(fileName); bool hashcodeMatches = duplicateFile ? Utility.GetMD5HashFromFile(fileName).Equals(child.Hash) : false; if (duplicateFile && actionType == ActionType.None) { throw new IOException("File already exist"); } else if (!duplicateFile || actionType == ActionType.Force || (actionType == ActionType.Sync && !hashcodeMatches)) { using (var fileStream = new FileStream(fileName, actionType == ActionType.Force || actionType == ActionType.Sync ? FileMode.Create : FileMode.CreateNew)) { var downloader = client.GetAsyncFileDownloader(child); progressInfo.ProgressTotal(progressInfo.FileIndex, child.FileSizeBytes.GetValueOrDefault()); downloader.OnTransferProgress = (sender, args) => { if (args.Progress.TotalBytes > 0) { progressInfo.ProgressTransferred(progressInfo.FileIndex, args.Progress.BytesTransferred); } }; downloader.DownloadToAsync(fileStream).Wait(); fileStream.Close(); fileSupportDelegate(fileName); } } }
void IAction.CopyFileItem(ProgressInfo progressInfo) { var fileInfo = (FileInfo)child; Models.Item fileItem = null; fileName = child.Name; try { fileItem = client.Items.ByPath(uploadTarget.url, "/" + child.Name).Execute(); } catch (ODataException e) { if (e.Code != System.Net.HttpStatusCode.NotFound) { throw e; } } bool duplicate = fileItem != null && fileItem is Models.File; bool hashcodeMatches = duplicate ? (fileItem as Models.File).Hash.Equals(Utility.GetMD5HashFromFile(child.FullName)) : false; if (duplicate && actionType == ActionType.None) { throw new IOException("File already exist"); } else if (!duplicate || actionType == ActionType.Force || (actionType == ActionType.Sync && !hashcodeMatches)) { var uploadSpec = new UploadSpecificationRequest { CanResume = false, Details = details, FileName = fileInfo.Name, FileSize = fileInfo.Length, Method = UploadMethod.Threaded, Parent = uploadTarget.url, ThreadCount = 4, Raw = true }; using (var platformFileInfo = new PlatformFileInfo(fileInfo)) { var uploader = client.GetAsyncFileUploader(uploadSpec, platformFileInfo); progressInfo.ProgressTotal(progressInfo.FileIndex, fileInfo.Length); uploader.OnTransferProgress = (sender, args) => { if (args.Progress.TotalBytes > 0) { progressInfo.ProgressTransferred(progressInfo.FileIndex, args.Progress.BytesTransferred); } }; Task.Run(() => uploader.UploadAsync()).Wait(); fileSupportDelegate(fileInfo.Name); } } }
/// <summary> /// Execute all actions list in parallel (threads) /// </summary> internal void Execute() { int remainingCounter = ActionsQueue.Count; if (remainingCounter > 0) { int maxParallelThreads = System.Environment.ProcessorCount * 2; int runningThreads = 0; int threadIndex = 1; while (remainingCounter > 0) { // if actions queue is not empty and current running threads are less than the allowed max parallel threads count if (ActionsQueue.Count > 0 && runningThreads < maxParallelThreads) { runningThreads++; IAction downloadAction = ActionsQueue.Dequeue(); Task t = Task.Factory.StartNew(() => { try { ProgressInfo fileProgressInfo = new ProgressInfo(); fileProgressInfo.ProgressTransferred = this.ProgressDone; fileProgressInfo.ProgressTotal = this.ProgressTotal; fileProgressInfo.FileIndex = threadIndex; ProgressInfoList.Add(threadIndex++, fileProgressInfo); downloadAction.CopyFileItem(fileProgressInfo); } catch (Exception error) { Log.Logger.Instance.Error(error.Message); } remainingCounter--; runningThreads--; }); } UpdateProgress(); Thread.Sleep(1000); } UpdateProgress(); Thread.Sleep(1000); } }
/// <summary> /// Execute all actions list in parallel (threads) /// </summary> internal void Execute() { int remainingCounter = ActionsQueue.Count; if (remainingCounter > 0) { int maxParallelThreads = System.Environment.ProcessorCount * 2; int runningThreads = 0; int threadIndex = 1; while (remainingCounter > 0) { // if actions queue is not empty and current running threads are less than the allowed max parallel threads count if (ActionsQueue.Count > 0 && runningThreads < maxParallelThreads) { Interlocked.Increment(ref runningThreads); IAction downloadAction = ActionsQueue.Dequeue(); Task t = Task.Factory.StartNew(async() => { for (int i = 1; i <= 7; i++) { try { ProgressInfo fileProgressInfo = new ProgressInfo(); fileProgressInfo.ProgressTransferred = this.ProgressDone; fileProgressInfo.ProgressTotal = this.ProgressTotal; fileProgressInfo.FileIndex = threadIndex; ProgressInfoList.Add(threadIndex++, fileProgressInfo); if (i > 1) { // This means that this is a retry. In that case force the operation // Otherwise file already exists error is thrown downloadAction.OpActionType = ActionType.Force; downloadAction.CopyFileItem(fileProgressInfo); } else { downloadAction.CopyFileItem(fileProgressInfo); } // Task completed, break out of the loop. Log.Logger.Instance.Debug("Action on Filename : " + downloadAction.FileName + " got completed in " + i + " try"); break; } catch (AggregateException tce) { // This means ShareFile Client Api has cancelled the task. // Retry the operation. Log.Logger.Instance.Error(tce.Message + " Upload/Download action for " + downloadAction.FileName + "\n" + tce.StackTrace); if (i == 7) { // No need to wait break; } // Wait for sometime before retrying the operation double timeToWait = Math.Pow(2, i); await Task.Delay(TimeSpan.FromSeconds(timeToWait)); } catch (Exception e) { // This means operation failed due to some other reasons. // No need to retry, break out of the loop. Log.Logger.Instance.Error(e.Message + "\n" + e.StackTrace); break; } } Interlocked.Decrement(ref remainingCounter); Interlocked.Decrement(ref runningThreads); }); } UpdateProgress(); Thread.Sleep(1000); } UpdateProgress(); Thread.Sleep(1000); } }