private void LocationServiceStorageLocationChanging(object sender, PersistentStorageLocationChangingEventArgs e) { ReferenceCountedDisposable <IPersistentStorage> storage = null; lock (_lock) { if (e.SolutionId != _currentPersistentStorageSolutionId) { return; } // We will transfer ownership in a thread-safe way out so we can dispose outside the lock storage = _currentPersistentStorage; _currentPersistentStorage = null; _currentPersistentStorageSolutionId = null; } if (storage != null) { if (e.MustUseNewStorageLocationImmediately) { // Dispose storage outside of the lock. Note this only removes our reference count; clients who are still // using this will still be holding a reference count. storage.Dispose(); } else { // make it to shutdown asynchronously Task.Run(() => storage.Dispose()); } } }
public Result OpenHostFileSystem(out ReferenceCountedDisposable <IFileSystem> fileSystem, U8Span path, bool openCaseSensitive) { UnsafeHelpers.SkipParamInit(out fileSystem); Result rc; if (!path.IsEmpty()) { rc = Util.VerifyHostPath(path); if (rc.IsFailure()) { return(rc); } } // Todo: Return shared fs from Create rc = FsCreators.TargetManagerFileSystemCreator.Create(out IFileSystem hostFs, openCaseSensitive); if (rc.IsFailure()) { return(rc); } ReferenceCountedDisposable <IFileSystem> sharedHostFs = null; ReferenceCountedDisposable <IFileSystem> subDirFs = null; try { sharedHostFs = new ReferenceCountedDisposable <IFileSystem>(hostFs); if (path.IsEmpty()) { ReadOnlySpan <byte> rootHostPath = new[] { (byte)'C', (byte)':', (byte)'/' }; rc = sharedHostFs.Target.GetEntryType(out _, new U8Span(rootHostPath)); // Nintendo ignores all results other than this one if (ResultFs.TargetNotFound.Includes(rc)) { return(rc); } Shared.Move(out fileSystem, ref sharedHostFs); return(Result.Success); } rc = FsCreators.SubDirectoryFileSystemCreator.Create(out subDirFs, ref sharedHostFs, path, preserveUnc: true); if (rc.IsFailure()) { return(rc); } fileSystem = subDirFs; return(Result.Success); } finally { sharedHostFs?.Dispose(); subDirFs?.Dispose(); } }
protected override void Dispose(bool isDisposing) { if (isDisposing) { _baseOperator?.Dispose(); } }
static Result Mount(FileSystemClient fs, U8Span mountName, GameCardHandle handle, GameCardPartition partitionId) { Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) { return(rc); } using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable <IFileSystemSf> fileSystem = null; try { rc = fsProxy.Target.OpenGameCardFileSystem(out fileSystem, handle, partitionId); if (rc.IsFailure()) { return(rc); } var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem); var mountNameGenerator = new GameCardCommonMountNameGenerator(handle, partitionId); return(fs.Register(mountName, fileSystemAdapter, mountNameGenerator)); } finally { fileSystem?.Dispose(); } }
public static Result GetAndClearPatrolReadAllocateBufferCount(this StorageService service, out long successCount, out long failureCount) { UnsafeHelpers.SkipParamInit(out successCount, out failureCount); ReferenceCountedDisposable <IStorageDeviceOperator> mmcOperator = null; try { Result rc = service.GetMmcManagerOperator(out mmcOperator); if (rc.IsFailure()) { return(rc); } int operationId = MakeOperationId(MmcManagerOperationIdValue.GetAndClearPatrolReadAllocateBufferCount); OutBuffer successCountBuffer = OutBuffer.FromStruct(ref successCount); OutBuffer failureCountBuffer = OutBuffer.FromStruct(ref failureCount); return(mmcOperator.Target.OperateOut2(out _, successCountBuffer, out _, failureCountBuffer, operationId)); } finally { mmcOperator?.Dispose(); } }
protected override void Dispose(bool isDisposing) { if (isDisposing) { _baseDirectory?.Dispose(); } }
public static Result MountCustomStorage(this FileSystemClient fs, U8Span mountName, CustomStorageId storageId) { Result rc = fs.Impl.CheckMountName(mountName); if (rc.IsFailure()) { return(rc); } ReferenceCountedDisposable <IFileSystemSf> fileSystem = null; try { using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); rc = fsProxy.Target.OpenCustomStorageFileSystem(out fileSystem, storageId); if (rc.IsFailure()) { return(rc); } var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem); return(fs.Register(mountName, fileSystemAdapter)); } finally { fileSystem?.Dispose(); } }
protected override void Dispose(bool isDisposing) { if (isDisposing) { _baseStorage?.Dispose(); } }
protected override void Dispose(bool disposing) { if (_baseFileSystem is null) { return; } if (disposing) { if (typeof(T) == typeof(SaveDataFileSystem)) { _cacheManager.Register( (ReferenceCountedDisposable <SaveDataFileSystem>)(object) _baseFileSystem); } else if (typeof(T) == typeof(ApplicationTemporaryFileSystem)) { _cacheManager.Register( (ReferenceCountedDisposable <ApplicationTemporaryFileSystem>)(object) _baseFileSystem); } else if (typeof(T) == typeof(DirectorySaveDataFileSystem)) { _cacheManager.Register( (ReferenceCountedDisposable <DirectorySaveDataFileSystem>)(object) _baseFileSystem); } _baseFileSystem.Dispose(); _baseFileSystem = null; } base.Dispose(disposing); }
protected override void Dispose(bool isDisposing) { if (isDisposing) { _baseCommitManager?.Dispose(); } }
/// <summary> /// Commits all added file systems. /// </summary> /// <returns>The <see cref="Result"/> of the operation.</returns> public Result Commit() { lock (Locker) { Result rc = EnsureSaveDataForContext(); if (rc.IsFailure()) { return(rc); } ReferenceCountedDisposable <IFileSystem> contextFs = null; try { rc = MultiCommitInterface.Target.OpenMultiCommitContext(out contextFs); if (rc.IsFailure()) { return(rc); } return(Commit(contextFs.Target)); } finally { contextFs?.Dispose(); } } }
protected override void Dispose(bool isDisposing) { if (isDisposing) { _baseReader?.Dispose(); } }
public void TestWeakReferenceLifetime() { var target = new DisposableObject(); var reference = new ReferenceCountedDisposable <DisposableObject>(target); var weakReference = new ReferenceCountedDisposable <DisposableObject> .WeakReference(reference); var reference2 = reference.TryAddReference(); Assert.NotNull(reference2); reference.Dispose(); // TryAddReference fails after dispose for a counted reference Assert.Null(reference.TryAddReference()); Assert.NotNull(reference2.Target); Assert.False(target.IsDisposed); // However, a WeakReference created from the disposed reference can still add a reference var reference3 = weakReference.TryAddReference(); Assert.NotNull(reference3); reference2.Dispose(); Assert.False(target.IsDisposed); reference3.Dispose(); Assert.True(target.IsDisposed); }
public Result OpenBaseFileSystem(out ReferenceCountedDisposable <IFileSystemSf> fileSystem, BaseFileSystemId fileSystemId) { UnsafeHelpers.SkipParamInit(out fileSystem); Result rc = CheckCapabilityById(fileSystemId, _processId); if (rc.IsFailure()) { return(rc); } ReferenceCountedDisposable <IFileSystem> fs = null; try { // Open the file system rc = _serviceImpl.OpenBaseFileSystem(out fs, fileSystemId); if (rc.IsFailure()) { return(rc); } // Create an SF adapter for the file system fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs); return(Result.Success); } finally { fs?.Dispose(); } }
public static Result GetGameCardHandle(this FileSystemClient fs, out GameCardHandle handle) { UnsafeHelpers.SkipParamInit(out handle); using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable <IDeviceOperator> deviceOperator = null; try { Result rc = fsProxy.Target.OpenDeviceOperator(out deviceOperator); fs.Impl.AbortIfNeeded(rc); if (rc.IsFailure()) { return(rc); } rc = deviceOperator.Target.GetGameCardHandle(out handle); fs.Impl.AbortIfNeeded(rc); return(rc); } finally { deviceOperator?.Dispose(); } }
static Result Mount(FileSystemClientImpl fs, U8Span mountName, BisPartitionId partitionId) { Result rc = fs.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) { return(rc); } using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject(); // Nintendo doesn't use the provided rootPath FspPath.CreateEmpty(out FspPath sfPath); ReferenceCountedDisposable <IFileSystemSf> fileSystem = null; try { rc = fsProxy.Target.OpenBisFileSystem(out fileSystem, in sfPath, partitionId); if (rc.IsFailure()) { return(rc); } var nameGenerator = new BisCommonMountNameGenerator(partitionId); var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem); return(fs.Fs.Register(mountName, fileSystemAdapter, nameGenerator)); } finally { fileSystem?.Dispose(); } }
public static Result GetAndClearMmcErrorInfo(this StorageService service, out StorageErrorInfo errorInfo, out long logSize, Span <byte> logBuffer) { UnsafeHelpers.SkipParamInit(out errorInfo, out logSize); ReferenceCountedDisposable <IStorageDeviceOperator> mmcOperator = null; try { Result rc = service.GetMmcManagerOperator(out mmcOperator); if (rc.IsFailure()) { return(rc); } int operationId = MakeOperationId(MmcManagerOperationIdValue.GetAndClearErrorInfo); var logOutBuffer = new OutBuffer(logBuffer); OutBuffer errorInfoOutBuffer = OutBuffer.FromStruct(ref errorInfo); return(mmcOperator.Target.OperateOut2(out _, errorInfoOutBuffer, out logSize, logOutBuffer, operationId)); } finally { mmcOperator?.Dispose(); } }
protected override void DisposeImpl() { // dispose service and snapshot channels _serviceEndPoint.UnexpectedExceptionThrown -= UnexpectedExceptionThrown; _serviceEndPoint.Dispose(); _remoteDataRpc.Dispose(); base.DisposeImpl(); }
public static Result OpenMmcStorage(this StorageService service, out ReferenceCountedDisposable <IStorage> storage, MmcPartition partition) { UnsafeHelpers.SkipParamInit(out storage); ReferenceCountedDisposable <IStorageDeviceManager> deviceManager = null; try { Result rc = service.GetMmcManager(out deviceManager); if (rc.IsFailure()) { return(rc); } rc = GetAttribute(out ulong attribute, partition); if (rc.IsFailure()) { return(rc); } ReferenceCountedDisposable <IStorageSf> mmcStorage = null; ReferenceCountedDisposable <IStorage> tempStorage = null; try { rc = deviceManager.Target.OpenStorage(out mmcStorage, attribute); if (rc.IsFailure()) { return(rc); } tempStorage = StorageServiceObjectAdapter.CreateShared(ref mmcStorage); if (IsSpeedEmulationNeeded(partition)) { tempStorage = SpeedEmulationStorage.CreateShared(ref tempStorage); if (tempStorage is null) { return(ResultFs.AllocationMemoryFailedCreateShared.Log()); } } storage = Shared.Move(ref tempStorage); return(Result.Success); } finally { mmcStorage?.Dispose(); tempStorage?.Dispose(); } } finally { deviceManager?.Dispose(); } }
protected override void Dispose(bool disposing) { if (disposing) { _entryCountSemaphore?.Dispose(); _mountCountSemaphore?.Dispose(); } base.Dispose(disposing); }
protected override void Dispose(bool disposing) { if (disposing) { BaseFileSystem?.Dispose(); BaseFileSystem = null; } base.Dispose(disposing); }
protected override void Dispose(bool disposing) { if (disposing) { _baseStorage?.Target.UnsetOpenType(_type); _baseStorage?.Dispose(); } base.Dispose(disposing); }
public void Dispose() { if (_pinnedObject != null) { _semaphore.Dispose(); _pinnedObject.Dispose(); _pinnedObject = null; } }
public void TestTryAddReferenceFailsAfterDispose() { var target = new DisposableObject(); var reference = new ReferenceCountedDisposable <DisposableObject>(target); reference.Dispose(); Assert.Null(reference.TryAddReference()); }
// Todo: Make case sensitive public Result Create(out ReferenceCountedDisposable <IFileSystem> fileSystem, U8Span rootPath, BisPartitionId partitionId, bool caseSensitive) { UnsafeHelpers.SkipParamInit(out fileSystem); if (!IsValidPartitionId(partitionId)) { return(ResultFs.InvalidArgument.Log()); } if (rootPath.IsNull()) { return(ResultFs.NullptrArgument.Log()); } if (Config.TryGetFileSystem(out IFileSystem fs, partitionId)) { fileSystem = new ReferenceCountedDisposable <IFileSystem>(fs); return(Result.Success); } if (Config.RootFileSystem == null) { return(ResultFs.PreconditionViolation.Log()); } var partitionPath = GetPartitionPath(partitionId).ToU8String(); ReferenceCountedDisposable <IFileSystem> partitionFileSystem = null; ReferenceCountedDisposable <IFileSystem> sharedRootFs = null; try { sharedRootFs = new ReferenceCountedDisposable <IFileSystem>(Config.RootFileSystem); Result rc = Utility.WrapSubDirectory(out partitionFileSystem, ref sharedRootFs, partitionPath, true); if (rc.IsFailure()) { return(rc); } if (rootPath.IsEmpty()) { Shared.Move(out fileSystem, ref partitionFileSystem); return(Result.Success); } return(Utility.CreateSubDirectoryFileSystem(out fileSystem, ref partitionFileSystem, rootPath)); } finally { partitionFileSystem?.Dispose(); sharedRootFs?.Dispose(); } }
protected override void OnStopped() { // we are asked to stop. unsubscribe and dispose to disconnect. // there are 2 ways to get disconnected. one is Roslyn decided to disconnect with RemoteHost (ex, cancellation or recycle OOP) and // the other is external thing disconnecting remote host from us (ex, user killing OOP process). // the Disconnected event we subscribe is to detect #2 case. and this method is for #1 case. so when we are willingly disconnecting // we don't need the event, otherwise, Disconnected event will be called twice. _rpc.Disconnected -= OnRpcDisconnected; _rpc.Dispose(); _remotableDataRpc.Dispose(); }
protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _accessor.Dispose(); } _start = null; }
/// <summary> /// Recovers an interrupted multi-commit. The commit will either be completed or rolled back depending on /// where in the commit process it was interrupted. Does nothing if there is no commit to recover. /// </summary> /// <param name="multiCommitInterface">The core interface used for multi-commits.</param> /// <param name="saveService">The save data service.</param> /// <returns>The <see cref="Result"/> of the operation.<br/> /// <see cref="Result.Success"/>: The recovery was successful or there was no multi-commit to recover.</returns> public static Result Recover(ISaveDataMultiCommitCoreInterface multiCommitInterface, SaveDataFileSystemServiceImpl saveService) { lock (Locker) { bool needsRecover = true; ReferenceCountedDisposable <IFileSystem> fileSystem = null; try { // Check if a multi-commit was interrupted by checking if there's a commit context file. Result rc = multiCommitInterface.OpenMultiCommitContext(out fileSystem); if (rc.IsFailure()) { if (!ResultFs.PathNotFound.Includes(rc) && !ResultFs.TargetNotFound.Includes(rc)) { return(rc); } // Unable to open the multi-commit context file system, so there's nothing to recover needsRecover = false; } if (needsRecover) { rc = fileSystem.Target.OpenFile(out IFile file, CommitContextFileName, OpenMode.Read); file?.Dispose(); if (rc.IsFailure()) { // Unable to open the context file. No multi-commit to recover. if (ResultFs.PathNotFound.Includes(rc)) { needsRecover = false; } } } if (!needsRecover) { return(Result.Success); } // There was a context file. Recover the unfinished commit. return(Recover(multiCommitInterface, fileSystem.Target, saveService)); } finally { fileSystem?.Dispose(); } } }
static Result Mount(FileSystemClient fs, U8Span mountName, ContentStorageId storageId) { // It can take some time for the system partition to be ready (if it's on the SD card). // Thus, we will retry up to 10 times, waiting one second each time. const int maxRetries = 10; const int retryInterval = 1000; Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) { return(rc); } using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject(); ReferenceCountedDisposable <IFileSystemSf> fileSystem = null; try { for (int i = 0; i < maxRetries; i++) { rc = fsProxy.Target.OpenContentStorageFileSystem(out fileSystem, storageId); if (rc.IsSuccess()) { break; } if (!ResultFs.SystemPartitionNotReady.Includes(rc)) { return(rc); } if (i == maxRetries - 1) { return(rc); } fs.Hos.Os.SleepThread(TimeSpan.FromMilliSeconds(retryInterval)); } var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem); var mountNameGenerator = new ContentStorageCommonMountNameGenerator(storageId); return(fs.Register(mountName, fileSystemAdapter, mountNameGenerator)); } finally { fileSystem?.Dispose(); } }
public Result OpenBisStorage(out ReferenceCountedDisposable <IStorageSf> storage, BisPartitionId id) { UnsafeHelpers.SkipParamInit(out storage); var storageFlag = StorageType.Bis; using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag); Result rc = GetProgramInfo(out ProgramInfo programInfo); if (rc.IsFailure()) { return(rc); } rc = GetAccessibilityForOpenBisPartition(out Accessibility accessibility, programInfo, id); if (rc.IsFailure()) { return(rc); } bool canAccess = accessibility.CanRead && accessibility.CanWrite; if (!canAccess) { return(ResultFs.PermissionDenied.Log()); } ReferenceCountedDisposable <IStorage> tempStorage = null; try { rc = _serviceImpl.OpenBisStorage(out tempStorage, id); if (rc.IsFailure()) { return(rc); } tempStorage = StorageLayoutTypeSetStorage.CreateShared(ref tempStorage, storageFlag); // Todo: Async storage storage = StorageInterfaceAdapter.CreateShared(ref tempStorage); return(Result.Success); } finally { tempStorage?.Dispose(); } }