using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core; using Tango.FileSystem; namespace Tango.FSE.Common.FileSystem { public class FileSystemHandler : ExtendedObject { private Action _abortAction; private FileSystemHandlerStatus _statusBeforePause; private System.Timers.Timer _transferRateTimer; private double _lastPosition; private TaskCompletionSource _completionSource; private bool _completed; public event EventHandler StatusChanged; public event EventHandler> ProgressChanged; public event EventHandler IsPausedChanged; public FileSystemHandlerType Type { get; set; } private FileSystemHandlerStatus _status; public FileSystemHandlerStatus Status { get { return _status; } set { if (_status != value) { _status = value; RaisePropertyChangedAuto(); StatusChanged?.Invoke(this, _status); } } } private TangoProgress _progress; public TangoProgress Progress { get { return _progress; } set { _progress = value; RaisePropertyChangedAuto(); } } private bool _isPaused; public bool IsPaused { get { return _isPaused; } set { if (_isPaused != value) { _isPaused = value; IsPausedChanged?.Invoke(this, new EventArgs()); if (_isPaused) { _statusBeforePause = Status; Status = FileSystemHandlerStatus.Paused; } else { Status = _statusBeforePause; } RaisePropertyChangedAuto(); } } } private long _transferRate; public long TransferRate { get { return _transferRate; } set { _transferRate = value; RaisePropertyChangedAuto(); } } private Exception _failedException; public Exception FailedException { get { return _failedException; } set { _failedException = value; RaisePropertyChangedAuto(); } } public FileSystemItem FileSystemItem { get; set; } public String Destination { get; set; } public String OperationId { get; set; } public FileSystemHandler(FileSystemHandlerType type, FileSystemItem fileSystemItem, String destination, Action abortAction) { Progress = new TangoProgress(); _completionSource = new TaskCompletionSource(); Type = type; FileSystemItem = fileSystemItem; Destination = destination; _abortAction = abortAction; } private void _transferRateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (Status == FileSystemHandlerStatus.Aborted || Status == FileSystemHandlerStatus.Completed || Status == FileSystemHandlerStatus.Failed) { _transferRateTimer.Dispose(); return; } TransferRate = (long)(Progress.Value - _lastPosition); _lastPosition = Progress.Value; } internal void InvalidateProgress(double position, double length) { if (_transferRateTimer == null) { _transferRateTimer = new System.Timers.Timer(1000); _transferRateTimer.Elapsed += _transferRateTimer_Elapsed; _transferRateTimer.Start(); } Progress = new TangoProgress() { IsIndeterminate = false, Value = position, Maximum = length, }; ProgressChanged?.Invoke(this, new TangoProgressChangedEventArgs(Progress)); if (!IsPaused) { Status = (Type == FileSystemHandlerType.FileDownload || Type == FileSystemHandlerType.FolderDownload) ? FileSystemHandlerStatus.Downloading : FileSystemHandlerStatus.Uploading; } } internal void RaiseFailed(Exception exception) { if (!_completed) { _completed = true; Status = FileSystemHandlerStatus.Failed; FailedException = exception; _completionSource.SetException(exception); } } internal void RaiseAborted() { if (!_completed) { _completed = true; Status = FileSystemHandlerStatus.Aborted; _completionSource.SetException(new OperationCanceledException("File system operation aborted.")); } } internal void RaiseCompleted() { if (!_completed) { _completed = true; Status = FileSystemHandlerStatus.Completed; _completionSource.SetResult(Status); } } public void Abort() { Status = FileSystemHandlerStatus.Aborted; _abortAction?.Invoke(); } public Task WaitForCompletion() { return _completionSource.Task; } } }