<PackageReference Include="Relativity.Server.Transfer.SDK" Version="7.7.0" />

HttpTransferCommand

using Relativity.Services.Exceptions; using Relativity.Transfer.Http.Issues; using Relativity.Transfer.Http.Paths; using Relativity.Transfer.Http.Resources; using Relativity.Transfer.Paths; using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer.Http { internal sealed class HttpTransferCommand : TransferPathCommandBase { private const string LogPrefix = "HTTP Transfer Command"; private readonly HttpClientConfiguration configuration; private readonly IFileTransferService fileTransferService; private readonly HttpTransferIssueBuilderFactory issueBuilderFactory; public HttpTransferCommand(ITransferLog log, ITransferRequest request, ITransferJobService jobService, IFileSystemService fileSystemService, HttpClientConfiguration configuration, IFileTransferService fileTransferService) : base(log, request, jobService, fileSystemService, configuration) { if (fileTransferService == null) throw new ArgumentNullException("fileTransferService"); if (configuration == null) throw new ArgumentNullException("configuration"); this.fileTransferService = fileTransferService; this.configuration = configuration; issueBuilderFactory = new HttpTransferIssueBuilderFactory(this.configuration); } protected override TransferPathResult OnExecute(TransferPath path, CancellationToken token) { if (!(path == (TransferPath)null)) { TransferPathResult transferPathResult = new TransferPathResult { Path = path, Status = TransferPathStatus.Started, StartTime = new DateTime?(DateTime.Now) }; TransferDirection direction; try { if (!token.IsCancellationRequested) { LargeFileProgress progress = (base.LargeFileProgressProvider != null) ? new LargeFileProgress(OnLargeFileProgress, base.LargeFileProgressRateSeconds) : null; direction = base.Request.Direction; TaskAwaiter<TransferPathResult> awaiter; switch (direction) { case TransferDirection.Download: { Task<TransferPathResult> task2 = fileTransferService.DownloadAsync(path, token, progress); task2.Wait(token); awaiter = task2.GetAwaiter(); transferPathResult = awaiter.GetResult(); break; } case TransferDirection.Upload: { Task<TransferPathResult> task = fileTransferService.UploadAsync(path, token, progress); task.Wait(token); awaiter = task.GetAwaiter(); transferPathResult = awaiter.GetResult(); break; } } if (transferPathResult.Status == TransferPathStatus.Successful || transferPathResult.Status == TransferPathStatus.Skipped) base.JobService.Statistics.TotalTransferredFiles++; base.JobService.Statistics.TotalTransferredBytes += transferPathResult.BytesTransferred; PublishTransferStatistics(false); if (token.IsCancellationRequested) { transferPathResult.Status = TransferPathStatus.Canceled; transferPathResult.EndTime = DateTime.Now; } return transferPathResult; } transferPathResult.Status = TransferPathStatus.Canceled; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } catch (ArgumentException ex) { base.Log.LogError(ex, "The transfer path contains one or more invalid data.", Array.Empty<object>()); IssueAttributes attribute = IssueAttributes.Error | IssueAttributes.File | IssueAttributes.InvalidCharacters; PublishTransferIssue(path, attribute, ex); throw new TransferException(ex.Message, ex, true); } catch (UnauthorizedAccessException exception) { return HandleUnauthorizedAccessException(path, exception, transferPathResult, configuration.MaxJobRetryAttempts); } catch (IOException ex2) { ITransferLog log = base.Log; IOException exception2 = ex2; object[] obj = new object[5]; direction = base.Request.Direction; obj[0] = direction.ToString(); obj[1] = path.SourcePath; obj[2] = (path.TargetFileName ?? string.Empty); obj[3] = path.TargetPath; obj[4] = LogRedaction.OnPositions(1, 2, 3); log.LogError(exception2, "An error occurred in File IO when {0} of path '{1}' with target name '{2}' to destination '{3}'", obj); IssueAttributes attribute2 = IssueAttributes.File | IssueAttributes.Io | IssueAttributes.StorageReadWrite | GetWarningErrorAttribute(); PublishTransferIssue(path, attribute2, ex2); throw new TransferException(ex2.Message, ex2, false); } catch (OperationCanceledException) { HandleCancel(transferPathResult); return transferPathResult; } catch (AggregateException ex4) { IssueAttributes issueAttributes = HandleAggregateException(ex4, path); if (issueAttributes.HasFlag(IssueAttributes.Error)) { ITransferLog log2 = base.Log; AggregateException exception3 = ex4; object[] obj2 = new object[5]; direction = base.Request.Direction; obj2[0] = direction.ToString(); obj2[1] = path.SourcePath; obj2[2] = (path.TargetFileName ?? string.Empty); obj2[3] = path.TargetPath; obj2[4] = LogRedaction.OnPositions(1, 2, 3); log2.LogError(exception3, "Error occurred during {0} of path '{1}' with target name '{2}' to destination '{3}'.", obj2); } else if (issueAttributes.HasFlag(IssueAttributes.Warning)) { ITransferLog log3 = base.Log; AggregateException exception4 = ex4; object[] obj3 = new object[5]; direction = base.Request.Direction; obj3[0] = direction.ToString(); obj3[1] = path.SourcePath; obj3[2] = (path.TargetFileName ?? string.Empty); obj3[3] = path.TargetPath; obj3[4] = LogRedaction.OnPositions(1, 2, 3); log3.LogWarning(exception4, "Error occurred during 0 of path '{1}' with target name '{2}' to destination '{3}' but is but is configured to bypass this specific error.", obj3); } if (!issueAttributes.HasFlag(IssueAttributes.FileNotFound)) { if (!base.FilePermissionErrorsRetry || !issueAttributes.HasFlag(IssueAttributes.ReadWritePermissions)) { HttpPathStatusResolver httpPathStatusResolver = new HttpPathStatusResolver(new PathStatusResolver(configuration)); using (IEnumerator<Exception> enumerator = ex4.Flatten().InnerExceptions.GetEnumerator()) { if (enumerator.MoveNext()) { Exception current = enumerator.Current; TransferPathStatus transferPathStatus = httpPathStatusResolver.Resolve(current); if (transferPathStatus == TransferPathStatus.Fatal) throw new TransferException(HttpErrorCodes.GetErrorMessage(current), current, true); transferPathResult.Status = transferPathStatus; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } } throw new TransferException(ex4.Message, ex4, false); } transferPathResult.Status = TransferPathStatus.PermissionsError; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } transferPathResult.Status = TransferPathStatus.FileNotFound; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } catch (Exception ex5) { ITransferLog log4 = base.Log; Exception exception5 = ex5; object[] obj4 = new object[5]; direction = base.Request.Direction; obj4[0] = direction.ToString(); obj4[1] = path.SourcePath; obj4[2] = (path.TargetFileName ?? string.Empty); obj4[3] = path.TargetPath; obj4[4] = LogRedaction.OnPositions(1, 2, 3); log4.LogError(exception5, "Error occurred during {0} of path '{1}' with target name '{2}' to destination '{3}'", obj4); IssueAttributes attribute3 = GetWarningErrorAttribute() | IssueAttributes.File; PublishTransferIssue(path, attribute3, ex5); throw new TransferException(ex5.Message, ex5, false); } } throw new ArgumentNullException("path"); } protected override void OnPreExecute(CancellationToken token) { if (!token.IsCancellationRequested) try { base.Log.LogInformation("{0} - Attempting to authenticate with Relativity.", "HTTP Transfer Command"); fileTransferService.Login(); base.Log.LogInformation("{0} - Successfully authenticated with Relativity.", "HTTP Transfer Command"); } catch (AggregateException ex) { base.Log.LogError(ex, HttpStrings.AuthenticationError, Array.Empty<object>()); HandleAggregateException(ex, null); } catch (Exception exception) { base.Log.LogError(exception, HttpStrings.AuthenticationError, Array.Empty<object>()); PublishTransferIssue(null, IssueAttributes.Authentication | IssueAttributes.Warning, exception); } } private IssueAttributes HandleAggregateException(AggregateException aggregateException, TransferPath path) { if (aggregateException == null) throw new ArgumentNullException("aggregateException"); IssueAttributes issueAttributes = (path != (TransferPath)null) ? IssueAttributes.File : IssueAttributes.Job; foreach (Exception innerException in aggregateException.Flatten().InnerExceptions) { IssueAttributes issueAttributesFromException = GetIssueAttributesFromException(path, innerException); issueAttributes |= issueAttributesFromException; PublishTransferIssue(path, issueAttributesFromException, innerException); } return issueAttributes; } private IssueAttributes GetIssueAttributesFromException(TransferPath path, Exception exception) { IssueAttributes issueAttributes = (path != (TransferPath)null) ? IssueAttributes.File : IssueAttributes.Job; if (!(exception.GetType() == typeof(UnauthorizedAccessException))) { if (!(exception.GetType() == typeof(ArgumentException))) { if (!(exception.GetType() == typeof(FileNotFoundException))) { if (!(exception.GetType() == typeof(DirectoryNotFoundException))) { if (!(exception.GetType() == typeof(HttpRequestException))) { if (!(exception.GetType() == typeof(ServiceException))) { if (!(exception.GetType() == typeof(ConflictException))) { if (!(exception.GetType() == typeof(OverflowException))) return issueAttributes | GetWarningErrorAttribute(); return issueAttributes | IssueAttributes.Error; } issueAttributes |= OnGeneralServiceCommunicationException(issueAttributes); return issueAttributes | OnFileNotFoundServiceCommunicationException(issueAttributes); } issueAttributes |= OnGeneralServiceCommunicationException(issueAttributes); return issueAttributes | GetWarningErrorAttribute(); } issueAttributes |= OnGeneralServiceCommunicationException(issueAttributes); if (!ContainsConflictCode(exception)) return issueAttributes | GetWarningErrorAttribute(); return issueAttributes | OnFileNotFoundServiceCommunicationException(issueAttributes); } return issueAttributes | (IssueAttributes.DirectoryNotFound | IssueAttributes.File | IssueAttributes.Io | GetWarningErrorAttribute()); } return issueAttributes | (IssueAttributes.File | IssueAttributes.FileNotFound | IssueAttributes.Io | (base.FileNotFoundErrorsDisabled ? IssueAttributes.Warning : GetWarningErrorAttribute())); } return issueAttributes | (IssueAttributes.Error | IssueAttributes.File | IssueAttributes.InvalidCharacters); } return issueAttributes | (IssueAttributes.File | IssueAttributes.ReadWritePermissions | (base.FilePermissionErrorsRetry ? GetWarningErrorAttribute() : IssueAttributes.Error)); } private IssueAttributes OnFileNotFoundServiceCommunicationException(IssueAttributes attribute) { attribute |= (IssueAttributes.FileNotFound | (base.FileNotFoundErrorsDisabled ? IssueAttributes.Warning : GetWarningErrorAttribute())); return attribute; } private IssueAttributes OnGeneralServiceCommunicationException(IssueAttributes attribute) { attribute |= (IssueAttributes.File | IssueAttributes.Io); return attribute; } private void PublishTransferIssue(TransferPath path, IssueAttributes attribute, Exception exception) { ITransferIssue issue = issueBuilderFactory.Create().CreateFromException(path, exception).WithAttributes(attribute) .WithMaxRetryAttempts(configuration.MaxJobRetryAttempts) .WithRetryAttempt(base.JobService.Statistics.RetryAttempt) .Build(); RegisterIssue(issue); } private static bool ContainsConflictCode(Exception exception) { string value = 409.ToString(); return exception.Message.Contains(value); } } }