Cleanup some code, removed ntfs usage on cache monitor

This commit is contained in:
cake
2025-10-29 04:49:46 +01:00
parent 9a846a37d4
commit 3e626c5e47
2 changed files with 112 additions and 33 deletions

View File

@@ -429,7 +429,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
try try
{ {
return _fileCompactor.GetFileSizeOnDisk(f, StorageisNTFS); return _fileCompactor.GetFileSizeOnDisk(f);
} }
catch catch
{ {

View File

@@ -4,11 +4,8 @@ using LightlessSync.Utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Channels; using System.Threading.Channels;
using System.Threading.Tasks;
using static LightlessSync.Utils.FileSystemHelper; using static LightlessSync.Utils.FileSystemHelper;
namespace LightlessSync.FileCache; namespace LightlessSync.FileCache;
@@ -89,27 +86,21 @@ public sealed class FileCompactor : IDisposable
MassCompactRunning = false; MassCompactRunning = false;
} }
public long GetFileSizeOnDisk(FileInfo fileInfo, bool? isNTFS = null) public long GetFileSizeOnDisk(FileInfo fileInfo)
{ {
var fsType = FileSystemHelper.GetFilesystemType(fileInfo.FullName); var fsType = GetFilesystemType(fileInfo.FullName);
bool ntfs = isNTFS ?? fsType == FileSystemHelper.FilesystemType.NTFS; if (fsType != FilesystemType.Btrfs && fsType != FilesystemType.NTFS)
if (fsType != FileSystemHelper.FilesystemType.Btrfs && !ntfs)
{ {
return fileInfo.Length; return fileInfo.Length;
} }
if (ntfs && !_dalamudUtilService.IsWine) if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine)
{ {
var clusterSize = GetClusterSize(fileInfo); return GetFileSizeOnDisk(fileInfo, GetClusterSize);
if (clusterSize == -1) return fileInfo.Length;
var losize = GetCompressedFileSizeW(fileInfo.FullName, out uint hosize);
var size = (long)hosize << 32 | losize;
return ((size + clusterSize - 1) / clusterSize) * clusterSize;
} }
if (fsType == FileSystemHelper.FilesystemType.Btrfs) if (fsType == FilesystemType.Btrfs)
{ {
try try
{ {
@@ -163,6 +154,41 @@ public sealed class FileCompactor : IDisposable
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
[DllImport("libc", SetLastError = true)]
private static extern int statvfs(string path, out Statvfs buf);
[StructLayout(LayoutKind.Sequential)]
private struct Statvfs
{
public ulong f_bsize;
public ulong f_frsize;
public ulong f_blocks;
public ulong f_bfree;
public ulong f_bavail;
public ulong f_files;
public ulong f_ffree;
public ulong f_favail;
public ulong f_fsid;
public ulong f_flag;
public ulong f_namemax;
}
private static int GetLinuxBlockSize(string path)
{
try
{
int result = statvfs(path, out var buf);
if (result != 0)
return -1;
return (int)buf.f_frsize;
}
catch
{
return -1;
}
}
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out IntPtr lpBytesReturned, out IntPtr lpOverlapped); private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out IntPtr lpBytesReturned, out IntPtr lpOverlapped);
@@ -190,7 +216,7 @@ public sealed class FileCompactor : IDisposable
return; return;
} }
var fsType = FileSystemHelper.GetFilesystemType(filePath); var fsType = GetFilesystemType(filePath);
var oldSize = fi.Length; var oldSize = fi.Length;
int clusterSize = GetClusterSize(fi); int clusterSize = GetClusterSize(fi);
@@ -201,7 +227,7 @@ public sealed class FileCompactor : IDisposable
} }
// NTFS Compression. // NTFS Compression.
if (fsType == FileSystemHelper.FilesystemType.NTFS && !_dalamudUtilService.IsWine) if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine)
{ {
if (!IsWOFCompactedFile(filePath)) if (!IsWOFCompactedFile(filePath))
{ {
@@ -250,6 +276,17 @@ public sealed class FileCompactor : IDisposable
} }
} }
private static long GetFileSizeOnDisk(FileInfo fileInfo, Func<FileInfo, int> getClusterSize)
{
int clusterSize = getClusterSize(fileInfo);
if (clusterSize <= 0)
return fileInfo.Length;
uint low = GetCompressedFileSizeW(fileInfo.FullName, out uint high);
long compressed = ((long)high << 32) | low;
return ((compressed + clusterSize - 1) / clusterSize) * clusterSize;
}
private static long RunStatGetBlocks(string path) private static long RunStatGetBlocks(string path)
{ {
var psi = new ProcessStartInfo("stat", $"-c %b \"{path}\"") var psi = new ProcessStartInfo("stat", $"-c %b \"{path}\"")
@@ -280,11 +317,10 @@ public sealed class FileCompactor : IDisposable
private void DecompressFile(string path) private void DecompressFile(string path)
{ {
_logger.LogDebug("Removing compression from {file}", path); _logger.LogDebug("Removing compression from {file}", path);
var fsType = FileSystemHelper.GetFilesystemType(path); var fsType = GetFilesystemType(path);
if (fsType == null) return;
//NTFS Decompression //NTFS Decompression
if (fsType == FileSystemHelper.FilesystemType.NTFS && !_dalamudUtilService.IsWine) if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine)
{ {
try try
{ {
@@ -304,7 +340,7 @@ public sealed class FileCompactor : IDisposable
} }
//BTRFS Decompression //BTRFS Decompression
if (fsType == FileSystemHelper.FilesystemType.Btrfs) if (fsType == FilesystemType.Btrfs)
{ {
try try
{ {
@@ -360,16 +396,60 @@ public sealed class FileCompactor : IDisposable
private int GetClusterSize(FileInfo fi) private int GetClusterSize(FileInfo fi)
{ {
if (!fi.Exists) return -1; try
var root = fi.Directory?.Root.FullName.ToLower() ?? string.Empty; {
if (string.IsNullOrEmpty(root)) return -1; if (!fi.Exists)
if (_clusterSizes.TryGetValue(root, out int value)) return value; return -1;
_logger.LogDebug("Getting Cluster Size for {path}, root {root}", fi.FullName, root);
int result = GetDiskFreeSpaceW(root, out uint sectorsPerCluster, out uint bytesPerSector, out _, out _); var root = fi.Directory?.Root.FullName;
if (result == 0) return -1; if (string.IsNullOrEmpty(root))
_clusterSizes[root] = (int)(sectorsPerCluster * bytesPerSector); return -1;
_logger.LogDebug("Determined Cluster Size for root {root}: {cluster}", root, _clusterSizes[root]);
return _clusterSizes[root]; root = root.ToLowerInvariant();
if (_clusterSizes.TryGetValue(root, out int cached))
return cached;
_logger.LogDebug("Determining cluster/block size for {path} (root: {root})", fi.FullName, root);
int clusterSize;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
int result = GetDiskFreeSpaceW(
root,
out uint sectorsPerCluster,
out uint bytesPerSector,
out _,
out _);
if (result == 0)
{
_logger.LogWarning("GetDiskFreeSpaceW failed for {root}", root);
return -1;
}
clusterSize = (int)(sectorsPerCluster * bytesPerSector);
}
else
{
clusterSize = GetLinuxBlockSize(root);
if (clusterSize <= 0)
{
_logger.LogWarning("Failed to determine block size for {root}", root);
return -1;
}
}
_clusterSizes[root] = clusterSize;
_logger.LogDebug("Determined cluster/block size for {root}: {cluster} bytes", root, clusterSize);
return clusterSize;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error determining cluster size for {file}", fi.FullName);
return -1;
}
} }
public static bool UseSafeHandle(SafeHandle handle, Func<IntPtr, bool> action) public static bool UseSafeHandle(SafeHandle handle, Func<IntPtr, bool> action)
@@ -418,7 +498,6 @@ public sealed class FileCompactor : IDisposable
string output = proc.StandardOutput.ReadToEnd(); string output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(); proc.WaitForExit();
// look for "flags: compressed" in the output
if (output.Contains("flags: compressed", StringComparison.OrdinalIgnoreCase)) if (output.Contains("flags: compressed", StringComparison.OrdinalIgnoreCase))
{ {
return true; return true;