Changes in file compression for windows, redone linux side because wine issues.

This commit is contained in:
cake
2025-10-31 23:47:41 +01:00
parent 5feb74c1c0
commit 6e3c60f627
3 changed files with 627 additions and 508 deletions

View File

@@ -137,7 +137,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
if (fsType == FileSystemHelper.FilesystemType.Btrfs) if (fsType == FileSystemHelper.FilesystemType.Btrfs)
{ {
StorageIsBtrfs = true; StorageIsBtrfs = true;
Logger.LogInformation("Lightless Storage is on BTRFS drive: {isNtfs}", StorageIsBtrfs); Logger.LogInformation("Lightless Storage is on BTRFS drive: {isBtrfs}", StorageIsBtrfs);
} }
Logger.LogDebug("Initializing Lightless FSW on {path}", lightlessPath); Logger.LogDebug("Initializing Lightless FSW on {path}", lightlessPath);
@@ -661,24 +661,25 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
if (ct.IsCancellationRequested) return; if (ct.IsCancellationRequested) return;
// scan new files var newFiles = allScannedFiles.Where(c => !c.Value).Select(c => c.Key).ToList();
if (allScannedFiles.Any(c => !c.Value)) foreach (var cachePath in newFiles)
{ {
Parallel.ForEach(allScannedFiles.Where(c => !c.Value).Select(c => c.Key), if (ct.IsCancellationRequested) break;
new ParallelOptions() ProcessOne(cachePath);
{ Interlocked.Increment(ref _currentFileProgress);
MaxDegreeOfParallelism = threadCount, }
CancellationToken = ct
}, (cachePath) => Logger.LogTrace("Scanner added {count} new files to db", newFiles.Count);
void ProcessOne(string? cachePath)
{ {
if (_fileDbManager == null || _ipcManager?.Penumbra == null || cachePath == null) if (_fileDbManager == null || _ipcManager?.Penumbra == null || cachePath == null)
{ {
Logger.LogTrace("Potential null in db: {isDbNull} penumbra: {isPenumbraNull} cachepath: {isPathNull}", _fileDbManager == null, _ipcManager?.Penumbra == null, cachePath == null); Logger.LogTrace("Potential null in db: {isDbNull} penumbra: {isPenumbraNull} cachepath: {isPathNull}",
_fileDbManager == null, _ipcManager?.Penumbra == null, cachePath == null);
return; return;
} }
if (ct.IsCancellationRequested) return;
if (!_ipcManager.Penumbra.APIAvailable) if (!_ipcManager.Penumbra.APIAvailable)
{ {
Logger.LogWarning("Penumbra not available"); Logger.LogWarning("Penumbra not available");
@@ -690,15 +691,14 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
var entry = _fileDbManager.CreateFileEntry(cachePath); var entry = _fileDbManager.CreateFileEntry(cachePath);
if (entry == null) _ = _fileDbManager.CreateCacheEntry(cachePath); if (entry == null) _ = _fileDbManager.CreateCacheEntry(cachePath);
} }
catch (IOException ioex)
{
Logger.LogDebug(ioex, "File busy or locked: {file}", cachePath);
}
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogWarning(ex, "Failed adding {file}", cachePath); Logger.LogWarning(ex, "Failed adding {file}", cachePath);
} }
Interlocked.Increment(ref _currentFileProgress);
});
Logger.LogTrace("Scanner added {notScanned} new files to db", allScannedFiles.Count(c => !c.Value));
} }
Logger.LogDebug("Scan complete"); Logger.LogDebug("Scan complete");

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
using System.Collections.Concurrent; using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace LightlessSync.Utils namespace LightlessSync.Utils
@@ -20,6 +22,8 @@ namespace LightlessSync.Utils
} }
private const string _mountPath = "/proc/mounts"; private const string _mountPath = "/proc/mounts";
private const int _defaultBlockSize = 4096;
private static readonly Dictionary<string, int> _blockSizeCache = new(StringComparer.OrdinalIgnoreCase);
private static readonly ConcurrentDictionary<string, FilesystemType> _filesystemTypeCache = new(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, FilesystemType> _filesystemTypeCache = new(StringComparer.OrdinalIgnoreCase);
public static FilesystemType GetFilesystemType(string filePath, bool isWine = false) public static FilesystemType GetFilesystemType(string filePath, bool isWine = false)
@@ -27,6 +31,7 @@ namespace LightlessSync.Utils
try try
{ {
string rootPath; string rootPath;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && (!IsProbablyWine() || !isWine)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && (!IsProbablyWine() || !isWine))
{ {
var info = new FileInfo(filePath); var info = new FileInfo(filePath);
@@ -49,6 +54,7 @@ namespace LightlessSync.Utils
{ {
var root = new DriveInfo(rootPath); var root = new DriveInfo(rootPath);
var format = root.DriveFormat?.ToUpperInvariant() ?? string.Empty; var format = root.DriveFormat?.ToUpperInvariant() ?? string.Empty;
detected = format switch detected = format switch
{ {
"NTFS" => FilesystemType.NTFS, "NTFS" => FilesystemType.NTFS,
@@ -62,10 +68,28 @@ namespace LightlessSync.Utils
detected = GetLinuxFilesystemType(filePath); detected = GetLinuxFilesystemType(filePath);
} }
if (isWine || IsProbablyWine())
{
switch (detected)
{
case FilesystemType.NTFS:
case FilesystemType.Unknown:
{
var linuxDetected = GetLinuxFilesystemType(filePath);
if (linuxDetected != FilesystemType.Unknown)
{
detected = linuxDetected;
}
break;
}
}
}
_filesystemTypeCache[rootPath] = detected; _filesystemTypeCache[rootPath] = detected;
return detected; return detected;
} }
catch (Exception ex) catch
{ {
return FilesystemType.Unknown; return FilesystemType.Unknown;
} }
@@ -175,7 +199,84 @@ namespace LightlessSync.Utils
} }
} }
public static int GetBlockSizeForPath(string path, ILogger? logger = null, bool isWine = false)
{
try
{
if (string.IsNullOrWhiteSpace(path))
return _defaultBlockSize;
var fi = new FileInfo(path);
if (!fi.Exists)
return _defaultBlockSize;
var root = fi.Directory?.Root.FullName.ToLowerInvariant() ?? "/";
if (_blockSizeCache.TryGetValue(root, out int cached))
return cached;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !isWine)
{
int result = GetDiskFreeSpaceW(root,
out uint sectorsPerCluster,
out uint bytesPerSector,
out _,
out _);
if (result == 0)
{
logger?.LogWarning("Failed to determine block size for {root}", root);
return _defaultBlockSize;
}
int clusterSize = (int)(sectorsPerCluster * bytesPerSector);
_blockSizeCache[root] = clusterSize;
logger?.LogTrace("NTFS cluster size for {root}: {cluster}", root, clusterSize);
return clusterSize;
}
string realPath = fi.FullName;
if (isWine && realPath.StartsWith("Z:\\", StringComparison.OrdinalIgnoreCase))
{
realPath = "/" + realPath.Substring(3).Replace('\\', '/');
}
var psi = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"stat -f -c %s '{realPath.Replace("'", "'\\''")}'\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = "/"
};
using var proc = Process.Start(psi);
string stdout = proc?.StandardOutput.ReadToEnd().Trim() ?? "";
proc?.WaitForExit();
if (int.TryParse(stdout, out int blockSize) && blockSize > 0)
{
_blockSizeCache[root] = blockSize;
logger?.LogTrace("Filesystem block size via stat for {root}: {block}", root, blockSize);
return blockSize;
}
logger?.LogTrace("stat did not return valid block size for {file}, output: {out}", fi.FullName, stdout);
_blockSizeCache[root] = _defaultBlockSize;
return _defaultBlockSize;
}
catch (Exception ex)
{
logger?.LogTrace(ex, "Error determining block size for {path}", path);
return _defaultBlockSize;
}
}
[DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)]
private static extern int GetDiskFreeSpaceW([In, MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters, out uint lpTotalNumberOfClusters);
//Extra check on //Extra check on
private static bool IsProbablyWine() => Environment.GetEnvironmentVariable("WINELOADERNOEXEC") != null || Environment.GetEnvironmentVariable("WINEDLLPATH") != null || Directory.Exists("/proc/self") && File.Exists("/proc/mounts"); public static bool IsProbablyWine() => Environment.GetEnvironmentVariable("WINELOADERNOEXEC") != null || Environment.GetEnvironmentVariable("WINEDLLPATH") != null || Directory.Exists("/proc/self") && File.Exists("/proc/mounts");
} }
} }