diff --git a/LightlessSync/Services/Mediator/Messages.cs b/LightlessSync/Services/Mediator/Messages.cs index 08e47da..7e8e220 100644 --- a/LightlessSync/Services/Mediator/Messages.cs +++ b/LightlessSync/Services/Mediator/Messages.cs @@ -73,7 +73,7 @@ public record HubClosedMessage(Exception? Exception) : SameThreadMessage; public record ResumeScanMessage(string Source) : MessageBase; public record FileCacheInitializedMessage : MessageBase; public record DownloadReadyMessage(Guid RequestId) : MessageBase; -public record DownloadStartedMessage(GameObjectHandler DownloadId, Dictionary DownloadStatus) : MessageBase; +public record DownloadStartedMessage(GameObjectHandler DownloadId, IReadOnlyDictionary DownloadStatus) : MessageBase; public record DownloadFinishedMessage(GameObjectHandler DownloadId) : MessageBase; public record UiToggleMessage(Type UiType) : MessageBase; public record PlayerUploadingMessage(GameObjectHandler Handler, bool IsUploading) : MessageBase; @@ -139,4 +139,4 @@ public record OpenUserProfileMessage(UserData User) : MessageBase; public record LocationSharingMessage(UserData User, LocationInfo LocationInfo, DateTimeOffset ExpireAt) : MessageBase; public record MapChangedMessage(uint MapId) : MessageBase; #pragma warning restore S2094 -#pragma warning restore MA0048 // File name must match type name \ No newline at end of file +#pragma warning restore MA0048 // File name must match type name diff --git a/LightlessSync/UI/CompactUI.cs b/LightlessSync/UI/CompactUI.cs index 089f104..cabef7d 100644 --- a/LightlessSync/UI/CompactUI.cs +++ b/LightlessSync/UI/CompactUI.cs @@ -39,7 +39,7 @@ public class CompactUi : WindowMediatorSubscriberBase private readonly LightlessConfigService _configService; private readonly LightlessMediator _lightlessMediator; private readonly PairLedger _pairLedger; - private readonly ConcurrentDictionary> _currentDownloads = new(); + private readonly ConcurrentDictionary> _currentDownloads = new(); private readonly DrawEntityFactory _drawEntityFactory; private readonly FileUploadManager _fileTransferManager; private readonly PlayerPerformanceConfigService _playerPerformanceConfig; diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 0697333..06c7213 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -17,7 +17,7 @@ namespace LightlessSync.UI; public class DownloadUi : WindowMediatorSubscriberBase { private readonly LightlessConfigService _configService; - private readonly ConcurrentDictionary> _currentDownloads = new(); + private readonly ConcurrentDictionary> _currentDownloads = new(); private readonly DalamudUtilService _dalamudUtilService; private readonly FileUploadManager _fileTransferManager; private readonly UiSharedService _uiShared; @@ -164,7 +164,7 @@ public class DownloadUi : WindowMediatorSubscriberBase const float rounding = 6f; var shadowOffset = new Vector2(2, 2); - List>> transfers; + List>> transfers; try { transfers = _currentDownloads.ToList(); diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index 1e5e055..cf64df1 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -51,7 +51,7 @@ public class SettingsUi : WindowMediatorSubscriberBase private readonly CacheMonitor _cacheMonitor; private readonly LightlessConfigService _configService; private readonly UiThemeConfigService _themeConfigService; - private readonly ConcurrentDictionary> _currentDownloads = new(); + private readonly ConcurrentDictionary> _currentDownloads = new(); private readonly DalamudUtilService _dalamudUtilService; private readonly HttpClient _httpClient; private readonly FileCacheManager _fileCacheManager; diff --git a/LightlessSync/WebAPI/Files/FileDownloadManager.cs b/LightlessSync/WebAPI/Files/FileDownloadManager.cs index c0f4fc1..e8b0af5 100644 --- a/LightlessSync/WebAPI/Files/FileDownloadManager.cs +++ b/LightlessSync/WebAPI/Files/FileDownloadManager.cs @@ -18,8 +18,7 @@ namespace LightlessSync.WebAPI.Files; public partial class FileDownloadManager : DisposableMediatorSubscriberBase { - private readonly Dictionary _downloadStatus; - private readonly object _downloadStatusLock = new(); + private readonly ConcurrentDictionary _downloadStatus; private readonly FileCompactor _fileCompactor; private readonly FileCacheManager _fileDbManager; @@ -46,7 +45,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase ModelDecimationService modelDecimationService, TextureMetadataHelper textureMetadataHelper) : base(logger, mediator) { - _downloadStatus = new Dictionary(StringComparer.Ordinal); + _downloadStatus = new ConcurrentDictionary(StringComparer.Ordinal); _orchestrator = orchestrator; _fileDbManager = fileCacheManager; _fileCompactor = fileCompactor; @@ -86,10 +85,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase public void ClearDownload() { CurrentDownloads.Clear(); - lock (_downloadStatusLock) - { - _downloadStatus.Clear(); - } + _downloadStatus.Clear(); CurrentOwnerToken = null; } @@ -156,29 +152,20 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase private void SetStatus(string key, DownloadStatus status) { - lock (_downloadStatusLock) - { - if (_downloadStatus.TryGetValue(key, out var st)) - st.DownloadStatus = status; - } + if (_downloadStatus.TryGetValue(key, out var st)) + st.DownloadStatus = status; } private void AddTransferredBytes(string key, long delta) { - lock (_downloadStatusLock) - { - if (_downloadStatus.TryGetValue(key, out var st)) - st.TransferredBytes += delta; - } + if (_downloadStatus.TryGetValue(key, out var st)) + st.AddTransferredBytes(delta); } private void MarkTransferredFiles(string key, int files) { - lock (_downloadStatusLock) - { - if (_downloadStatus.TryGetValue(key, out var st)) - st.TransferredFiles = files; - } + if (_downloadStatus.TryGetValue(key, out var st)) + st.SetTransferredFiles(files); } private static byte MungeByte(int byteOrEof) @@ -712,34 +699,31 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase .ToArray(); // init statuses - lock (_downloadStatusLock) + _downloadStatus.Clear(); + + // direct downloads and batch downloads tracked separately + foreach (var d in directDownloads) { - _downloadStatus.Clear(); - - // direct downloads and batch downloads tracked separately - foreach (var d in directDownloads) + _downloadStatus[d.DirectDownloadUrl!] = new FileDownloadStatus { - _downloadStatus[d.DirectDownloadUrl!] = new FileDownloadStatus - { - DownloadStatus = DownloadStatus.WaitingForSlot, - TotalBytes = d.Total, - TotalFiles = 1, - TransferredBytes = 0, - TransferredFiles = 0 - }; - } + DownloadStatus = DownloadStatus.WaitingForSlot, + TotalBytes = d.Total, + TotalFiles = 1, + TransferredBytes = 0, + TransferredFiles = 0 + }; + } - foreach (var chunk in batchChunks) + foreach (var chunk in batchChunks) + { + _downloadStatus[chunk.StatusKey] = new FileDownloadStatus { - _downloadStatus[chunk.StatusKey] = new FileDownloadStatus - { - DownloadStatus = DownloadStatus.WaitingForQueue, - TotalBytes = chunk.Items.Sum(x => x.Total), - TotalFiles = 1, - TransferredBytes = 0, - TransferredFiles = 0 - }; - } + DownloadStatus = DownloadStatus.WaitingForQueue, + TotalBytes = chunk.Items.Sum(x => x.Total), + TotalFiles = 1, + TransferredBytes = 0, + TransferredFiles = 0 + }; } if (directDownloads.Count > 0 || batchChunks.Length > 0) diff --git a/LightlessSync/WebAPI/Files/Models/FileDownloadStatus.cs b/LightlessSync/WebAPI/Files/Models/FileDownloadStatus.cs index 9340278..aa0aed0 100644 --- a/LightlessSync/WebAPI/Files/Models/FileDownloadStatus.cs +++ b/LightlessSync/WebAPI/Files/Models/FileDownloadStatus.cs @@ -1,10 +1,46 @@ -namespace LightlessSync.WebAPI.Files.Models; +using System.Threading; + +namespace LightlessSync.WebAPI.Files.Models; public class FileDownloadStatus { - public DownloadStatus DownloadStatus { get; set; } - public long TotalBytes { get; set; } - public int TotalFiles { get; set; } - public long TransferredBytes { get; set; } - public int TransferredFiles { get; set; } -} \ No newline at end of file + private int _downloadStatus; + private long _totalBytes; + private int _totalFiles; + private long _transferredBytes; + private int _transferredFiles; + + public DownloadStatus DownloadStatus + { + get => (DownloadStatus)Volatile.Read(ref _downloadStatus); + set => Volatile.Write(ref _downloadStatus, (int)value); + } + + public long TotalBytes + { + get => Interlocked.Read(ref _totalBytes); + set => Interlocked.Exchange(ref _totalBytes, value); + } + + public int TotalFiles + { + get => Volatile.Read(ref _totalFiles); + set => Volatile.Write(ref _totalFiles, value); + } + + public long TransferredBytes + { + get => Interlocked.Read(ref _transferredBytes); + set => Interlocked.Exchange(ref _transferredBytes, value); + } + + public int TransferredFiles + { + get => Volatile.Read(ref _transferredFiles); + set => Volatile.Write(ref _transferredFiles, value); + } + + public void AddTransferredBytes(long delta) => Interlocked.Add(ref _transferredBytes, delta); + + public void SetTransferredFiles(int files) => Volatile.Write(ref _transferredFiles, files); +}