mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add StatusReportService
This commit is contained in:
parent
e5291eb06a
commit
2f9fbdb818
10 changed files with 309 additions and 74 deletions
|
@ -5,17 +5,16 @@ namespace LibHac.Fs
|
|||
[StructLayout(LayoutKind.Sequential, Size = 0x80)]
|
||||
public struct MemoryReportInfo
|
||||
{
|
||||
long PooledBufferFreeSizePeak;
|
||||
long PooledBufferRetriedCount;
|
||||
long PooledBufferReduceAllocationCount;
|
||||
long BufferManagerFreeSizePeak;
|
||||
long BufferManagerRetiredCount;
|
||||
long ExpHeapFreeSizePeak;
|
||||
long BufferPoolFreeSizePeak;
|
||||
long PatrolAllocateSuccessCount;
|
||||
long PatrolAllocateFailureCount;
|
||||
long BufferManagerTotalAllocatableSizePeak;
|
||||
long BufferPoolAllocateSizeMax;
|
||||
};
|
||||
|
||||
public long PooledBufferFreeSizePeak;
|
||||
public long PooledBufferRetriedCount;
|
||||
public long PooledBufferReduceAllocationCount;
|
||||
public long BufferManagerFreeSizePeak;
|
||||
public long BufferManagerRetriedCount;
|
||||
public long ExpHeapFreeSizePeak;
|
||||
public long BufferPoolFreeSizePeak;
|
||||
public long PatrolAllocateSuccessCount;
|
||||
public long PatrolAllocateFailureCount;
|
||||
public long BufferManagerTotalAllocatableSizePeak;
|
||||
public long BufferPoolAllocateSizeMax;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,4 +9,6 @@ namespace LibHac.FsSrv
|
|||
|
||||
public delegate Result SaveTransferCmacGenerator(Span<byte> mac, ReadOnlySpan<byte> data,
|
||||
SaveDataTransferCryptoConfiguration.KeyIndex index, int keyGeneration);
|
||||
|
||||
public delegate Result PatrolAllocateCountGetter(out long successCount, out long failureCount);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace LibHac.FsSrv
|
|||
public NcaFileSystemServiceImpl NcaFileSystemService { get; set; }
|
||||
public SaveDataFileSystemServiceImpl SaveDataFileSystemService { get; set; }
|
||||
public TimeServiceImpl TimeService { get; set; }
|
||||
public StatusReportServiceImpl StatusReportService { get; set; }
|
||||
public ProgramRegistryServiceImpl ProgramRegistryService { get; set; }
|
||||
public AccessLogServiceImpl AccessLogService { get; set; }
|
||||
}
|
||||
|
|
|
@ -28,6 +28,65 @@ namespace LibHac.FsSrv
|
|||
CurrentProcess = ulong.MaxValue;
|
||||
}
|
||||
|
||||
private Result GetProgramInfo(out ProgramInfo programInfo)
|
||||
{
|
||||
return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess);
|
||||
}
|
||||
|
||||
private Result GetNcaFileSystemService(out NcaFileSystemService ncaFsService)
|
||||
{
|
||||
if (NcaFsService is null)
|
||||
{
|
||||
ncaFsService = null;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
ncaFsService = NcaFsService.Target;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService)
|
||||
{
|
||||
if (SaveFsService is null)
|
||||
{
|
||||
saveFsService = null;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
saveFsService = SaveFsService.Target;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private BaseStorageService GetBaseStorageService()
|
||||
{
|
||||
return new BaseStorageService(FsProxyCore.Config.BaseStorageService, CurrentProcess);
|
||||
}
|
||||
|
||||
private BaseFileSystemService GetBaseFileSystemService()
|
||||
{
|
||||
return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess);
|
||||
}
|
||||
|
||||
private TimeService GetTimeService()
|
||||
{
|
||||
return new TimeService(FsProxyCore.Config.TimeService, CurrentProcess);
|
||||
}
|
||||
|
||||
private StatusReportService GetStatusReportService()
|
||||
{
|
||||
return new StatusReportService(FsProxyCore.Config.StatusReportService);
|
||||
}
|
||||
|
||||
private ProgramIndexRegistryService GetProgramIndexRegistryService()
|
||||
{
|
||||
return new ProgramIndexRegistryService(FsProxyCore.Config.ProgramRegistryService, CurrentProcess);
|
||||
}
|
||||
|
||||
private AccessLogService GetAccessLogService()
|
||||
{
|
||||
return new AccessLogService(FsProxyCore.Config.AccessLogService, CurrentProcess);
|
||||
}
|
||||
|
||||
public Result OpenFileSystemWithId(out ReferenceCountedDisposable<IFileSystemSf> fileSystem, in FspPath path,
|
||||
ulong id, FileSystemProxyType fsType)
|
||||
{
|
||||
|
@ -863,7 +922,7 @@ namespace LibHac.FsSrv
|
|||
|
||||
public Result GetAndClearErrorInfo(out FileSystemProxyErrorInfo errorInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return GetStatusReportService().GetAndClearFileSystemProxyErrorInfo(out errorInfo);
|
||||
}
|
||||
|
||||
public Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfoBuffer, int programCount)
|
||||
|
@ -984,14 +1043,14 @@ namespace LibHac.FsSrv
|
|||
return ncaFsService.OpenRegisteredUpdatePartition(out fileSystem);
|
||||
}
|
||||
|
||||
public Result GetAndClearMemoryReportInfo(out MemoryReportInfo report)
|
||||
public Result GetAndClearMemoryReportInfo(out MemoryReportInfo reportInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return GetStatusReportService().GetAndClearMemoryReportInfo(out reportInfo);
|
||||
}
|
||||
|
||||
public Result GetFsStackUsage(out uint stackUsage, FsStackUsageThreadType threadType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return GetStatusReportService().GetFsStackUsage(out stackUsage, threadType);
|
||||
}
|
||||
|
||||
public Result OverrideSaveDataTransferTokenSignVerificationKey(InBuffer key)
|
||||
|
@ -1058,59 +1117,5 @@ namespace LibHac.FsSrv
|
|||
{
|
||||
return GetBaseFileSystemService().OpenBisWiper(out bisWiper, transferMemoryHandle, transferMemorySize);
|
||||
}
|
||||
|
||||
private Result GetProgramInfo(out ProgramInfo programInfo)
|
||||
{
|
||||
return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess);
|
||||
}
|
||||
|
||||
private Result GetNcaFileSystemService(out NcaFileSystemService ncaFsService)
|
||||
{
|
||||
if (NcaFsService is null)
|
||||
{
|
||||
ncaFsService = null;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
ncaFsService = NcaFsService.Target;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService)
|
||||
{
|
||||
if (SaveFsService is null)
|
||||
{
|
||||
saveFsService = null;
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
}
|
||||
|
||||
saveFsService = SaveFsService.Target;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private BaseStorageService GetBaseStorageService()
|
||||
{
|
||||
return new BaseStorageService(FsProxyCore.Config.BaseStorageService, CurrentProcess);
|
||||
}
|
||||
|
||||
private BaseFileSystemService GetBaseFileSystemService()
|
||||
{
|
||||
return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess);
|
||||
}
|
||||
|
||||
private TimeService GetTimeService()
|
||||
{
|
||||
return new TimeService(FsProxyCore.Config.TimeService, CurrentProcess);
|
||||
}
|
||||
|
||||
private ProgramIndexRegistryService GetProgramIndexRegistryService()
|
||||
{
|
||||
return new ProgramIndexRegistryService(FsProxyCore.Config.ProgramRegistryService, CurrentProcess);
|
||||
}
|
||||
|
||||
private AccessLogService GetAccessLogService()
|
||||
{
|
||||
return new AccessLogService(FsProxyCore.Config.AccessLogService, CurrentProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.FsSrv.Creators;
|
||||
using LibHac.FsSrv.Impl;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage;
|
||||
using LibHac.Sm;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
|
@ -17,6 +19,7 @@ namespace LibHac.FsSrv
|
|||
private const ulong SpeedEmulationProgramIdMaximum = 0x100000000001FFF;
|
||||
|
||||
private FileSystemProxyCoreImpl FsProxyCore { get; }
|
||||
public StorageService Storage { get; }
|
||||
|
||||
/// <summary>The client instance to be used for internal operations like save indexer access.</summary>
|
||||
public HorizonClient Hos { get; }
|
||||
|
@ -48,6 +51,8 @@ namespace LibHac.FsSrv
|
|||
|
||||
Hos = horizonClient;
|
||||
|
||||
Storage = new StorageService(this);
|
||||
|
||||
IsDebugMode = false;
|
||||
|
||||
Timer = config.TimeSpanGenerator ?? new StopWatchTimeSpanGenerator();
|
||||
|
@ -155,6 +160,19 @@ namespace LibHac.FsSrv
|
|||
|
||||
var saveFsService = new SaveDataFileSystemServiceImpl(in saveFsServiceConfig);
|
||||
|
||||
var statusReportServiceConfig = new StatusReportServiceImpl.Configuration();
|
||||
statusReportServiceConfig.NcaFsServiceImpl = ncaFsService;
|
||||
statusReportServiceConfig.SaveFsServiceImpl = saveFsService;
|
||||
statusReportServiceConfig.BufferManagerMemoryReport = null;
|
||||
statusReportServiceConfig.ExpHeapMemoryReport = null;
|
||||
statusReportServiceConfig.BufferPoolMemoryReport = null;
|
||||
statusReportServiceConfig.GetPatrolAllocateCounts = null;
|
||||
statusReportServiceConfig.MainThreadStackUsageReporter = new DummyStackUsageReporter();
|
||||
statusReportServiceConfig.IpcWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
|
||||
statusReportServiceConfig.PipeLineWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
|
||||
|
||||
var statusReportService = new StatusReportServiceImpl(in statusReportServiceConfig);
|
||||
|
||||
var accessLogServiceConfig = new AccessLogServiceImpl.Configuration();
|
||||
accessLogServiceConfig.MinimumProgramIdForSdCardLog = 0x0100000000003000;
|
||||
accessLogServiceConfig.HorizonClient = Hos;
|
||||
|
@ -169,6 +187,7 @@ namespace LibHac.FsSrv
|
|||
NcaFileSystemService = ncaFsService,
|
||||
SaveDataFileSystemService = saveFsService,
|
||||
TimeService = timeService,
|
||||
StatusReportService = statusReportService,
|
||||
ProgramRegistryService = programRegistryService,
|
||||
AccessLogService = accessLogService
|
||||
};
|
||||
|
@ -238,6 +257,11 @@ namespace LibHac.FsSrv
|
|||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
private class DummyStackUsageReporter : IStackUsageReporter
|
||||
{
|
||||
public uint GetStackUsage() => 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -268,6 +292,31 @@ namespace LibHac.FsSrv
|
|||
public ITimeSpanGenerator TimeSpanGenerator { get; set; }
|
||||
}
|
||||
|
||||
public class StorageService
|
||||
{
|
||||
internal FileSystemServer Fs;
|
||||
private IStorageDeviceManagerFactory _factory;
|
||||
|
||||
internal StorageService(FileSystemServer parentServer)
|
||||
{
|
||||
Fs = parentServer;
|
||||
}
|
||||
|
||||
public void SetStorageDeviceManagerFactory(IStorageDeviceManagerFactory factory)
|
||||
{
|
||||
Assert.NotNull(factory);
|
||||
Assert.Null(_factory);
|
||||
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
public IStorageDeviceManagerFactory GetStorageDeviceManagerFactory()
|
||||
{
|
||||
Assert.NotNull(_factory);
|
||||
return _factory;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions in the nn::fssrv::detail namespace use this struct.
|
||||
// Possibly move this to the main class if the separation doesn't seem necessary.
|
||||
internal struct FileSystemServerImpl
|
||||
|
|
7
src/LibHac/FsSrv/IStackUsageReporter.cs
Normal file
7
src/LibHac/FsSrv/IStackUsageReporter.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace LibHac.FsSrv
|
||||
{
|
||||
public interface IStackUsageReporter
|
||||
{
|
||||
uint GetStackUsage();
|
||||
}
|
||||
}
|
11
src/LibHac/FsSrv/MemoryReport.cs
Normal file
11
src/LibHac/FsSrv/MemoryReport.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace LibHac.FsSrv
|
||||
{
|
||||
public abstract class MemoryReport
|
||||
{
|
||||
public abstract long GetFreeSizePeak();
|
||||
public abstract long GetTotalAllocatableSizePeak();
|
||||
public abstract long GetRetriedCount();
|
||||
public abstract long GetAllocateSizeMax();
|
||||
public abstract void Clear();
|
||||
}
|
||||
}
|
|
@ -612,9 +612,23 @@ namespace LibHac.FsSrv
|
|||
return programId;
|
||||
}
|
||||
|
||||
public void ResetTemporaryStorageIndexer()
|
||||
public Result GetSaveDataIndexCount(out int count)
|
||||
{
|
||||
_config.SaveIndexerManager.ResetIndexer(SaveDataSpaceId.Temporary);
|
||||
Unsafe.SkipInit(out count);
|
||||
|
||||
SaveDataIndexerAccessor accessor = null;
|
||||
try
|
||||
{
|
||||
Result rc = OpenSaveDataIndexerAccessor(out accessor, out bool _, SaveDataSpaceId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
count = accessor.Indexer.GetIndexCount();
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
accessor?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OpenSaveDataIndexerAccessor(out SaveDataIndexerAccessor accessor, out bool neededInit,
|
||||
|
@ -622,5 +636,10 @@ namespace LibHac.FsSrv
|
|||
{
|
||||
return _config.SaveIndexerManager.OpenSaveDataIndexerAccessor(out accessor, out neededInit, spaceId);
|
||||
}
|
||||
|
||||
public void ResetTemporaryStorageIndexer()
|
||||
{
|
||||
_config.SaveIndexerManager.ResetIndexer(SaveDataSpaceId.Temporary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace LibHac.FsSrv.Sf
|
|||
Result OutputAccessLogToSdCard(InBuffer textBuffer);
|
||||
Result RegisterUpdatePartition();
|
||||
Result OpenRegisteredUpdatePartition(out ReferenceCountedDisposable<IFileSystemSf> fileSystem);
|
||||
Result GetAndClearMemoryReportInfo(out MemoryReportInfo report);
|
||||
Result GetAndClearMemoryReportInfo(out MemoryReportInfo reportInfo);
|
||||
Result GetProgramIndexForAccessLog(out int programIndex, out int programCount);
|
||||
Result GetFsStackUsage(out uint stackUsage, FsStackUsageThreadType threadType);
|
||||
Result UnsetSaveDataRootPath();
|
||||
|
|
142
src/LibHac/FsSrv/StatusReportService.cs
Normal file
142
src/LibHac/FsSrv/StatusReportService.cs
Normal file
|
@ -0,0 +1,142 @@
|
|||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Os;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
public readonly struct StatusReportService
|
||||
{
|
||||
private readonly StatusReportServiceImpl _serviceImpl;
|
||||
|
||||
public StatusReportService(StatusReportServiceImpl serviceImpl)
|
||||
{
|
||||
_serviceImpl = serviceImpl;
|
||||
}
|
||||
|
||||
public Result GetAndClearFileSystemProxyErrorInfo(out FileSystemProxyErrorInfo errorInfo)
|
||||
{
|
||||
return _serviceImpl.GetAndClearFileSystemProxyErrorInfo(out errorInfo);
|
||||
}
|
||||
|
||||
public Result GetAndClearMemoryReportInfo(out MemoryReportInfo reportInfo)
|
||||
{
|
||||
return _serviceImpl.GetAndClearMemoryReportInfo(out reportInfo);
|
||||
}
|
||||
|
||||
public Result GetFsStackUsage(out uint stackUsage, FsStackUsageThreadType threadType)
|
||||
{
|
||||
stackUsage = _serviceImpl.ReportStackUsage(threadType);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public class StatusReportServiceImpl
|
||||
{
|
||||
private Configuration _config;
|
||||
private SdkMutexType _mutex;
|
||||
|
||||
public StatusReportServiceImpl(in Configuration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
_mutex.Initialize();
|
||||
}
|
||||
|
||||
public struct Configuration
|
||||
{
|
||||
public NcaFileSystemServiceImpl NcaFsServiceImpl;
|
||||
public SaveDataFileSystemServiceImpl SaveFsServiceImpl;
|
||||
// Missing: FatFileSystemCreator (Not an IFatFileSystemCreator)
|
||||
public MemoryReport BufferManagerMemoryReport;
|
||||
public MemoryReport ExpHeapMemoryReport;
|
||||
public MemoryReport BufferPoolMemoryReport;
|
||||
public PatrolAllocateCountGetter GetPatrolAllocateCounts;
|
||||
public IStackUsageReporter MainThreadStackUsageReporter;
|
||||
public IStackUsageReporter IpcWorkerThreadStackUsageReporter;
|
||||
public IStackUsageReporter PipeLineWorkerThreadStackUsageReporter;
|
||||
|
||||
public FileSystemServer FsServer;
|
||||
}
|
||||
|
||||
public Result GetAndClearFileSystemProxyErrorInfo(out FileSystemProxyErrorInfo errorInfo)
|
||||
{
|
||||
errorInfo = new FileSystemProxyErrorInfo();
|
||||
|
||||
_config.NcaFsServiceImpl.GetAndClearRomFsErrorInfo(out errorInfo.RomFsRemountForDataCorruptionCount,
|
||||
out errorInfo.RomFsUnrecoverableDataCorruptionByRemountCount,
|
||||
out errorInfo.RomFsRecoveredByInvalidateCacheCount);
|
||||
|
||||
// Missing: GetFatInfo
|
||||
|
||||
Result rc = _config.SaveFsServiceImpl.GetSaveDataIndexCount(out int count);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
errorInfo.SaveDataIndexCount = count;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result GetAndClearMemoryReportInfo(out MemoryReportInfo reportInfo)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
reportInfo = new MemoryReportInfo();
|
||||
|
||||
// Missing: Get and clear pooled buffer stats
|
||||
reportInfo.PooledBufferFreeSizePeak = 0;
|
||||
reportInfo.PooledBufferRetriedCount = 0;
|
||||
reportInfo.PooledBufferReduceAllocationCount = 0;
|
||||
|
||||
MemoryReport report = _config.BufferManagerMemoryReport;
|
||||
if (report != null)
|
||||
{
|
||||
reportInfo.BufferManagerFreeSizePeak = report.GetFreeSizePeak();
|
||||
reportInfo.BufferManagerTotalAllocatableSizePeak = report.GetTotalAllocatableSizePeak();
|
||||
reportInfo.BufferManagerRetriedCount = report.GetRetriedCount();
|
||||
report.Clear();
|
||||
}
|
||||
|
||||
report = _config.ExpHeapMemoryReport;
|
||||
if (report != null)
|
||||
{
|
||||
reportInfo.ExpHeapFreeSizePeak = report.GetFreeSizePeak();
|
||||
report.Clear();
|
||||
}
|
||||
|
||||
report = _config.BufferPoolMemoryReport;
|
||||
if (report != null)
|
||||
{
|
||||
reportInfo.BufferPoolFreeSizePeak = report.GetFreeSizePeak();
|
||||
reportInfo.BufferPoolAllocateSizeMax = report.GetAllocateSizeMax();
|
||||
report.Clear();
|
||||
}
|
||||
|
||||
if (_config.GetPatrolAllocateCounts != null)
|
||||
{
|
||||
_config.GetPatrolAllocateCounts(out reportInfo.PatrolAllocateSuccessCount,
|
||||
out reportInfo.PatrolAllocateFailureCount);
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public uint ReportStackUsage(FsStackUsageThreadType threadType)
|
||||
{
|
||||
switch (threadType)
|
||||
{
|
||||
case FsStackUsageThreadType.MainThread:
|
||||
Assert.NotNull(_config.MainThreadStackUsageReporter);
|
||||
return _config.MainThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
case FsStackUsageThreadType.IpcWorker:
|
||||
Assert.NotNull(_config.IpcWorkerThreadStackUsageReporter);
|
||||
return _config.IpcWorkerThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
case FsStackUsageThreadType.PipelineWorker:
|
||||
Assert.NotNull(_config.PipeLineWorkerThreadStackUsageReporter);
|
||||
return _config.PipeLineWorkerThreadStackUsageReporter.GetStackUsage();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue