Warning cleansing process
This commit is contained in:
@@ -85,7 +85,7 @@ public sealed partial class FileCompactor : IDisposable
|
||||
int workerId = i;
|
||||
|
||||
_workers.Add(Task.Factory.StartNew(
|
||||
() => ProcessQueueWorkerAsync(_compactionCts.Token, workerId),
|
||||
() => ProcessQueueWorkerAsync(workerId, _compactionCts.Token),
|
||||
_compactionCts.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default).Unwrap());
|
||||
@@ -120,7 +120,8 @@ public sealed partial class FileCompactor : IDisposable
|
||||
var folder = _lightlessConfigService.Current.CacheFolder;
|
||||
if (string.IsNullOrWhiteSpace(folder) || !Directory.Exists(folder))
|
||||
{
|
||||
_logger.LogWarning("Filecompacator couldnt find your Cache folder: {folder}", folder);
|
||||
if (_logger.IsEnabled(LogLevel.Warning))
|
||||
_logger.LogWarning("Filecompacator couldnt find your Cache folder: {folder}", folder);
|
||||
Progress = "0/0";
|
||||
return;
|
||||
}
|
||||
@@ -281,12 +282,15 @@ public sealed partial class FileCompactor : IDisposable
|
||||
return (flowControl: false, value: blocks * 512L);
|
||||
}
|
||||
|
||||
_logger.LogDebug("Btrfs size probe failed for {linux} (exit {code}). stdout='{so}' stderr='{se}'. Falling back to Length.", linuxPath, res.code, outTrim, (res.se ?? "").Trim());
|
||||
if (_logger.IsEnabled(LogLevel.Debug))
|
||||
_logger.LogDebug("Btrfs size probe failed for {linux} (exit {code}). stdout='{so}' stderr='{se}'. Falling back to Length.", linuxPath, res.code, outTrim, (res.se ?? "").Trim());
|
||||
|
||||
return (flowControl: false, value: fileInfo.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed Btrfs size probe for {file}, using Length", fileInfo.FullName);
|
||||
if (_logger.IsEnabled(LogLevel.Debug))
|
||||
_logger.LogDebug(ex, "Failed Btrfs size probe for {file}, using Length", fileInfo.FullName);
|
||||
return (flowControl: true, value: fileInfo.Length);
|
||||
}
|
||||
}
|
||||
@@ -307,7 +311,8 @@ public sealed partial class FileCompactor : IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed stat size for {file}, fallback to Length", fileInfo.FullName);
|
||||
if (_logger.IsEnabled(LogLevel.Debug))
|
||||
_logger.LogDebug(ex, "Failed stat size for {file}, fallback to Length", fileInfo.FullName);
|
||||
}
|
||||
|
||||
return (flowControl: true, value: default);
|
||||
@@ -323,7 +328,8 @@ public sealed partial class FileCompactor : IDisposable
|
||||
var fi = new FileInfo(filePath);
|
||||
if (!fi.Exists)
|
||||
{
|
||||
_logger.LogTrace("[W{worker}] Skip compaction: missing {file}", workerId, filePath);
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
_logger.LogTrace("[W{worker}] Skip compaction: missing {file}", workerId, filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -338,7 +344,8 @@ public sealed partial class FileCompactor : IDisposable
|
||||
|
||||
if (oldSize < minSizeBytes)
|
||||
{
|
||||
_logger.LogTrace("[W{worker}] Skip compaction: {file} ({size} B) < threshold ({th} B)", workerId, filePath, oldSize, minSizeBytes);
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
_logger.LogTrace("[W{worker}] Skip compaction: {file} ({size} B) < threshold ({th} B)", workerId, filePath, oldSize, minSizeBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -358,7 +365,8 @@ public sealed partial class FileCompactor : IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogTrace("[W{worker}] Already NTFS-compressed with XPRESS8K: {file}", workerId, filePath);
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
_logger.LogTrace("[W{worker}] Already NTFS-compressed with XPRESS8K: {file}", workerId, filePath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -379,12 +387,14 @@ public sealed partial class FileCompactor : IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogTrace("[W{worker}] Already Btrfs-compressed with clzo: {file}", workerId, filePath);
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
_logger.LogTrace("[W{worker}] Already Btrfs-compressed with clzo: {file}", workerId, filePath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogTrace("[W{worker}] Skip compact: unsupported FS for {file}", workerId, filePath);
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
_logger.LogTrace("[W{worker}] Skip compact: unsupported FS for {file}", workerId, filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1045,10 +1055,10 @@ public sealed partial class FileCompactor : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the queue with, meant for a worker/thread
|
||||
/// Process the queue, meant for a worker/thread
|
||||
/// </summary>
|
||||
/// <param name="token">Cancellation token for the worker whenever it needs to be stopped</param>
|
||||
private async Task ProcessQueueWorkerAsync(CancellationToken token, int workerId)
|
||||
private async Task ProcessQueueWorkerAsync(int workerId, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1139,17 +1149,18 @@ public sealed partial class FileCompactor : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_isWindows)
|
||||
{
|
||||
using var _ = new FileStream(winePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var _ = new FileStream(linuxPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
}
|
||||
var pathToOpen = _isWindows ? winePath : linuxPath;
|
||||
|
||||
if (string.IsNullOrEmpty(pathToOpen) || !File.Exists(pathToOpen))
|
||||
return false;
|
||||
|
||||
using var _ = new FileStream(pathToOpen, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return true;
|
||||
}
|
||||
catch { return false; }
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -227,7 +227,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddSingleton<ConfigurationMigrator>();
|
||||
collection.AddSingleton<ConfigurationSaveService>();
|
||||
collection.AddSingleton<HubFactory>();
|
||||
collection.AddSingleton(s => new BroadcastScannerService( s.GetRequiredService<ILogger<BroadcastScannerService>>(), clientState, objectTable, framework, s.GetRequiredService<BroadcastService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<NameplateHandler>(), s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<LightlessConfigService>()));
|
||||
collection.AddSingleton(s => new BroadcastScannerService(s.GetRequiredService<ILogger<BroadcastScannerService>>(), objectTable, framework, s.GetRequiredService<BroadcastService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<NameplateHandler>()));
|
||||
|
||||
|
||||
// add scoped services
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Plugin.Services;
|
||||
using LightlessSync.API.Dto.User;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace LightlessSync.Services;
|
||||
|
||||
public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDisposable
|
||||
public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
||||
{
|
||||
private readonly ILogger<BroadcastScannerService> _logger;
|
||||
private readonly IObjectTable _objectTable;
|
||||
@@ -17,20 +16,19 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
private readonly BroadcastService _broadcastService;
|
||||
private readonly NameplateHandler _nameplateHandler;
|
||||
|
||||
private readonly ConcurrentDictionary<string, BroadcastEntry> _broadcastCache = new();
|
||||
private readonly ConcurrentDictionary<string, BroadcastEntry> _broadcastCache = new(StringComparer.Ordinal);
|
||||
private readonly Queue<string> _lookupQueue = new();
|
||||
private readonly HashSet<string> _lookupQueuedCids = new();
|
||||
private readonly HashSet<string> _syncshellCids = new();
|
||||
private readonly HashSet<string> _lookupQueuedCids = [];
|
||||
private readonly HashSet<string> _syncshellCids = [];
|
||||
|
||||
private static readonly TimeSpan MaxAllowedTtl = TimeSpan.FromMinutes(4);
|
||||
private static readonly TimeSpan RetryDelay = TimeSpan.FromMinutes(1);
|
||||
|
||||
private readonly CancellationTokenSource _cleanupCts = new();
|
||||
private Task? _cleanupTask;
|
||||
private readonly Task? _cleanupTask;
|
||||
|
||||
private readonly int _checkEveryFrames = 20;
|
||||
private int _frameCounter = 0;
|
||||
private int _lookupsThisFrame = 0;
|
||||
private const int MaxLookupsPerFrame = 30;
|
||||
private const int MaxQueueSize = 100;
|
||||
|
||||
@@ -40,14 +38,11 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID);
|
||||
|
||||
public BroadcastScannerService(ILogger<BroadcastScannerService> logger,
|
||||
IClientState clientState,
|
||||
IObjectTable objectTable,
|
||||
IFramework framework,
|
||||
BroadcastService broadcastService,
|
||||
LightlessMediator mediator,
|
||||
NameplateHandler nameplateHandler,
|
||||
DalamudUtilService dalamudUtil,
|
||||
LightlessConfigService configService) : base(logger, mediator)
|
||||
NameplateHandler nameplateHandler) : base(logger, mediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_objectTable = objectTable;
|
||||
@@ -69,7 +64,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
public void Update()
|
||||
{
|
||||
_frameCounter++;
|
||||
_lookupsThisFrame = 0;
|
||||
var lookupsThisFrame = 0;
|
||||
|
||||
if (!_broadcastService.IsBroadcasting)
|
||||
return;
|
||||
@@ -91,12 +86,12 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
if (_frameCounter % _checkEveryFrames == 0 && _lookupQueue.Count > 0)
|
||||
{
|
||||
var cidsToLookup = new List<string>();
|
||||
while (_lookupQueue.Count > 0 && _lookupsThisFrame < MaxLookupsPerFrame)
|
||||
while (_lookupQueue.Count > 0 && lookupsThisFrame < MaxLookupsPerFrame)
|
||||
{
|
||||
var cid = _lookupQueue.Dequeue();
|
||||
_lookupQueuedCids.Remove(cid);
|
||||
cidsToLookup.Add(cid);
|
||||
_lookupsThisFrame++;
|
||||
lookupsThisFrame++;
|
||||
}
|
||||
|
||||
if (cidsToLookup.Count > 0 && !_batchRunning)
|
||||
@@ -156,7 +151,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
var newSet = _broadcastCache
|
||||
.Where(e => e.Value.IsBroadcasting && e.Value.ExpiryTime > now && !string.IsNullOrEmpty(e.Value.GID))
|
||||
.Select(e => e.Key)
|
||||
.ToHashSet();
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
|
||||
if (!_syncshellCids.SetEquals(newSet))
|
||||
{
|
||||
@@ -172,7 +167,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
return _broadcastCache
|
||||
return [.. _broadcastCache
|
||||
.Where(e => e.Value.IsBroadcasting && e.Value.ExpiryTime > now && !string.IsNullOrEmpty(e.Value.GID))
|
||||
.Select(e => new BroadcastStatusInfoDto
|
||||
{
|
||||
@@ -180,8 +175,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
IsBroadcasting = true,
|
||||
TTL = e.Value.ExpiryTime - now,
|
||||
GID = e.Value.GID
|
||||
})
|
||||
.ToList();
|
||||
})];
|
||||
}
|
||||
|
||||
private async Task ExpiredBroadcastCleanupLoop()
|
||||
@@ -192,7 +186,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(10), token);
|
||||
await Task.Delay(TimeSpan.FromSeconds(10), token).ConfigureAwait(false);
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var (cid, entry) in _broadcastCache.ToArray())
|
||||
@@ -202,7 +196,10 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// No action needed when cancelled
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Broadcast cleanup loop crashed");
|
||||
@@ -235,8 +232,14 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
_framework.Update -= OnFrameworkUpdate;
|
||||
if (_cleanupTask != null)
|
||||
{
|
||||
_cleanupTask?.Wait(100, _cleanupCts.Token);
|
||||
}
|
||||
|
||||
_cleanupCts.Cancel();
|
||||
_cleanupTask?.Wait(100);
|
||||
_cleanupCts.Dispose();
|
||||
|
||||
_nameplateHandler.Uninit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
private Vector4 textColor;
|
||||
private Vector4 glowColor;
|
||||
|
||||
private record VanityState(bool TextEnabled, bool GlowEnabled, Vector4 TextColor, Vector4 GlowColor);
|
||||
private VanityState _savedVanity;
|
||||
private sealed record VanityState(bool TextEnabled, bool GlowEnabled, Vector4 TextColor, Vector4 GlowColor);
|
||||
private VanityState? _savedVanity;
|
||||
|
||||
public EditProfileUi(ILogger<EditProfileUi> logger, LightlessMediator mediator,
|
||||
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
||||
@@ -189,25 +189,28 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
if (!success) return;
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var fileContent = File.ReadAllBytes(file);
|
||||
using MemoryStream ms = new(fileContent);
|
||||
var format = await Image.DetectFormatAsync(ms).ConfigureAwait(false);
|
||||
if (!format.FileExtensions.Contains("png", StringComparer.OrdinalIgnoreCase))
|
||||
var fileContent = await File.ReadAllBytesAsync(file).ConfigureAwait(false);
|
||||
MemoryStream ms = new(fileContent);
|
||||
await using (ms.ConfigureAwait(false))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
using var image = Image.Load<Rgba32>(fileContent);
|
||||
var format = await Image.DetectFormatAsync(ms).ConfigureAwait(false);
|
||||
if (!format.FileExtensions.Contains("png", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
using var image = Image.Load<Rgba32>(fileContent);
|
||||
|
||||
if (image.Width > 256 || image.Height > 256 || (fileContent.Length > 250 * 1024))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
if (image.Width > 256 || image.Height > 256 || (fileContent.Length > 250 * 1024))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_showFileDialogError = false;
|
||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), BannerPictureBase64: null, Description: null, Tags: null))
|
||||
.ConfigureAwait(false);
|
||||
_showFileDialogError = false;
|
||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), BannerPictureBase64: null, Description: null, Tags: null))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ public static class VariousExtensions
|
||||
.OrderBy(g => string.IsNullOrEmpty(g.Hash) ? g.FileSwapPath : g.Hash, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
var newTail = newFileReplacements.Where(g => g.GamePaths.Any(p => p.Contains("/tail/", StringComparison.OrdinalIgnoreCase)))
|
||||
.OrderBy(g => string.IsNullOrEmpty(g.Hash) ? g.FileSwapPath : g.Hash, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
var existingTransients = existingFileReplacements.Where(g => g.GamePaths.Any(g => !g.EndsWith("mdl") && !g.EndsWith("tex") && !g.EndsWith("mtrl")))
|
||||
var existingTransients = existingFileReplacements.Where(g => g.GamePaths.Any(g => !g.EndsWith("mdl", StringComparison.Ordinal) && !g.EndsWith("tex", StringComparison.Ordinal) && !g.EndsWith("mtrl", StringComparison.Ordinal)))
|
||||
.OrderBy(g => string.IsNullOrEmpty(g.Hash) ? g.FileSwapPath : g.Hash, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
var newTransients = newFileReplacements.Where(g => g.GamePaths.Any(g => !g.EndsWith("mdl") && !g.EndsWith("tex") && !g.EndsWith("mtrl")))
|
||||
var newTransients = newFileReplacements.Where(g => g.GamePaths.Any(g => !g.EndsWith("mdl", StringComparison.Ordinal) && !g.EndsWith("tex", StringComparison.Ordinal) && !g.EndsWith("mtrl", StringComparison.Ordinal)))
|
||||
.OrderBy(g => string.IsNullOrEmpty(g.Hash) ? g.FileSwapPath : g.Hash, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
logger.LogTrace("[BASE-{appbase}] ExistingFace: {of}, NewFace: {fc}; ExistingHair: {eh}, NewHair: {nh}; ExistingTail: {et}, NewTail: {nt}; ExistingTransient: {etr}, NewTransient: {ntr}", applicationBase,
|
||||
|
||||
Reference in New Issue
Block a user