/// <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();
            }
        }
Beispiel #2
0
 internal Result OpenSaveDataIndexerAccessor(out SaveDataIndexerAccessor accessor, out bool neededInit, SaveDataSpaceId spaceId)
 {
     return(SaveDataIndexerManager.OpenAccessor(out accessor, out neededInit, spaceId));
 }
        /// <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());
            }
        }