deterministic-hash-code-helper

This commit is contained in:
Mike Phares 2025-04-06 13:22:44 -07:00
parent 4e6504af7e
commit 31b5a4925b
7 changed files with 458 additions and 47 deletions

View File

@ -18,6 +18,7 @@
"DEVICEHEIGHTPOINTS", "DEVICEHEIGHTPOINTS",
"DEVICEWIDTHPOINTS", "DEVICEWIDTHPOINTS",
"endianness", "endianness",
"Exif",
"FAMC", "FAMC",
"FAMS", "FAMS",
"FIXEDMEDIA", "FIXEDMEDIA",

7
.vscode/tasks.json vendored
View File

@ -82,13 +82,16 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "File-Folder-Helper AOT s X Sort", "label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
"type": "shell", "type": "shell",
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe",
"args": [ "args": [
"s", "s",
"X", "X",
"L:/DevOps/Mesa_FI/File-Watcher' Day-Helper-2024-01-08 'L:/DevOps/Mesa_FI/File-Watcher/Helpers" "L:/DevOps/Mesa_FI/File-Watcher",
"Day-Helper-2025-03-20",
"false",
"4"
], ],
"problemMatcher": [] "problemMatcher": []
} }

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Worker"> <Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
@ -10,8 +10,9 @@
<UserSecretsId>6062c774-99a9-4f4a-b42d-a9cb7fcbd8be</UserSecretsId> <UserSecretsId>6062c774-99a9-4f4a-b42d-a9cb7fcbd8be</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CliWrap" Version="3.8.2" />
<PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" /> <PackageReference Include="DiscUtils.Iso9660" Version="0.16.13" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.14" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
@ -19,9 +20,13 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.1" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.7.0" /> <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.7.0" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.13" /> <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.14" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" /> <PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.Drawing.Common" Version="8.0.14" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" /> <PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="9.0.2" /> <PackageReference Include="System.Text.Json" Version="9.0.3" />
<PackageReference Include="Phares.AA.Shared" Version="8.0.114.12235" />
<PackageReference Include="Phares.AA.Metadata" Version="8.0.114.12235" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,363 @@
using CliWrap;
using File_Watcher.Models;
using ShellProgressBar;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text.Json;
using View_by_Distance.Metadata.Models;
using View_by_Distance.Metadata.Models.Stateless;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless;
namespace File_Watcher.Helpers;
internal static partial class DeterministicHashCodeHelper
{
private class Windows : IWindows, IDisposable
{
private ProgressBar? _ProgressBar;
private readonly ProgressBarOptions _ProgressBarOptions;
public int CurrentTick { get; internal set; }
public Windows() =>
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient httpClient, Uri uri) =>
GetDeterministicHashCode(httpClient, uri);
DeterministicHashCode IWindows.GetDeterministicHashCode(HttpClient? httpClient, FilePath filePath)
{
DeterministicHashCode result;
if (httpClient is not null)
result = GetDeterministicHashCode(httpClient, new Uri(filePath.FullName));
else
{
Stream stream = File.OpenRead(filePath.FullName);
result = GetDeterministicHashCode(stream);
stream.Dispose();
}
return result;
}
private static DeterministicHashCode GetDeterministicHashCode(HttpClient httpClient, Uri uri)
{
DeterministicHashCode result;
Stream stream = GetStream(httpClient, uri);
result = GetDeterministicHashCode(stream);
stream.Dispose();
return result;
}
private static Stream GetStream(HttpClient httpClient, Uri uri)
{
Stream result;
Task<Stream> task = httpClient.GetStreamAsync(uri);
task.Wait();
result = task.Result;
return result;
}
private static DeterministicHashCode GetDeterministicHashCode(Stream stream)
{
DeterministicHashCode result;
int? id;
int? width;
int? height;
try
{
#pragma warning disable CA1416
using Image image = Image.FromStream(stream);
width = image.Width;
height = image.Height;
using Bitmap bitmap = new(image);
Rectangle rectangle = new(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
IntPtr intPtr = bitmapData.Scan0;
int length = bitmapData.Stride * bitmap.Height;
byte[] bytes = new byte[length];
Marshal.Copy(intPtr, bytes, 0, length);
bitmap.UnlockBits(bitmapData);
#pragma warning restore CA1416
id = IId.GetDeterministicHashCode(bytes);
}
catch (Exception)
{
id = null;
width = null;
height = null;
}
result = new(height, id, width);
return result;
}
void IWindows.Tick() =>
_ProgressBar?.Tick();
void IDisposable.Dispose()
{
_ProgressBar?.Dispose();
GC.SuppressFinalize(this);
}
void IWindows.ConstructProgressBar(int maxTicks, string message)
{
_ProgressBar?.Dispose();
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
}
ReadOnlyCollection<string> IWindows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(ResultSettings resultSettings, HttpClient? httpClient, FilePath filePath)
{
List<string> results = [];
bool isValidVideoFormatExtensions = resultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered);
if (isValidVideoFormatExtensions)
{
bool check;
if (httpClient is not null)
DownloadFile(httpClient, filePath);
try
{
CommandTask<CommandResult> commandTask = Cli.Wrap("L:/Git/ffmpeg-2024-10-02-git-358fdf3083-full_build/bin/ffmpeg.exe")
.WithArguments(["-i", filePath.FullName, "-vf", "select=eq(n\\,0)", "-q:v", "1", $"{filePath.Name}-%4d.jpg"])
.WithWorkingDirectory(filePath.DirectoryFullPath)
.ExecuteAsync();
commandTask.Task.Wait();
check = true;
}
catch (Exception)
{
check = false;
}
if (check)
{
results.AddRange(Directory.GetFiles(filePath.DirectoryFullPath, $"{filePath.Name}-*.jpg", SearchOption.TopDirectoryOnly));
if (results.Count == 0)
throw new Exception();
File.SetCreationTime(results[0], new(filePath.CreationTicks));
File.SetLastWriteTime(results[0], new(filePath.LastWriteTicks));
Thread.Sleep(100);
}
}
return results.AsReadOnly();
}
private static void DownloadFile(HttpClient httpClient, FilePath filePath)
{
FileStream fileStream = new(filePath.FullName, FileMode.Truncate);
Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(filePath.FullName);
httpResponseMessage.Wait();
Task task = httpResponseMessage.Result.Content.CopyToAsync(fileStream);
task.Wait();
}
}
internal static bool WindowsWork(AppSettings appSettings, ILogger<Worker>? logger)
{
string json;
string jsonFile;
string sourceDirectory;
List<string> check = [];
string archiveEntryFile;
long ticks = DateTime.Now.Ticks;
ReadOnlyCollection<FirstPass> collection;
string rootDirectory = Path.GetFullPath(appSettings.ResultSettings.RootDirectory);
if (!Directory.Exists(rootDirectory))
_ = Directory.CreateDirectory(rootDirectory);
string[] zipFiles = Directory.GetFiles(rootDirectory, "*.zip", SearchOption.TopDirectoryOnly);
if (zipFiles.Length > 0)
_ = IPath.DeleteEmptyDirectories(rootDirectory);
foreach (string zipFile in zipFiles)
{
check.Clear();
sourceDirectory = zipFile[..^4];
jsonFile = $"{sourceDirectory}.json";
if (Directory.Exists(sourceDirectory) || File.Exists(jsonFile))
continue;
_ = Directory.CreateDirectory(sourceDirectory);
using ZipArchive zip = ZipFile.Open(zipFile, ZipArchiveMode.Read);
foreach (ZipArchiveEntry zipArchiveEntry in zip.Entries)
{
check.Add(zipArchiveEntry.Name);
archiveEntryFile = Path.Combine(sourceDirectory, zipArchiveEntry.Name);
zipArchiveEntry.ExtractToFile(archiveEntryFile);
}
collection = WindowsWork(logger, appSettings, ticks, sourceDirectory);
if (check.Count == collection.Count)
{
json = JsonSerializer.Serialize(collection.ToList(), FirstPassCollectionSourceGenerationContext.Default.ListFirstPass);
File.WriteAllText(jsonFile, json);
}
Directory.Delete(sourceDirectory, recursive: true);
}
return true;
}
private static ReadOnlyCollection<FirstPass> WindowsWork(ILogger<Worker>? logger, AppSettings appSettings, long ticks, string sourceDirectory)
{
ReadOnlyCollection<FirstPass> results;
Windows windows = new();
IWindows windowsInterface = windows;
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, sourceDirectory);
A_Metadata metadata = new(appSettings.ResultSettings, appSettings.MetadataSettings);
int appSettingsMaxDegreeOfParallelism = appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism;
ReadOnlyCollection<string> files = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories).AsReadOnly();
if (files.Count > 0)
_ = IPath.DeleteEmptyDirectories(sourceDirectory);
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count : 123000;
windowsInterface.ConstructProgressBar(filesCount, "EnumerateFiles load");
if (appSettingsMaxDegreeOfParallelism == 1)
results = WindowsSynchronousWork(logger, appSettings, windowsInterface, files, metadata);
else
results = WindowsAsynchronousWork(appSettings, windows, files, metadata, appSettingsMaxDegreeOfParallelism);
return results;
}
private static ReadOnlyCollection<FirstPass> WindowsSynchronousWork(ILogger<Worker>? logger, AppSettings appSettings, IWindows windows, IEnumerable<string> files, A_Metadata metadata)
{
List<FirstPass> results = [];
int index = -1;
ReadOnlyDictionary<string, List<FileHolder>> keyValuePairs = IMetadata.GetKeyValuePairs(files);
foreach (KeyValuePair<string, List<FileHolder>> keyValuePair in keyValuePairs)
{
if (keyValuePair.Value.Count > 2)
throw new NotSupportedException("Too many sidecar files!");
index = WindowsSynchronousWork(logger, appSettings, windows, metadata, results, index, keyValuePair);
}
return results.AsReadOnly();
}
private static int WindowsSynchronousWork(ILogger<Worker>? logger, AppSettings appSettings, IWindows windows, A_Metadata metadata, List<FirstPass> results, int index, KeyValuePair<string, List<FileHolder>> keyValuePair)
{
int result = index + 1;
windows.Tick();
FilePath filePath;
FirstPass firstPass;
string directoryName;
ExifDirectory exifDirectory;
HttpClient? httpClient = null;
List<FileHolder> sidecarFiles;
DeterministicHashCode deterministicHashCode;
bool fastForwardMovingPictureExpertsGroupUsed;
MinimumYearAndPathCombined minimumYearAndPathCombined;
FilePath? fastForwardMovingPictureExpertsGroupFilePath;
ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
foreach (FileHolder fileHolder in keyValuePair.Value)
{
if (appSettings.DeterministicHashCodeConfiguration.SidecarExtensions.Contains(fileHolder.ExtensionLowered))
continue;
if (appSettings.ResultSettings.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
continue;
filePath = FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, fileHolder, result);
if (filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
continue;
if (filePath.Id is not null)
{
fastForwardMovingPictureExpertsGroupFiles = null;
deterministicHashCode = new(null, filePath.Id, null);
directoryName = Path.GetFileName(filePath.DirectoryFullPath);
if (directoryName.EndsWith(filePath.Id.Value.ToString()))
continue;
}
else
{
fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(appSettings.ResultSettings, httpClient, filePath);
fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(appSettings.ResultSettings, appSettings.MetadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), result);
deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? windows.GetDeterministicHashCode(httpClient, filePath) : windows.GetDeterministicHashCode(httpClient, fastForwardMovingPictureExpertsGroupFilePath);
}
sidecarFiles = [];
filePath = FilePath.Get(filePath, deterministicHashCode);
for (int i = 0; i < keyValuePair.Value.Count; i++)
{
if (keyValuePair.Value[i].ExtensionLowered == fileHolder.ExtensionLowered)
continue;
sidecarFiles.Add(keyValuePair.Value[i]);
}
try
{ (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(appSettings.ResultSettings, appSettings.MetadataSettings, httpClient, filePath); }
catch (Exception)
{
logger?.LogWarning("<{filePath}>", filePath.FullName);
continue;
}
fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
{
foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
File.Delete(fastForwardMovingPictureExpertsGroupFile);
}
if (!fastForwardMovingPictureExpertsGroupUsed && appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered))
fastForwardMovingPictureExpertsGroupUsed = true;
firstPass = new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, minimumYearAndPathCombined, sidecarFiles.ToArray());
results.Add(firstPass);
}
return result;
}
private static ReadOnlyCollection<FirstPass> WindowsAsynchronousWork(AppSettings appSettings, Windows windows, ReadOnlyCollection<string> files, A_Metadata metadata, int appSettingsMaxDegreeOfParallelism)
{
List<FirstPass> results = [];
FirstPass firstPass;
List<string> distinct = [];
List<MetadataGroup> metadataGroups = [];
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism };
files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(windows, appSettings.ResultSettings, appSettings.MetadataSettings, metadata, distinct, metadataGroups));
if (windows?.CurrentTick != results.Count)
throw new NotSupportedException();
foreach (MetadataGroup metadataGroup in metadataGroups)
{
if (metadataGroup.FastForwardMovingPictureExpertsGroupUsed || !appSettings.ResultSettings.ValidVideoFormatExtensions.Contains(metadataGroup.FilePath.ExtensionLowered))
firstPass = new(metadataGroup.ExifDirectory, metadataGroup.FastForwardMovingPictureExpertsGroupUsed, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
else
firstPass = new(metadataGroup.ExifDirectory, FastForwardMovingPictureExpertsGroupUsed: true, metadataGroup.MinimumYearAndPathCombined, metadataGroup.SidecarFiles.ToArray());
results.Add(firstPass);
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<NginxFileSystem>? GetRecursiveCollection(HttpClient httpClient, string host, string page)
{
List<NginxFileSystem>? results;
Uri uri = new($"http://{host}/{page}");
string format = NginxFileSystem.GetFormat();
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local;
Task<HttpResponseMessage> taskHttpResponseMessage = httpClient.GetAsync(uri);
taskHttpResponseMessage.Wait();
if (!taskHttpResponseMessage.Result.IsSuccessStatusCode)
results = null;
else
{
Task<string> taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync();
taskString.Wait();
NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray);
if (nginxFileSystems is null)
results = null;
else
{
results = [];
NginxFileSystem nginxFileSystem;
ReadOnlyCollection<NginxFileSystem>? directory;
for (int i = 0; i < nginxFileSystems.Length; i++)
{
nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]);
if (nginxFileSystem.Type == "file")
results.Add(nginxFileSystem);
else
{
directory = GetRecursiveCollection(httpClient, host, $"{page}/{nginxFileSystem.Name}");
if (directory is null)
continue;
results.AddRange(directory);
}
}
}
}
return results?.AsReadOnly();
}
}

View File

@ -1,47 +1,45 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace File_Watcher.Models; namespace File_Watcher.Models;
public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
CompassConfiguration CompassConfiguration, CompassConfiguration CompassConfiguration,
DeterministicHashCodeConfiguration DeterministicHashCodeConfiguration,
DriveConfiguration DriveConfiguration, DriveConfiguration DriveConfiguration,
EAFLogConfiguration EAFLogConfiguration, EAFLogConfiguration EAFLogConfiguration,
EDADatabaseConfiguration EDADatabaseConfiguration, EDADatabaseConfiguration EDADatabaseConfiguration,
FileWatcherConfiguration FileWatcherConfiguration, FileWatcherConfiguration FileWatcherConfiguration,
InfinityQSConfiguration InfinityQSConfiguration, InfinityQSConfiguration InfinityQSConfiguration,
IsoConfiguration IsoConfiguration, IsoConfiguration IsoConfiguration,
MetadataSettings MetadataSettings,
MetrologyConfiguration MetrologyConfiguration, MetrologyConfiguration MetrologyConfiguration,
NugetConfiguration NugetConfiguration, NugetConfiguration NugetConfiguration,
ResultSettings ResultSettings,
SerialConfiguration SerialConfiguration, SerialConfiguration SerialConfiguration,
StratusConfiguration StratusConfiguration, StratusConfiguration StratusConfiguration,
TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration, TransmissionControlProtocolConfiguration TransmissionControlProtocolConfiguration,
WaferCounterConfiguration WaferCounterConfiguration) WaferCounterConfiguration WaferCounterConfiguration)
{ {
public override string ToString()
{
string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings);
return result;
}
private static void Verify(AppSettings _)
{ }
public static AppSettings Get(IConfigurationRoot configurationRoot) public static AppSettings Get(IConfigurationRoot configurationRoot)
{ {
AppSettings result; AppSettings result;
#pragma warning disable IL3050, IL2026 #pragma warning disable IL3050, IL2026
CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>(); CamstarOracleConfiguration? camstarOracleConfiguration = configurationRoot.GetSection(nameof(CamstarOracleConfiguration)).Get<CamstarOracleConfiguration>();
CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>(); CompassConfiguration? compassConfiguration = configurationRoot.GetSection(nameof(CompassConfiguration)).Get<CompassConfiguration>();
DeterministicHashCodeConfiguration? deterministicHashCodeConfiguration = configurationRoot.GetSection(nameof(DeterministicHashCodeConfiguration)).Get<DeterministicHashCodeConfiguration>();
DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get<DriveConfiguration>(); DriveConfiguration? driveConfiguration = configurationRoot.GetSection(nameof(DriveConfiguration)).Get<DriveConfiguration>();
EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get<EAFLogConfiguration>(); EAFLogConfiguration? eafLogConfiguration = configurationRoot.GetSection(nameof(EAFLogConfiguration)).Get<EAFLogConfiguration>();
EDADatabaseConfiguration? edaDatabaseConfiguration = configurationRoot.GetSection(nameof(EDADatabaseConfiguration)).Get<EDADatabaseConfiguration>(); EDADatabaseConfiguration? edaDatabaseConfiguration = configurationRoot.GetSection(nameof(EDADatabaseConfiguration)).Get<EDADatabaseConfiguration>();
FileWatcherConfiguration? fileWatcherConfiguration = configurationRoot.GetSection(nameof(FileWatcherConfiguration)).Get<FileWatcherConfiguration>(); FileWatcherConfiguration? fileWatcherConfiguration = configurationRoot.GetSection(nameof(FileWatcherConfiguration)).Get<FileWatcherConfiguration>();
InfinityQSConfiguration? infinityQSConfiguration = configurationRoot.GetSection(nameof(InfinityQSConfiguration)).Get<InfinityQSConfiguration>(); InfinityQSConfiguration? infinityQSConfiguration = configurationRoot.GetSection(nameof(InfinityQSConfiguration)).Get<InfinityQSConfiguration>();
IsoConfiguration? isoConfiguration = configurationRoot.GetSection(nameof(IsoConfiguration)).Get<IsoConfiguration>(); IsoConfiguration? isoConfiguration = configurationRoot.GetSection(nameof(IsoConfiguration)).Get<IsoConfiguration>();
MetadataSettings? metadataSettings = configurationRoot.GetSection(nameof(MetadataSettings)).Get<MetadataSettings>();
MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get<MetrologyConfiguration>(); MetrologyConfiguration? metrologyConfiguration = configurationRoot.GetSection(nameof(MetrologyConfiguration)).Get<MetrologyConfiguration>();
NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get<NugetConfiguration>(); NugetConfiguration? nugetConfiguration = configurationRoot.GetSection(nameof(NugetConfiguration)).Get<NugetConfiguration>();
ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get<ResultSettings>();
SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get<SerialConfiguration>(); SerialConfiguration? serialConfiguration = configurationRoot.GetSection(nameof(SerialConfiguration)).Get<SerialConfiguration>();
StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get<StratusConfiguration>(); StratusConfiguration? stratusConfiguration = configurationRoot.GetSection(nameof(StratusConfiguration)).Get<StratusConfiguration>();
TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get<TransmissionControlProtocolConfiguration>(); TransmissionControlProtocolConfiguration? transmissionControlProtocolConfiguration = configurationRoot.GetSection(nameof(TransmissionControlProtocolConfiguration)).Get<TransmissionControlProtocolConfiguration>();
@ -49,14 +47,17 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
#pragma warning restore IL3050, IL2026 #pragma warning restore IL3050, IL2026
if (camstarOracleConfiguration is null if (camstarOracleConfiguration is null
|| compassConfiguration is null || compassConfiguration is null
|| deterministicHashCodeConfiguration is null
|| driveConfiguration is null || driveConfiguration is null
|| eafLogConfiguration is null || eafLogConfiguration is null
|| edaDatabaseConfiguration is null || edaDatabaseConfiguration is null
|| fileWatcherConfiguration is null || fileWatcherConfiguration is null
|| infinityQSConfiguration is null || infinityQSConfiguration is null
|| isoConfiguration is null || isoConfiguration is null
|| metadataSettings is null
|| metrologyConfiguration is null || metrologyConfiguration is null
|| nugetConfiguration is null || nugetConfiguration is null
|| resultSettings is null
|| serialConfiguration is null || serialConfiguration is null
|| stratusConfiguration is null || stratusConfiguration is null
|| transmissionControlProtocolConfiguration is null || transmissionControlProtocolConfiguration is null
@ -76,14 +77,17 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
} }
result = new(camstarOracleConfiguration, result = new(camstarOracleConfiguration,
compassConfiguration, compassConfiguration,
deterministicHashCodeConfiguration,
driveConfiguration, driveConfiguration,
eafLogConfiguration, eafLogConfiguration,
edaDatabaseConfiguration, edaDatabaseConfiguration,
fileWatcherConfiguration, fileWatcherConfiguration,
infinityQSConfiguration, infinityQSConfiguration,
isoConfiguration, isoConfiguration,
metadataSettings,
metrologyConfiguration, metrologyConfiguration,
nugetConfiguration, nugetConfiguration,
resultSettings,
serialConfiguration, serialConfiguration,
stratusConfiguration, stratusConfiguration,
transmissionControlProtocolConfiguration, transmissionControlProtocolConfiguration,
@ -92,6 +96,18 @@ public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration,
return result; return result;
} }
private static void Verify(AppSettings appSettings)
{
if (appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism > Environment.ProcessorCount)
throw new Exception($"Environment.ProcessorCount must be larger or equal to {nameof(appSettings.DeterministicHashCodeConfiguration.MaxDegreeOfParallelism)}");
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings);
return result;
}
} }
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]

View File

@ -0,0 +1,22 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Watcher.Models;
public record DeterministicHashCodeConfiguration(int MaxDegreeOfParallelism,
string[] SidecarExtensions)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, DeterministicHashCodeConfigurationSourceGenerationContext.Default.DeterministicHashCodeConfiguration);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(DeterministicHashCodeConfiguration))]
internal partial class DeterministicHashCodeConfigurationSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -1,4 +1,4 @@
using File_Watcher.Models; using File_Watcher.Models;
using Microsoft.Extensions.Hosting.WindowsServices; using Microsoft.Extensions.Hosting.WindowsServices;
using System.Data; using System.Data;
@ -13,13 +13,6 @@ public partial class Worker : BackgroundService
private readonly AppSettings _AppSettings; private readonly AppSettings _AppSettings;
private readonly IHttpClientFactory _HttpClientFactory; private readonly IHttpClientFactory _HttpClientFactory;
public override Task StopAsync(CancellationToken cancellationToken)
{
if (_AppSettings.FileWatcherConfiguration.Helper == nameof(Helpers.HelperCamstarOracle))
Helpers.HelperCamstarOracle.Heartbeat(_AppSettings, _HttpClientFactory, _Logger, Infineon.Monitoring.MonA.State.Down, cancellationToken);
return base.StopAsync(cancellationToken);
}
public Worker(IHttpClientFactory httpClientFactory, ILogger<Worker> logger, IServiceProvider serviceProvider, AppSettings appSettings, List<string> collection) public Worker(IHttpClientFactory httpClientFactory, ILogger<Worker> logger, IServiceProvider serviceProvider, AppSettings appSettings, List<string> collection)
{ {
_Logger = logger; _Logger = logger;
@ -33,6 +26,37 @@ public partial class Worker : BackgroundService
_IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime)); _IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime));
} }
public override Task StopAsync(CancellationToken cancellationToken)
{
if (_AppSettings.FileWatcherConfiguration.Helper == nameof(Helpers.HelperCamstarOracle))
Helpers.HelperCamstarOracle.Heartbeat(_AppSettings, _HttpClientFactory, _Logger, Infineon.Monitoring.MonA.State.Down, cancellationToken);
return base.StopAsync(cancellationToken);
}
protected override async Task ExecuteAsync(CancellationToken cancellationToken) =>
await Body(cancellationToken);
private async Task Body(CancellationToken cancellationToken)
{
if (!_IsWindowsService)
{
_Logger.LogInformation("Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!", _AppSettings.FileWatcherConfiguration.Helper);
throw new EvaluateException($"Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!");
}
if (!_IsWindowsService)
{
for (int i = 0; i < int.MaxValue; i++)
{
BodyInner(cancellationToken);
Thread.Sleep(_AppSettings.FileWatcherConfiguration.MillisecondsDelay);
}
}
while (_IsWindowsService && !cancellationToken.IsCancellationRequested)
{
BodyInner(cancellationToken);
await Task.Delay(_AppSettings.FileWatcherConfiguration.MillisecondsDelay, cancellationToken);
}
}
private void BodyInner(CancellationToken cancellationToken) private void BodyInner(CancellationToken cancellationToken)
{ {
_Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); _Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt"));
@ -60,6 +84,7 @@ public partial class Worker : BackgroundService
nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken),
nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger), nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger),
nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken),
nameof(Helpers.DeterministicHashCodeHelper) => Helpers.DeterministicHashCodeHelper.WindowsWork(_AppSettings, _Logger),
nameof(Helpers.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken),
_ => throw new NotSupportedException() _ => throw new NotSupportedException()
}; };
@ -67,28 +92,4 @@ public partial class Worker : BackgroundService
_Logger.LogInformation("B) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); _Logger.LogInformation("B) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.FileWatcherConfiguration.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt"));
} }
private async Task Body(CancellationToken cancellationToken)
{
if (!_IsWindowsService)
{
_Logger.LogInformation("Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!", _AppSettings.FileWatcherConfiguration.Helper);
throw new EvaluateException($"Set break point and skip to run {_AppSettings.FileWatcherConfiguration.Helper}!");
}
if (!_IsWindowsService)
{
for (int i = 0; i < int.MaxValue; i++)
{
BodyInner(cancellationToken);
Thread.Sleep(_AppSettings.FileWatcherConfiguration.MillisecondsDelay);
}
}
while (_IsWindowsService && !cancellationToken.IsCancellationRequested)
{
BodyInner(cancellationToken);
await Task.Delay(_AppSettings.FileWatcherConfiguration.MillisecondsDelay, cancellationToken);
}
}
protected override async Task ExecuteAsync(CancellationToken cancellationToken) =>
await Body(cancellationToken);
} }