/// <summary> /// Opens a <see cref="SaveDataIndexerAccessor"/> for the specified save data space. /// </summary> /// <remarks> /// The returned <see cref="SaveDataIndexerAccessor"/> will have exclusive access to the requested indexer. /// The accessor must be disposed after use. /// </remarks> /// <param name="accessor">If the method returns successfully, contains the created accessor.</param> /// <param name="neededInit">If the method returns successfully, contains <see langword="true"/> /// if the indexer needed to be initialized.</param> /// <param name="spaceId">The <see cref="SaveDataSpaceId"/> of the indexer to open.</param> /// <returns>The <see cref="Result"/> of the operation.</returns> public Result OpenSaveDataIndexerAccessor(out SaveDataIndexerAccessor accessor, out bool neededInit, SaveDataSpaceId spaceId) { UnsafeHelpers.SkipParamInit(out neededInit); if (IsBisUserRedirectionEnabled && spaceId == SaveDataSpaceId.User) { spaceId = SaveDataSpaceId.ProperSystem; } UniqueLock indexerLock = default; try { ISaveDataIndexer indexer; switch (spaceId) { case SaveDataSpaceId.System: case SaveDataSpaceId.User: indexerLock = new UniqueLock(_bisIndexer.Locker); if (!_bisIndexer.IsInitialized) { _bisIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SystemIndexerMountName), SaveDataSpaceId.System, SaveDataId, MemoryResource); neededInit = true; } indexer = _bisIndexer.Indexer; break; case SaveDataSpaceId.SdSystem: case SaveDataSpaceId.SdCache: // ReSharper doesn't realize that UniqueLock locks the indexer's lock object // ReSharper disable InconsistentlySynchronizedField indexerLock = new UniqueLock(_sdCardIndexer.Locker); // We need to reinitialize the indexer if the SD card has changed if (!_sdCardHandleManager.IsValid(in _sdCardHandle) && _sdCardIndexer.IsInitialized) { _sdCardIndexer.Indexer.Dispose(); _sdCardIndexer.Indexer = null; } if (!_sdCardIndexer.IsInitialized) { _sdCardIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SdCardIndexerMountName), SaveDataSpaceId.SdSystem, SaveDataId, MemoryResource); _sdCardHandleManager.GetHandle(out _sdCardHandle).IgnoreResult(); neededInit = true; } indexer = _sdCardIndexer.Indexer; // ReSharper restore InconsistentlySynchronizedField break; case SaveDataSpaceId.Temporary: indexerLock = new UniqueLock(_tempIndexer.Locker); indexer = _tempIndexer.Indexer; break; case SaveDataSpaceId.ProperSystem: indexerLock = new UniqueLock(_properSystemIndexer.Locker); if (!_properSystemIndexer.IsInitialized) { _properSystemIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(ProperSystemIndexerMountName), SaveDataSpaceId.ProperSystem, SaveDataId, MemoryResource); neededInit = true; } indexer = _properSystemIndexer.Indexer; break; case SaveDataSpaceId.SafeMode: indexerLock = new UniqueLock(_safeIndexer.Locker); if (!_safeIndexer.IsInitialized) { _safeIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SafeModeIndexerMountName), SaveDataSpaceId.SafeMode, SaveDataId, MemoryResource); neededInit = true; } indexer = _safeIndexer.Indexer; break; default: accessor = default; return(ResultFs.InvalidArgument.Log()); } accessor = new SaveDataIndexerAccessor(indexer, ref indexerLock); return(Result.Success); } finally { indexerLock.Dispose(); } }
/// <summary> /// Opens a <see cref="SaveDataIndexerAccessor"/> for the specified save data space. /// </summary> /// <remarks> /// The returned <see cref="SaveDataIndexerAccessor"/> will have exclusive access to the requested indexer. /// The accessor must be disposed after use. /// </remarks> /// <param name="accessor">If the method returns successfully, contains the created accessor.</param> /// <param name="neededInit">If the method returns successfully, contains <see langword="true"/> /// if the indexer needed to be initialized.</param> /// <param name="spaceId">The <see cref="SaveDataSpaceId"/> of the indexer to open.</param> /// <returns>The <see cref="Result"/> of the operation.</returns> public Result OpenAccessor(out SaveDataIndexerAccessor accessor, out bool neededInit, SaveDataSpaceId spaceId) { neededInit = false; if (IsBisUserRedirectionEnabled && spaceId == SaveDataSpaceId.User) { spaceId = SaveDataSpaceId.ProperSystem; } switch (spaceId) { case SaveDataSpaceId.System: case SaveDataSpaceId.User: Monitor.Enter(_bisIndexer.Locker); if (!_bisIndexer.IsInitialized) { _bisIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SystemIndexerMountName), SaveDataSpaceId.System, SaveDataId, MemoryResource); neededInit = true; } accessor = new SaveDataIndexerAccessor(_bisIndexer.Indexer, _bisIndexer.Locker); return(Result.Success); case SaveDataSpaceId.SdSystem: case SaveDataSpaceId.SdCache: Monitor.Enter(_sdCardIndexer.Locker); // We need to reinitialize the indexer if the SD card has changed if (!_sdCardHandleManager.IsValid(in _sdCardHandle) && _sdCardIndexer.IsInitialized) { _sdCardIndexer.Indexer.Dispose(); _sdCardIndexer.Indexer = null; } if (!_sdCardIndexer.IsInitialized) { _sdCardIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SdCardIndexerMountName), SaveDataSpaceId.SdSystem, SaveDataId, MemoryResource); _sdCardHandleManager.GetHandle(out _sdCardHandle).IgnoreResult(); neededInit = true; } accessor = new SaveDataIndexerAccessor(_sdCardIndexer.Indexer, _sdCardIndexer.Locker); return(Result.Success); case SaveDataSpaceId.Temporary: Monitor.Enter(_tempIndexer.Locker); accessor = new SaveDataIndexerAccessor(_tempIndexer.Indexer, _tempIndexer.Locker); return(Result.Success); case SaveDataSpaceId.ProperSystem: Monitor.Enter(_properSystemIndexer.Locker); if (!_properSystemIndexer.IsInitialized) { _properSystemIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(ProperSystemIndexerMountName), SaveDataSpaceId.ProperSystem, SaveDataId, MemoryResource); neededInit = true; } accessor = new SaveDataIndexerAccessor(_properSystemIndexer.Indexer, _properSystemIndexer.Locker); return(Result.Success); case SaveDataSpaceId.SafeMode: Monitor.Enter(_safeIndexer.Locker); if (!_safeIndexer.IsInitialized) { _safeIndexer.Indexer = new SaveDataIndexer(FsClient, new U8Span(SafeModeIndexerMountName), SaveDataSpaceId.SafeMode, SaveDataId, MemoryResource); neededInit = true; } accessor = new SaveDataIndexerAccessor(_safeIndexer.Indexer, _safeIndexer.Locker); return(Result.Success); default: accessor = default; return(ResultFs.InvalidArgument.Log()); } }