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

AsperaEventHandler

using Aspera.Transfer; using Relativity.Transfer.Aspera.Resources; using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; namespace Relativity.Transfer.Aspera { internal class AsperaEventHandler : IAsperaEventHandler, IDisposable { private readonly ITransferLog log; private readonly ITransferRequest request; private readonly AutoResetEvent startJobWaitHandle = new AutoResetEvent(false); private readonly AutoResetEvent stopJobWaitHandle = new AutoResetEvent(false); private readonly List<ListenerHandlerBase> registeredHandlers = new List<ListenerHandlerBase>(); private readonly ITransferJobService jobService; private bool disposed; private readonly List<TransferEvent> EventsToSkipInRawLogs = new List<TransferEvent> { TransferEvent.FILE_START, TransferEvent.FILE_STOP, TransferEvent.PROGRESS }; private TransferStatus Status { get; set; } public AsperaEventHandler(ITransferRequest request, ITransferJobService service, ITransferLog log, AsperaClientConfiguration configuration) { if (request == null) throw new ArgumentNullException("request"); if (service == null) throw new ArgumentNullException("service"); if (log == null) throw new ArgumentNullException("log"); jobService = service; this.log = log; this.request = request; RegisterHandler(configuration); } private void RegisterHandler(AsperaClientConfiguration configuration) { ListenerHandlerBase item = ListenerFactory.CreateTransferListener(request, jobService, log, configuration); ListenerHandlerBase item2 = ListenerFactory.CreateSessionListener(request, jobService, log, configuration); ListenerHandlerBase item3 = ListenerFactory.CreateStatisticsListener(request, jobService, log, configuration); registeredHandlers.Add(item2); registeredHandlers.Add(item); registeredHandlers.Add(item3); } public TransferStatus GetTransferStatus() { return Status; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void HandleEvent(AsperaEvent asperaEvent) { try { foreach (ListenerHandlerBase registeredHandler in registeredHandlers) { try { registeredHandler.Execute(asperaEvent.TransferEvent, asperaEvent.SessionStats, asperaEvent.FileStats); } catch (Exception exception) { log.LogTransferError(exception, request, AsperaStrings.UnexpectedEventHandlerException, Array.Empty<object>()); } } } finally { bool flag = ShouldSignalStartJob(asperaEvent.TransferEvent, asperaEvent.SessionStats); bool flag2 = ShouldSignalStopJob(asperaEvent.TransferEvent, asperaEvent.SessionStats); try { jobService.PublishStatistics(flag2); if (flag) SignalStartJob(); } finally { if (flag2) { ValidateEndTime(); Status = jobService.CalculateTransferStatus(); SignalStopJob(); } } } } private void ValidateEndTime() { if (!jobService.Statistics.EndTime.HasValue) jobService.Statistics.EndTime = DateTime.Now; } public void WaitStartJob(CancellationToken token, TimeSpan timeout) { log.LogTransferDebug(request, "Waiting for the Aspera start job wait handle.", Array.Empty<object>()); WaitHandle.WaitAny(new WaitHandle[2] { token.WaitHandle, startJobWaitHandle }, timeout); log.LogTransferDebug(request, "Received the Aspera start job wait handle.", Array.Empty<object>()); } public void WaitStopJob(CancellationToken token, TimeSpan timeout) { log.LogTransferDebug(request, "Waiting for the Aspera stop job wait handle.", Array.Empty<object>()); WaitHandle.WaitAny(new WaitHandle[2] { token.WaitHandle, stopJobWaitHandle }, timeout); log.LogTransferDebug(request, "Received the Aspera stop job wait handle.", Array.Empty<object>()); } private static bool ShouldSignalStartJob(TransferEvent sessionEvent, SessionStats sessionStats) { if (sessionEvent == TransferEvent.SESSION_START) return true; if (sessionStats != null && sessionStats.State == SessionState.FAILED) return true; return false; } private static bool ShouldSignalStopJob(TransferEvent sessionEvent, SessionStats sessionStats) { if (sessionEvent == TransferEvent.SESSION_ERROR || sessionEvent == TransferEvent.SESSION_STOP) return true; if (sessionStats != null && (sessionStats.State == SessionState.FAILED || sessionStats.State == SessionState.FINISHED)) return true; return false; } private void SignalStartJob() { if (!disposed) { startJobWaitHandle.Set(); log.LogTransferDebug(request, "Set the Aspera listener start wait handle.", Array.Empty<object>()); } } private void SignalStopJob() { if (!disposed) { stopJobWaitHandle.Set(); log.LogTransferDebug(request, "Set the Aspera listener stop wait handle.", Array.Empty<object>()); } } private void Dispose(bool disposing) { if (!disposed) { if (disposing) { jobService.ClearTransferIssueList(); registeredHandlers.Clear(); startJobWaitHandle.Dispose(); stopJobWaitHandle.Dispose(); } disposed = true; } } [Conditional("DEBUG")] private void LogRawAsperaEvent(AsperaEvent asperaEvent) { if (!EventsToSkipInRawLogs.Contains(asperaEvent.TransferEvent)) { StringBuilder stringBuilder = new StringBuilder("RAW AsperaEvent:\n"); stringBuilder.AppendLine($"""{asperaEvent.TransferEvent}"); if (asperaEvent.SessionStats != null) { stringBuilder.AppendLine("SessionStats: "); stringBuilder.AppendLine(" - ID: " + asperaEvent.SessionStats.Id); stringBuilder.AppendLine(" - SessionId: " + asperaEvent.SessionStats.SessionId); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.XferId}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.XferRetry}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.State}"); stringBuilder.AppendLine(" - SourcePaths: " + asperaEvent.SessionStats.SourcePaths); stringBuilder.AppendLine(" - DestPath: " + asperaEvent.SessionStats.DestPath); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.UdpPort}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.Policy}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TotalWrittenBytes}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.FilesComplete}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.FilesSkipped}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.FilesFailed}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.ErrorCode}"); stringBuilder.AppendLine(" - ErrorDescription: " + asperaEvent.SessionStats.ErrorDescription); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TotalLostBytes}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TotalTransferredBytes}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.PreCalcTotalBytes}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.PreCalcTotalFiles}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.ElapsedUSec / 1000000}"); stringBuilder.AppendLine(" - ManifestFilePath: " + asperaEvent.SessionStats.ManifestFilePath); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TransfersAttempted}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TransfersFailed}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TransfersPassed}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TransfersSkipped}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.SourcePathsScanAttempted}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.SourcePathsScanFailed}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.SourcePathsScanIrregular}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.SourcePathsScanExcluded}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.Pmtu}"); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.TcpPort}"); stringBuilder.AppendLine(" - ServerNodeId: " + asperaEvent.SessionStats.ServerNodeId); stringBuilder.AppendLine(" - ClientNodeId: " + asperaEvent.SessionStats.ClientNodeId); stringBuilder.AppendLine(" - ServerClusterId: " + asperaEvent.SessionStats.ServerClusterId); stringBuilder.AppendLine(" - ClientClusterId: " + asperaEvent.SessionStats.ClientClusterId); stringBuilder.AppendLine($"""{asperaEvent.SessionStats.RetryTimeout}"); } if (asperaEvent.FileStats != null) { stringBuilder.AppendLine("FileStats: "); stringBuilder.AppendLine($"""{asperaEvent.FileStats.state}"); stringBuilder.AppendLine(" - name: " + asperaEvent.FileStats.name); stringBuilder.AppendLine($"""{asperaEvent.FileStats.errCode}"); stringBuilder.AppendLine(" - errDescription: " + asperaEvent.FileStats.errDescription); stringBuilder.AppendLine($"""{asperaEvent.FileStats.contiguousBytes}"); stringBuilder.AppendLine($"""{asperaEvent.FileStats.sizeBytes}"); stringBuilder.AppendLine($"""{asperaEvent.FileStats.writtenBytes}"); stringBuilder.AppendLine($"""{asperaEvent.FileStats.startByte}"); stringBuilder.AppendLine($"""{asperaEvent.FileStats.endByte}"); stringBuilder.AppendLine(" - fileChecksumType: " + asperaEvent.FileStats.fileChecksumType); stringBuilder.AppendLine(" - fileChecksum: " + asperaEvent.FileStats.fileChecksum); stringBuilder.AppendLine(" - name: " + asperaEvent.FileStats.name); stringBuilder.AppendLine(" - name: " + asperaEvent.FileStats.name); } log.LogInformation(stringBuilder.ToString(), Array.Empty<object>()); } } } }