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>());
}
}
}
}