Adjust opened SaveDataInfoReaders if the collection is modified

This commit is contained in:
Alex Barney 2019-10-23 15:44:00 -05:00
parent f0aac13fab
commit 04b123f16e
4 changed files with 67 additions and 3 deletions

View file

@ -227,7 +227,7 @@ namespace LibHac.Fs.Shim
}
}
public struct SaveDataIterator
public struct SaveDataIterator : IDisposable
{
private FileSystemClient FsClient { get; }
private ISaveDataInfoReader Reader { get; }
@ -259,5 +259,10 @@ namespace LibHac.Fs.Shim
return rc;
}
public void Dispose()
{
Reader?.Dispose();
}
}
}

View file

@ -2,7 +2,7 @@
namespace LibHac.FsService
{
public interface ISaveDataInfoReader
public interface ISaveDataInfoReader : IDisposable
{
Result ReadSaveDataInfo(out long readCount, Span<byte> saveDataInfoBuffer);
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using LibHac.Common;
@ -26,6 +27,7 @@ namespace LibHac.FsService
private bool IsKvdbLoaded { get; set; }
private ulong LastPublishedId { get; set; }
private int Version { get; set; }
private List<SaveDataInfoReader> OpenedReaders { get; } = new List<SaveDataInfoReader>();
public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId)
{
@ -356,6 +358,8 @@ namespace LibHac.FsService
var reader = new SaveDataInfoReader(this);
OpenedReaders.Add(reader);
infoReader = reader;
return Result.Success;
@ -490,10 +494,55 @@ namespace LibHac.FsService
private Result AdjustOpenedInfoReaders(ref SaveDataAttribute key)
{
// todo
// If a new key is added or removed during iteration of the list,
// make sure the current item of the iterator remains the same
// Todo: A more efficient way of doing this
List<SaveDataAttribute> list = KvDatabase.ToList().Select(x => x.key).ToList();
int index = list.BinarySearch(key);
bool keyWasAdded = index >= 0;
if (!keyWasAdded)
{
// If the item was not found, List<T>.BinarySearch returns a negative number that
// is the bitwise complement of the index of the next element that is larger than the item
index = ~index;
}
foreach (SaveDataInfoReader reader in OpenedReaders)
{
if (keyWasAdded)
{
// New key was inserted before the iterator's position
// increment the position to compensate
if(reader.Position >= index)
{
reader.Position++;
}
}
else
{
// The position should be decremented if the iterator's position is
// after the key that came directly after the deleted key
if (reader.Position > index)
{
reader.Position--;
}
}
}
return Result.Success;
}
private void CloseReader(SaveDataInfoReader reader)
{
bool wasRemoved = OpenedReaders.Remove(reader);
Debug.Assert(wasRemoved);
}
private ref struct Mounter
{
private FileSystemClient FsClient { get; set; }
@ -602,6 +651,11 @@ namespace LibHac.FsService
return Result.Success;
}
}
public void Dispose()
{
Indexer?.CloseReader(this);
}
}
}
}

View file

@ -48,6 +48,11 @@ namespace LibHac.FsService
return Result.Success;
}
public void Dispose()
{
Reader?.Dispose();
}
}
[StructLayout(LayoutKind.Explicit, Size = 0x50)]