aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-09 00:29:06 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-09 00:29:06 +0300
commit5774f40b650a376e9b622dba9df6c43589b0d398 (patch)
tree8d80f23cbb9cc264cc5be1bd82c52402eed612e6 /Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
parent42391bb46aa9dda0f56a7909268a2cffdf36f1d8 (diff)
downloadTango-5774f40b650a376e9b622dba9df6c43589b0d398.tar.gz
Tango-5774f40b650a376e9b622dba9df6c43589b0d398.zip
Logs, Comments & General organization on FSE/PPC.
Several improvements.
Diffstat (limited to 'Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs')
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs529
1 files changed, 408 insertions, 121 deletions
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
index 86ee2a73e..8381133bf 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
@@ -8,6 +8,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.Core;
+using Tango.Core.ExtensionMethods;
using Tango.Core.IO;
using Tango.Core.Threading;
using Tango.FileSystem;
@@ -20,31 +21,79 @@ using Tango.WebRTC;
namespace Tango.FSE.UI.FileSystem
{
+ /// <summary>
+ /// Represents the <see cref="IFileSystemProvider"/> default implementation.
+ /// </summary>
+ /// <seealso cref="Tango.Core.ExtendedObject" />
+ /// <seealso cref="Tango.FSE.Common.FileSystem.IFileSystemProvider" />
public class DefaultFileSystemProvider : ExtendedObject, IFileSystemProvider
{
private IMachineProvider _machineProvider;
private BasicTransporter _webRtcTransporter;
private const string WEB_RTC_CHANNEL_NAME = "FileSystemChannel";
- private const long MAX_CHUNK_SIZE = 1024 * 100;
- private const long MIN_CHUNK_SIZE = 1024;
- private const long MAX_CHUNK_SIZE_WEB_RTC = 1024 * 50;
- private const int WEB_RTC_MAX_RETRIES = 8;
+ private const long MAX_CHUNK_SIZE = 1024 * 100; //Max chunk size for the standard channel (WebSockets/SignalR).
+ private const long MIN_CHUNK_SIZE = 1024; //Min chunk size for the standard channel.
+ private const long MAX_CHUNK_SIZE_WEB_RTC = 1024 * 50; //Max chunk size for the WebRTC channel.
+ private const long MIN_CHUNK_SIZE_WEB_RTC = 1024; //Min chunk size for the WebRTC channel.
+ private const int WEB_RTC_MAX_RETRIES = 8; //Maximum number of retries per chunk for the WebRTC channel until falling back to standard channel.
private List<FileSystemHandler> _activeHandlers;
+ #region Properties
+
private bool _enableWebRTC;
+ /// <summary>
+ /// Gets or sets a value indicating whether to enable a P2P WebRTC channel for fast transport.
+ /// </summary>
public bool EnableWebRTC
{
get { return _enableWebRTC; }
- set { _enableWebRTC = value; RaisePropertyChangedAuto(); }
+ set
+ {
+ _enableWebRTC = value;
+ RaisePropertyChangedAuto();
+
+ if (value)
+ {
+ LogManager.Log("File system WebRTC channel is now enabled.");
+ }
+ else
+ {
+ LogManager.Log("File system WebRTC channel is now disabled.");
+ }
+ }
}
private bool _isWebRtcAvailable;
+ /// <summary>
+ /// Gets a value indicating whether the WebRTC channel is available.
+ /// </summary>
public bool IsWebRtcAvailable
{
get { return _isWebRtcAvailable; }
- private set { _isWebRtcAvailable = value; RaisePropertyChangedAuto(); }
+ private set
+ {
+ _isWebRtcAvailable = value;
+ RaisePropertyChangedAuto();
+
+ if (value)
+ {
+ LogManager.Log("File system WebRTC channel is now available.");
+ }
+ else
+ {
+ LogManager.Log("File system WebRTC channel is now available.");
+ }
+ }
}
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultFileSystemProvider"/> class.
+ /// </summary>
+ /// <param name="machineProvider">The machine provider.</param>
public DefaultFileSystemProvider(IMachineProvider machineProvider)
{
_activeHandlers = new List<FileSystemHandler>();
@@ -55,6 +104,10 @@ namespace Tango.FSE.UI.FileSystem
_machineProvider.MachineDisconnected += _machineProvider_MachineDisconnected;
}
+ #endregion
+
+ #region Machine Connection Event Handlers
+
private async void _machineProvider_MachineDisconnected(object sender, MachineDisconnectedEventArgs e)
{
IsWebRtcAvailable = false;
@@ -89,7 +142,7 @@ namespace Tango.FSE.UI.FileSystem
private async void _machineProvider_MachineConnected(object sender, MachineConnectedEventArgs e)
{
- if (EnableWebRTC)
+ if (_machineProvider.ConnectionType.IsRemote())
{
try
{
@@ -121,47 +174,100 @@ namespace Tango.FSE.UI.FileSystem
}
}
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Gets a folder by the specified path.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns></returns>
public async Task<IFileSystemContainer> GetFolder(string path)
{
- var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
+ try
{
- Path = path
- }, new TransportRequestConfig()
- {
- Timeout = TimeSpan.FromSeconds(30),
- });
+ LogManager.Log($"Retrieving remote folder '{path}'...");
- return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
+ {
+ Path = path,
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromSeconds(30),
+ });
+
+ return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Error retrieving remote folder.");
+ }
}
+ /// <summary>
+ /// Gets the specified special folder.
+ /// </summary>
+ /// <param name="specialFolder">The special folder.</param>
+ /// <returns></returns>
public async Task<IFileSystemContainer> GetSpecialFolder(Environment.SpecialFolder specialFolder)
{
- var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
- {
- SpecialFolder = specialFolder
- }, new TransportRequestConfig()
+ try
{
- Timeout = TimeSpan.FromSeconds(30),
- });
+ LogManager.Log($"Retrieving remote special folder '{specialFolder}'...");
+
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
+ {
+ SpecialFolder = specialFolder
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromSeconds(30),
+ });
- return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Error retrieving remote special folder.");
+ }
}
+ /// <summary>
+ /// Gets the ThisPC (the root path of the PC).
+ /// </summary>
+ /// <returns></returns>
public async Task<IFileSystemContainer> GetThisPC()
{
- var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
- {
- //No parameters at all
- }, new TransportRequestConfig()
+ try
{
- Timeout = TimeSpan.FromSeconds(30),
- });
+ LogManager.Log("Retrieving remote root directory (This PC)...");
- return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<GetFileSystemItemRequest, GetFileSystemItemResponse>(new GetFileSystemItemRequest()
+ {
+ //No parameters at all
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromSeconds(30),
+ });
+
+ return FileSystemItem.FromDTO(response.FileSystemItem) as IFileSystemContainer;
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Error retrieving remote root directory.");
+ }
}
+ /// <summary>
+ /// Downloads the specified file or folder item.
+ /// </summary>
+ /// <param name="item">The file or folder.</param>
+ /// <param name="localTargetFolder">The local target folder.</param>
+ /// <returns></returns>
public Task<FileSystemHandler> Download(FileSystemItem item, string localTargetFolder)
{
+ LogManager.Log($"Downloading remote item '{item.Path}' to local path '{localTargetFolder}'...");
+
String operationId = String.Empty;
String destination = String.Empty;
long downloadLength = 0;
@@ -171,23 +277,28 @@ namespace Tango.FSE.UI.FileSystem
destination = Path.Combine(localTargetFolder, item.Name);
-
handler = new FileSystemHandler(item.Type == FileSystemItemType.Folder ? FileSystemHandlerType.FolderDownload : FileSystemHandlerType.FileDownload, item, destination, async () =>
{
if (!aborted)
{
+ LogManager.Log($"Download aborted by user for '{item.Name}'. Aborting download...");
+
aborted = true;
try
{
+ LogManager.Log("Sending abort download operation request...");
+
var response = await _machineProvider.MachineOperator.SendGenericRequest<AbortOperationRequest, AbortOperationResponse>(
new AbortOperationRequest()
{
OperationId = operationId
}, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(30) });
+
+ LogManager.Log($"Download operation for '{item.Name} 'aborted successfully.");
}
catch (Exception ex)
{
- LogManager.Log(ex, "Error aborting the download operation.");
+ LogManager.Log(ex, $"Error aborting the download operation for '{item.Name}'.");
}
finally
{
@@ -204,24 +315,32 @@ namespace Tango.FSE.UI.FileSystem
{
if (item.Type == FileSystemItemType.File)
{
+ LogManager.Log("Download item identified as a file. Sending file download request...");
+
var response = await _machineProvider.MachineOperator.SendGenericRequest<FileDownloadRequest, FileDownloadResponse>(
new FileDownloadRequest()
{
Path = item.Path
}, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(20) });
+ LogManager.Log($"File download response received:\n{response.ToJsonString()}");
+
operationId = response.OperationId;
downloadLength = response.Length;
handler.OperationId = operationId;
}
else if (item.Type == FileSystemItemType.Folder)
{
+ LogManager.Log("Download item identified as a folder. Sending folder download request...");
+
var response = await _machineProvider.MachineOperator.SendGenericRequest<FolderDownloadRequest, FolderDownloadResponse>(
new FolderDownloadRequest()
{
Path = item.Path
}, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(60) });
+ LogManager.Log($"folder download response received:\n{response.ToJsonString()}");
+
operationId = response.OperationId;
downloadLength = response.Length;
handler.OperationId = operationId;
@@ -233,6 +352,7 @@ namespace Tango.FSE.UI.FileSystem
}
catch (Exception ex)
{
+ LogManager.Log(ex, $"Error downloading remote item '{item.Path}'.");
_activeHandlers.Remove(handler);
handler.RaiseFailed(ex);
return;
@@ -241,9 +361,14 @@ namespace Tango.FSE.UI.FileSystem
long position = 0;
bool webRtcFailed = false;
int webRtcRetries = WEB_RTC_MAX_RETRIES;
- long dynamixMaxChunkSizeSignalR = MAX_CHUNK_SIZE;
+ long dynamicMaxChunkSizeSignalR = MAX_CHUNK_SIZE;
+ long dynamicMaxChunkSizeWebRTC = MIN_CHUNK_SIZE_WEB_RTC;
+ bool isWebRTCChunkSizeFixed = false;
var tempFile = TemporaryManager.CreateFile();
+ LogManager.Log($"Generated temporary local file '{tempFile}'...");
+ LogManager.Log("Starting chunks download...");
+ LogManager.Log($"WebRTC active: {(IsWebRtcAvailable && EnableWebRTC).ToStringYesNo()}.");
while (position < downloadLength && !aborted)
{
@@ -263,27 +388,36 @@ namespace Tango.FSE.UI.FileSystem
Position = position,
};
- if (_webRtcTransporter != null && _webRtcTransporter.State == TransportComponentState.Connected && EnableWebRTC && !webRtcFailed)
+ if (_webRtcTransporter != null && _webRtcTransporter.State == TransportComponentState.Connected && EnableWebRTC && !webRtcFailed && _machineProvider.ConnectionType == MachineConnectionTypes.SignalR)
{
try
{
- request.MaxChunkSize = MAX_CHUNK_SIZE_WEB_RTC;
+ request.MaxChunkSize = dynamicMaxChunkSizeWebRTC;
+
response = await _webRtcTransporter.SendGenericRequest<ChunkDownloadRequest, ChunkDownloadResponse>(request, new TransportRequestConfig()
{
Timeout = TimeSpan.FromSeconds(2),
Priority = QueuePriority.Low
});
+ if (!isWebRTCChunkSizeFixed)
+ {
+ dynamicMaxChunkSizeWebRTC = Math.Min(dynamicMaxChunkSizeWebRTC + 1024, MAX_CHUNK_SIZE_WEB_RTC);
+ }
+
webRtcRetries = WEB_RTC_MAX_RETRIES;
}
catch (Exception ex)
{
webRtcRetries--;
+ dynamicMaxChunkSizeWebRTC = Math.Max(dynamicMaxChunkSizeWebRTC - 1024, MIN_CHUNK_SIZE_WEB_RTC);
+ isWebRTCChunkSizeFixed = true;
+
if (webRtcRetries == 0)
{
webRtcFailed = true;
- LogManager.Log(ex, "WebRTC chunk download failed. Falling back to standard download...");
+ LogManager.Log(ex, $"WebRTC chunk download for '{item.Name}' failed after {WEB_RTC_MAX_RETRIES} retries with exception:\n{ex.FlattenMessage()}\nFalling back to SignalR download...");
}
continue;
@@ -291,7 +425,7 @@ namespace Tango.FSE.UI.FileSystem
}
else
{
- request.MaxChunkSize = dynamixMaxChunkSizeSignalR;
+ request.MaxChunkSize = dynamicMaxChunkSizeSignalR;
Stopwatch watch = new Stopwatch();
watch.Start();
@@ -306,14 +440,14 @@ namespace Tango.FSE.UI.FileSystem
if (watch.Elapsed.TotalSeconds < 1)
{
- dynamixMaxChunkSizeSignalR += 1024 * 10;
+ dynamicMaxChunkSizeSignalR += 1024 * 10;
}
else if (watch.Elapsed.TotalSeconds > 1)
{
- dynamixMaxChunkSizeSignalR -= 1024 * 10;
+ dynamicMaxChunkSizeSignalR -= 1024 * 10;
}
- dynamixMaxChunkSizeSignalR = Math.Max(dynamixMaxChunkSizeSignalR, MIN_CHUNK_SIZE);
+ dynamicMaxChunkSizeSignalR = Math.Max(dynamicMaxChunkSizeSignalR, MIN_CHUNK_SIZE);
}
using (FileStream fs = new FileStream(tempFile, FileMode.Append))
@@ -326,6 +460,7 @@ namespace Tango.FSE.UI.FileSystem
}
catch (Exception ex)
{
+ LogManager.Log(ex, $"Download failed for '{item.Name}'.");
_activeHandlers.Remove(handler);
tempFile.Delete();
handler.RaiseFailed(ex);
@@ -335,27 +470,37 @@ namespace Tango.FSE.UI.FileSystem
if (!aborted)
{
+ LogManager.Log($"Chunks completed for '{item.Name}'.");
+
try
{
if (item.Type == FileSystemItemType.File)
{
+ LogManager.Log("Copying temporary file to destination directory...");
File.Copy(tempFile, destination, true);
+
+ LogManager.Log("Removing temporary file...");
tempFile.Delete();
}
else if (item.Type == FileSystemItemType.Folder)
{
+ LogManager.Log("Extracting temporary zip file to destination directory...");
+
using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(tempFile))
{
zip.ExtractAll(destination, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently);
}
+ LogManager.Log("Removing temporary zip file...");
tempFile.Delete();
}
+ LogManager.Log($"Download completed successfully for '{item.Name}'.");
handler.RaiseCompleted();
}
catch (Exception ex)
{
+ LogManager.Log(ex, $"Download failed on the final stage for {item.Name}.");
handler.RaiseFailed(ex);
}
}
@@ -370,6 +515,13 @@ namespace Tango.FSE.UI.FileSystem
return Task.FromResult(handler);
}
+ /// <summary>
+ /// Uploads the specified local file or folder.
+ /// </summary>
+ /// <param name="localSourcePath">The local source path.</param>
+ /// <param name="remoteFolder">The remote folder.</param>
+ /// <returns></returns>
+ /// <exception cref="System.IO.FileNotFoundException">Could not locate the local file or directory to upload.</exception>
public Task<FileSystemHandler> Upload(String localSourcePath, FileSystemItem remoteFolder)
{
String operationId = String.Empty;
@@ -381,44 +533,51 @@ namespace Tango.FSE.UI.FileSystem
if (Directory.Exists(localSourcePath))
{
+ LogManager.Log($"Uploading local folder '{localSourcePath}' to remote path '{remoteFolder.Path}'...");
sourceItem = new FolderItem() { Path = localSourcePath };
isFolder = true;
}
else if (File.Exists(localSourcePath))
{
+ LogManager.Log($"Uploading local file '{localSourcePath}' to remote path '{remoteFolder.Path}'...");
sourceItem = new FileItem() { Path = localSourcePath };
isFolder = false;
}
else
{
- throw new FileNotFoundException("Could not locate the local file or directory to upload.");
+ throw LogManager.Log(new FileNotFoundException("Could not locate the local file or directory to upload."), "Error uploading local item to remote location.");
}
FileSystemHandler handler = null;
handler = new FileSystemHandler(isFolder ? FileSystemHandlerType.FolderUpload : FileSystemHandlerType.FileUpload, sourceItem, destination, async () =>
- {
- if (!aborted)
- {
- aborted = true;
- try
- {
- var response = await _machineProvider.MachineOperator.SendGenericRequest<AbortOperationRequest, AbortOperationResponse>(
- new AbortOperationRequest()
- {
- OperationId = operationId
- }, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(30) });
- }
- catch (Exception ex)
- {
- LogManager.Log(ex, "Error aborting the upload operation.");
- }
- finally
- {
- handler.RaiseAborted();
- }
- }
- });
+ {
+ if (!aborted)
+ {
+ LogManager.Log($"Upload aborted by user for item '{sourceItem.Name}'. Aborting upload...");
+
+ aborted = true;
+ try
+ {
+ LogManager.Log("Sending upload operation abort request...");
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<AbortOperationRequest, AbortOperationResponse>(
+ new AbortOperationRequest()
+ {
+ OperationId = operationId
+ }, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(30) });
+
+ LogManager.Log($"Upload operation successfully aborted for item '{sourceItem.Name}'.");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error aborting the upload operation for item '{sourceItem.Name}'.");
+ }
+ finally
+ {
+ handler.RaiseAborted();
+ }
+ }
+ });
_activeHandlers.Add(handler);
@@ -428,23 +587,31 @@ namespace Tango.FSE.UI.FileSystem
{
if (!isFolder)
{
+ LogManager.Log("Upload item identified as a file. Sending file upload request...");
+
var response = await _machineProvider.MachineOperator.SendGenericRequest<FileUploadRequest, FileUploadResponse>(
new FileUploadRequest()
{
Path = destination
}, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(20) });
+ LogManager.Log($"File upload response received:\n{response.ToJsonString()}");
+
operationId = response.OperationId;
handler.OperationId = operationId;
}
else
{
+ LogManager.Log("Upload item identified as a folder. Sending file upload request...");
+
var response = await _machineProvider.MachineOperator.SendGenericRequest<FolderUploadRequest, FolderUploadResponse>(
new FolderUploadRequest()
{
Path = destination
}, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(20) });
+ LogManager.Log($"Folder upload response received:\n{response.ToJsonString()}");
+
operationId = response.OperationId;
handler.OperationId = operationId;
}
@@ -453,11 +620,13 @@ namespace Tango.FSE.UI.FileSystem
{
var originalPath = localSourcePath;
localSourcePath = TemporaryManager.CreateImaginaryFile().Path;
+ LogManager.Log($"Compressing local folder to temporary zip file '{localSourcePath}'...");
ZipFile.CreateFromDirectory(originalPath, localSourcePath);
}
}
catch (Exception ex)
{
+ LogManager.Log(ex, $"Error uploading local item '{sourceItem.Name}'.");
_activeHandlers.Remove(handler);
handler.RaiseFailed(ex);
return;
@@ -467,6 +636,11 @@ namespace Tango.FSE.UI.FileSystem
bool webRtcFailed = false;
int webRtcRetries = WEB_RTC_MAX_RETRIES;
long dynamixMaxChunkSizeSignalR = MAX_CHUNK_SIZE;
+ long dynamicMaxChunkSizeWebRTC = MIN_CHUNK_SIZE_WEB_RTC;
+ bool isWebRTCChunkSizeFixed = false;
+
+ LogManager.Log("Starting chunks download...");
+ LogManager.Log($"WebRTC active: {(IsWebRtcAvailable && EnableWebRTC).ToStringYesNo()}.");
using (FileStream fs = new FileStream(localSourcePath, FileMode.Open))
{
@@ -488,11 +662,11 @@ namespace Tango.FSE.UI.FileSystem
OperationId = operationId,
};
- if (_webRtcTransporter != null && _webRtcTransporter.State == TransportComponentState.Connected && EnableWebRTC && !webRtcFailed)
+ if (_webRtcTransporter != null && _webRtcTransporter.State == TransportComponentState.Connected && EnableWebRTC && !webRtcFailed && _machineProvider.ConnectionType == MachineConnectionTypes.SignalR)
{
try
{
- byte[] data = new byte[Math.Min(MAX_CHUNK_SIZE_WEB_RTC, fs.Length - fs.Position)];
+ byte[] data = new byte[Math.Min(dynamicMaxChunkSizeWebRTC, fs.Length - fs.Position)];
fs.Read(data, 0, data.Length);
request.Data = data;
request.IsCompleted = fs.Position == fs.Length;
@@ -503,16 +677,24 @@ namespace Tango.FSE.UI.FileSystem
Priority = QueuePriority.Low
});
+ if (!isWebRTCChunkSizeFixed)
+ {
+ dynamicMaxChunkSizeWebRTC = Math.Min(dynamicMaxChunkSizeWebRTC + 1024, MAX_CHUNK_SIZE_WEB_RTC);
+ }
+
webRtcRetries = WEB_RTC_MAX_RETRIES;
}
catch (Exception ex)
{
webRtcRetries--;
+ dynamicMaxChunkSizeWebRTC = Math.Max(dynamicMaxChunkSizeWebRTC - 1024, MIN_CHUNK_SIZE_WEB_RTC);
+ isWebRTCChunkSizeFixed = true;
+
if (webRtcRetries == 0)
{
webRtcFailed = true;
- LogManager.Log(ex, "WebRTC chunk upload failed. Falling back to standard upload...");
+ LogManager.Log(ex, $"WebRTC chunk upload for '{sourceItem.Name}' failed after {WEB_RTC_MAX_RETRIES} retries with exception:\n{ex.FlattenMessage()}\nFalling back to SignalR upload...");
}
continue;
@@ -553,6 +735,8 @@ namespace Tango.FSE.UI.FileSystem
}
catch (Exception ex)
{
+ LogManager.Log(ex, $"Upload failed for '{sourceItem.Name}'.");
+
_activeHandlers.Remove(handler);
handler.RaiseFailed(ex);
@@ -561,6 +745,7 @@ namespace Tango.FSE.UI.FileSystem
try
{
fs.Dispose();
+ LogManager.Log("Removing temporary zip file...");
File.Delete(localSourcePath);
}
catch { }
@@ -572,6 +757,7 @@ namespace Tango.FSE.UI.FileSystem
if (!aborted)
{
+ LogManager.Log($"Upload for '{sourceItem.Name}' completed successfully.");
handler.RaiseCompleted();
}
@@ -579,6 +765,7 @@ namespace Tango.FSE.UI.FileSystem
{
try
{
+ LogManager.Log("Removing temporary zip file...");
File.Delete(localSourcePath);
}
catch { }
@@ -591,107 +778,207 @@ namespace Tango.FSE.UI.FileSystem
return Task.FromResult(handler);
}
+ /// <summary>
+ /// Copies the specified remote file or folder to the specified target remote folder.
+ /// </summary>
+ /// <param name="source">The remote source file or folder.</param>
+ /// <param name="target">The remote target folder.</param>
+ /// <returns></returns>
+ /// <exception cref="System.NotSupportedException">
+ /// The source file system item is not supported for copying.
+ /// or
+ /// The target file system item is not a valid container.
+ /// </exception>
public async Task Copy(FileSystemItem source, FileSystemItem target)
{
- if (source.Type == FileSystemItemType.Drive)
- {
- throw new NotSupportedException("The source file system item is not supported for copying.");
- }
- if (target.Type == FileSystemItemType.File)
+ try
{
- throw new NotSupportedException("The target file system item is not a valid container.");
- }
+ LogManager.Log($"Copying remote item '{source.Path}' to '{target.Path}'...");
- await _machineProvider.MachineOperator.SendGenericRequest<CopyRequest, CopyResponse>(new CopyRequest()
- {
+ if (source.Type == FileSystemItemType.Drive)
+ {
+ throw new NotSupportedException("The source file system item is not supported for copying.");
+ }
+ if (target.Type == FileSystemItemType.File)
+ {
+ throw new NotSupportedException("The target file system item is not a valid container.");
+ }
+
+ await _machineProvider.MachineOperator.SendGenericRequest<CopyRequest, CopyResponse>(new CopyRequest()
+ {
- Source = source.Path,
- Destination = Path.Combine(target.Path, source.Name)
+ Source = source.Path,
+ Destination = Path.Combine(target.Path, source.Name)
- }, new TransportRequestConfig()
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromSeconds(120),
+ });
+ }
+ catch (Exception ex)
{
- Timeout = TimeSpan.FromSeconds(120),
- });
+ throw LogManager.Log(ex, "Error performing copy operation on remote file system.");
+ }
}
+ /// <summary>
+ /// Moves the specified remote file or folder to the remote target folder.
+ /// </summary>
+ /// <param name="source">The remote source file or folder.</param>
+ /// <param name="target">The remote target folder.</param>
+ /// <returns></returns>
+ /// <exception cref="System.NotSupportedException">
+ /// The source file system item is not supported for copying.
+ /// or
+ /// The target file system item is not a valid container.
+ /// </exception>
public async Task Move(FileSystemItem source, FileSystemItem target)
{
- if (source.Type == FileSystemItemType.Drive)
+ try
{
- throw new NotSupportedException("The source file system item is not supported for copying.");
- }
- if (target.Type == FileSystemItemType.File)
- {
- throw new NotSupportedException("The target file system item is not a valid container.");
- }
+ LogManager.Log($"Moving remote item '{source.Path}' to '{target.Path}'...");
- await _machineProvider.MachineOperator.SendGenericRequest<MoveRequest, MoveResponse>(new MoveRequest()
- {
+ if (source.Type == FileSystemItemType.Drive)
+ {
+ throw new NotSupportedException("The source file system item is not supported for moving.");
+ }
+ if (target.Type == FileSystemItemType.File)
+ {
+ throw new NotSupportedException("The target file system item is not a valid container.");
+ }
- Source = source.Path,
- Destination = Path.Combine(target.Path, source.Name)
+ await _machineProvider.MachineOperator.SendGenericRequest<MoveRequest, MoveResponse>(new MoveRequest()
+ {
+
+ Source = source.Path,
+ Destination = Path.Combine(target.Path, source.Name)
- }, new TransportRequestConfig()
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromSeconds(120),
+ });
+ }
+ catch (Exception ex)
{
- Timeout = TimeSpan.FromSeconds(120),
- });
+ throw LogManager.Log(ex, "Error performing move operation on the remote file system item.");
+ }
}
+ /// <summary>
+ /// Renames the specified file or folder.
+ /// </summary>
+ /// <param name="source">The remote source file or folder.</param>
+ /// <param name="newName">The new name.</param>
+ /// <returns></returns>
+ /// <exception cref="System.NotSupportedException">The source file system item is not supported for copying.</exception>
+ /// <exception cref="System.ArgumentException">The new name contains invalid characters.</exception>
public async Task Rename(FileSystemItem source, string newName)
{
- if (source.Type == FileSystemItemType.Drive)
+ try
{
- throw new NotSupportedException("The source file system item is not supported for copying.");
+ LogManager.Log($"Renaming remote item '{source.Path}' to '{newName}'...");
+
+ if (source.Type == FileSystemItemType.Drive)
+ {
+ throw new NotSupportedException("The source file system item is not supported for renaming.");
+ }
+ if (newName.ToList().Exists(x => Path.GetInvalidFileNameChars().Contains(x)))
+ {
+ throw new ArgumentException("The new name contains invalid characters.");
+ }
+
+ await _machineProvider.MachineOperator.SendGenericRequest<MoveRequest, MoveResponse>(new MoveRequest()
+ {
+ Source = source.Path,
+ Destination = Path.Combine(Path.GetDirectoryName(source.Path), newName)
+ });
}
- if (newName.ToList().Exists(x => Path.GetInvalidFileNameChars().Contains(x)))
+ catch (Exception ex)
{
- throw new ArgumentException("The new name contains invalid characters.");
+ throw LogManager.Log(ex, "Error performing rename operation on the remote file system item.");
}
-
- await _machineProvider.MachineOperator.SendGenericRequest<MoveRequest, MoveResponse>(new MoveRequest()
- {
-
- Source = source.Path,
- Destination = Path.Combine(Path.GetDirectoryName(source.Path), newName)
-
- });
}
+ /// <summary>
+ /// Deletes the specified file or folder.
+ /// </summary>
+ /// <param name="item">The remote file or folder.</param>
+ /// <returns></returns>
+ /// <exception cref="System.NotSupportedException">The source file system item is not supported for deletion.</exception>
public async Task Delete(FileSystemItem item)
{
- if (item.Type == FileSystemItemType.Drive)
+ try
{
- throw new NotSupportedException("The source file system item is not supported for deletion.");
- }
+ LogManager.Log($"Deleting remote item '{item.Path}'...");
+
+ if (item.Type == FileSystemItemType.Drive)
+ {
+ throw new NotSupportedException("The source file system item is not supported for deletion.");
+ }
- await _machineProvider.MachineOperator.SendGenericRequest<DeleteRequest, DeleteResponse>(new DeleteRequest()
+ await _machineProvider.MachineOperator.SendGenericRequest<DeleteRequest, DeleteResponse>(new DeleteRequest()
+ {
+ Path = item.Path
+ }, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(120) });
+ }
+ catch (Exception ex)
{
- Path = item.Path
- }, new TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(120) });
+ throw LogManager.Log(ex, "Error performing delete operation on the remote file system item.");
+ }
}
+ /// <summary>
+ /// Creates a new folder at the specified remote parent.
+ /// </summary>
+ /// <param name="parent">The remote parent path.</param>
+ /// <param name="folderName">Name of the new folder.</param>
+ /// <returns></returns>
public async Task<FolderItem> CreateFolder(FileSystemItem parent, string folderName)
{
- var response = await _machineProvider.MachineOperator.SendGenericRequest<CreateFolderRequest, CreateFolderResponse>(new CreateFolderRequest()
+ try
{
- Path = parent.Path,
- FolderName = folderName,
- });
+ LogManager.Log($"Creating new folder '{folderName}' on the remote path '{parent.Path}'...");
+
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<CreateFolderRequest, CreateFolderResponse>(new CreateFolderRequest()
+ {
+ Path = parent.Path,
+ FolderName = folderName,
+ });
- return FileSystemItem.FromDTO(response.FolderItem) as FolderItem;
+ return FileSystemItem.FromDTO(response.FolderItem) as FolderItem;
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Error creating new folder on the remote file system location.");
+ }
}
+ /// <summary>
+ /// Performs a disk space optimization.
+ /// </summary>
+ /// <returns></returns>
public async Task<PerformDiskSpaceOptimizationResponse> PerformDiskSpaceOptimization()
{
- var response = await _machineProvider.MachineOperator.SendGenericRequest<PerformDiskSpaceOptimizationRequest, PerformDiskSpaceOptimizationResponse>(new PerformDiskSpaceOptimizationRequest()
+ try
{
+ LogManager.Log("Performing disk space optimization on the remote file system.");
- }, new TransportRequestConfig()
- {
- Timeout = TimeSpan.FromMinutes(5)
- });
+ var response = await _machineProvider.MachineOperator.SendGenericRequest<PerformDiskSpaceOptimizationRequest, PerformDiskSpaceOptimizationResponse>(new PerformDiskSpaceOptimizationRequest()
+ {
+
+ }, new TransportRequestConfig()
+ {
+ Timeout = TimeSpan.FromMinutes(5)
+ });
- return response;
+ return response;
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Error occurred while trying to perform the disk space optimization on the remote file system.");
+ }
}
+
+ #endregion
}
}