<PackageReference Include="Relativity.Server.Import.SDK" Version="2.9.2" />

IoReporter

public class IoReporter : IIoReporter
Represents a class object to perform I/O operations, publish warning messages, and retry the operation.
using Relativity.DataExchange.Logger; using Relativity.DataExchange.Resources; using Relativity.Logging; using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Threading; namespace Relativity.DataExchange.Io { public class IoReporter : IIoReporter { private const int NoRetryInfo = -1; private int? ioErrorNumberOfRetriesShadowCopy; private int? ioErrorWaitTimeInSecondsShadowCopy; public IoReporterContext Context { get; } protected IAppSettings CachedAppSettings { get; } protected CancellationToken CancellationToken { get; } protected int IoErrorNumberOfRetries { get { if (!ioErrorNumberOfRetriesShadowCopy.HasValue) { ioErrorNumberOfRetriesShadowCopy = CachedAppSettings.IoErrorNumberOfRetries; if (CachedAppSettings.EnforceMinRetryCount) { int? nullable = ioErrorNumberOfRetriesShadowCopy; int num = 1; if ((nullable.GetValueOrDefault() < num) & nullable.HasValue) ioErrorNumberOfRetriesShadowCopy = 1; } } return ioErrorNumberOfRetriesShadowCopy.Value; } } protected int IoErrorWaitTimeInSeconds { get { if (!ioErrorWaitTimeInSecondsShadowCopy.HasValue) { ioErrorWaitTimeInSecondsShadowCopy = CachedAppSettings.IoErrorWaitTimeInSeconds; if (CachedAppSettings.EnforceMinWaitTime) { int? nullable = ioErrorWaitTimeInSecondsShadowCopy; int num = 1; if ((nullable.GetValueOrDefault() < num) & nullable.HasValue) ioErrorWaitTimeInSecondsShadowCopy = 1; } } return ioErrorWaitTimeInSecondsShadowCopy.Value; } } protected ILog Logger { get; } [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "The context argument is validated via ThrowIfNull.")] public IoReporter(IoReporterContext context, ILog logger, CancellationToken token) { Logger = logger.ThrowIfNull<ILog>("logger"); Context = context.ThrowIfNull("context"); CancellationToken = token; CachedAppSettings = context.AppSettings.DeepCopy(); } public static string BuildIoReporterWarningMessage(Exception exception, double timeoutSeconds) { return BuildIoReporterWarningMessage(exception, timeoutSeconds, -1, -1); } public static string BuildIoReporterWarningMessage(Exception exception, double timeoutSeconds, int retryCount, int totalRetryCount) { int num = totalRetryCount - retryCount; if (num < 0) num = 0; if (exception == null) { if (retryCount == -1 && totalRetryCount == -1) return string.Format(Strings.IoReporterWarningMessageWithoutException, timeoutSeconds); return string.Format(Strings.IoReporterWarningMessageWithoutExceptionAndRetryInfo, timeoutSeconds, num); } if (retryCount == -1 && totalRetryCount == -1) return string.Format(Strings.IoReporterWarningMessageWithException, timeoutSeconds, exception.Message); return string.Format(Strings.IoReporterWarningMessageWithExceptionAndRetryInfo, timeoutSeconds, num, exception.Message); } public virtual void CopyFile(string sourceFileName, string destFileName, bool overwrite, int lineNumber) { if (string.IsNullOrEmpty(sourceFileName)) throw new ArgumentNullException("sourceFileName"); if (string.IsNullOrEmpty(destFileName)) throw new ArgumentNullException("destFileName"); if (lineNumber < 0) throw new ArgumentOutOfRangeException("lineNumber", string.Format(Strings.LineNumberOutOfRangeExceptionMessage, "lineNumber")); Context.FileSystem.File.Copy(sourceFileName, destFileName, overwrite); } public virtual bool GetFileExists(string fileName, int lineNumber) { if (string.IsNullOrEmpty(fileName)) return false; if (lineNumber < 0) throw new ArgumentOutOfRangeException("lineNumber", string.Format(Strings.LineNumberOutOfRangeExceptionMessage, "lineNumber")); return Exec(lineNumber, fileName, "File Exists", () => Context.FileSystem.CreateFileInfo(fileName).Exists); } public virtual long GetFileLength(string fileName, int lineNumber) { if (string.IsNullOrEmpty(fileName)) return 0; if (lineNumber < 0) throw new ArgumentOutOfRangeException("lineNumber", string.Format(Strings.LineNumberOutOfRangeExceptionMessage, "lineNumber")); return Exec(lineNumber, fileName, "File Length", () => Context.FileSystem.CreateFileInfo(fileName).Length); } public virtual void PublishRetryMessage(Exception exception, TimeSpan timeSpan, int retryCount, int totalRetryCount, long lineNumber) { string text = BuildIoReporterWarningMessage(exception, timeSpan.TotalSeconds, retryCount, totalRetryCount); Context.PublishIoWarningEvent(new IoWarningEventArgs(text, lineNumber)); Logger.LogWarning(exception, text, Array.Empty<object>()); } public virtual void PublishWarningMessage(IoWarningEventArgs args) { if (args == null) throw new ArgumentNullException("args"); Context.PublishIoWarningEvent(args); Logger.LogWarning(args.Message, Array.Empty<object>()); } internal int CalculateWaitTimeInSeconds(int numberOfRetries) { int num = 0; if (numberOfRetries < IoErrorNumberOfRetries - 1) { num = IoErrorWaitTimeInSeconds; if (num < 0) num = 0; } return num; } private bool ThrowFileInfoInvalidPathException(Exception exception) { if (CachedAppSettings.DisableThrowOnIllegalCharacters) return ExceptionHelper.IsIllegalCharactersInPathException(exception); return false; } private FileInfoInvalidPathException CreateFileInfoInvalidPathException(Exception exception, string fileName) { string text = string.Format(CultureInfo.CurrentCulture, Strings.ImportInvalidPathCharactersExceptionMessage, fileName); Logger.LogError(exception, "{message}", new object[1] { text.Secure() }); return new FileInfoInvalidPathException(text); } private void LogWarning(Exception exception, TimeSpan timeSpan, int retryCount, int totalRetryCount) { string text = BuildIoReporterWarningMessage(exception, timeSpan.TotalSeconds, retryCount, totalRetryCount); Logger.LogWarning(exception, text, Array.Empty<object>()); } private void LogCancellation(int lineNumber, string fileName, string description) { Logger.LogInformation("The {description} I/O operation for file {fileName} and line number {lineNumber} has been canceled.", new object[3] { description, fileName.Secure(), lineNumber }); } private T Exec<T>(int lineNumber, string fileName, string description, Func<T> execFunc) { T result = default(T); int ioErrorNumberOfRetries = IoErrorNumberOfRetries; int num = ioErrorNumberOfRetries; Func<Exception, bool> func = null; while (num > 0) { if (CancellationToken.IsCancellationRequested) { LogCancellation(lineNumber, fileName, description); break; } try { num--; result = execFunc(); return result; } catch (OperationCanceledException) { LogCancellation(lineNumber, fileName, description); return result; } catch (Exception ex2) { if (func == null) func = RetryExceptionHelper.CreateRetryPredicate(Context.RetryOptions); if (!func(ex2)) throw; int retryCount = ioErrorNumberOfRetries - num; int num2 = CalculateWaitTimeInSeconds(num); TimeSpan timeSpan = TimeSpan.FromSeconds((double)num2); if (ThrowFileInfoInvalidPathException(ex2)) { LogWarning(ex2, timeSpan, retryCount, ioErrorNumberOfRetries); throw CreateFileInfoInvalidPathException(ex2, fileName); } if (num == 0 || Context.RetryOptions == RetryOptions.None) { LogWarning(ex2, timeSpan, retryCount, ioErrorNumberOfRetries); throw; } PublishRetryMessage(ex2, timeSpan, retryCount, ioErrorNumberOfRetries, lineNumber); if (num2 > 0) Thread.CurrentThread.Join(1000 * num2); } } return result; } } }