Move root directory cache to VFS.

This commit is contained in:
2020-09-03 00:58:07 +01:00
parent 4e01e5ebf1
commit 0c0b519072
2 changed files with 89 additions and 65 deletions

View File

@@ -27,14 +27,12 @@ namespace RomRepoMgr.Core.Filesystem
readonly ConcurrentDictionary<long, Stream> _streamsCache;
readonly Vfs _vfs;
long _lastHandle;
ConcurrentDictionary<string, long> _rootDirectoryCache;
string _umountToken;
public Fuse(Vfs vfs)
{
_directoryCache = new ConcurrentDictionary<long, List<DirectoryEntry>>();
_lastHandle = 0;
_rootDirectoryCache = new ConcurrentDictionary<string, long>();
_machinesStatCache = new ConcurrentDictionary<long, ConcurrentDictionary<string, CachedMachine>>();
_romSetsCache = new ConcurrentDictionary<long, RomSet>();
_machineFilesCache = new ConcurrentDictionary<ulong, ConcurrentDictionary<string, CachedFile>>();
@@ -106,30 +104,27 @@ namespace RomRepoMgr.Core.Filesystem
return 0;
}
if(_rootDirectoryCache.Count == 0)
FillRootDirectoryCache();
long romSetId = _vfs.GetRomSetId(pieces[0]);
if(!_rootDirectoryCache.TryGetValue(pieces[0], out long romSetId))
if(romSetId <= 0)
{
if(pieces[0] == ".fuse_umount" &&
_umountToken != null)
if(pieces[0] != ".fuse_umount" ||
_umountToken == null)
return Errno.ENOENT;
stat = new Stat
{
stat = new Stat
{
st_mode = FilePermissions.S_IFREG | NativeConvert.FromOctalPermissionString("0444"),
st_nlink = 1,
st_ctime = NativeConvert.ToTimeT(DateTime.UtcNow),
st_mtime = NativeConvert.ToTimeT(DateTime.UtcNow),
st_blksize = 0,
st_blocks = 0,
st_ino = 0,
st_size = 0
};
st_mode = FilePermissions.S_IFREG | NativeConvert.FromOctalPermissionString("0444"),
st_nlink = 1,
st_ctime = NativeConvert.ToTimeT(DateTime.UtcNow),
st_mtime = NativeConvert.ToTimeT(DateTime.UtcNow),
st_blksize = 0,
st_blocks = 0,
st_ino = 0,
st_size = 0
};
return 0;
}
return Errno.ENOENT;
return 0;
}
if(!_romSetsCache.TryGetValue(romSetId, out RomSet romSet))
@@ -808,40 +803,6 @@ namespace RomRepoMgr.Core.Filesystem
protected override Errno OnRemovePathExtendedAttribute(string path, string name) => Errno.EROFS;
void FillRootDirectoryCache()
{
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
List<DirectoryEntry> entries = new List<DirectoryEntry>
{
new DirectoryEntry("."),
new DirectoryEntry("..")
};
ConcurrentDictionary<string, long> rootCache = new ConcurrentDictionary<string, long>();
foreach(RomSet set in ctx.RomSets)
{
string name = set.Name.Replace('/', '');
if(entries.Any(e => e.Name == name))
name = Path.GetFileNameWithoutExtension(set.Filename)?.Replace('/', '');
if(entries.Any(e => e.Name == name) ||
name == null)
name = Path.GetFileNameWithoutExtension(set.Sha384);
if(name == null)
continue;
entries.Add(new DirectoryEntry(name));
rootCache[name] = set.Id;
_romSetsCache[set.Id] = set;
}
_rootDirectoryCache = rootCache;
}
protected override Errno OnOpenDirectory(string directory, OpenedPathInfo info)
{
try
@@ -881,7 +842,6 @@ namespace RomRepoMgr.Core.Filesystem
info.Handle = new IntPtr(_lastHandle);
_directoryCache[_lastHandle] = entries;
_rootDirectoryCache = rootCache;
return 0;
}
@@ -891,10 +851,9 @@ namespace RomRepoMgr.Core.Filesystem
if(pieces.Length == 0)
return Errno.ENOENT;
if(_rootDirectoryCache.Count == 0)
FillRootDirectoryCache();
long romSetId = _vfs.GetRomSetId(pieces[0]);
if(!_rootDirectoryCache.TryGetValue(pieces[0], out long romSetId))
if(romSetId <= 0)
return Errno.ENOENT;
if(!_romSetsCache.TryGetValue(romSetId, out RomSet romSet))
@@ -1076,10 +1035,9 @@ namespace RomRepoMgr.Core.Filesystem
if(pieces.Length == 0)
return mode.HasFlag(AccessModes.W_OK) ? Errno.EROFS : 0;
if(_rootDirectoryCache.Count == 0)
FillRootDirectoryCache();
long romSetId = _vfs.GetRomSetId(pieces[0]);
if(!_rootDirectoryCache.TryGetValue(pieces[0], out long romSetId))
if(romSetId <= 0)
return Errno.ENOENT;
if(!_romSetsCache.TryGetValue(romSetId, out RomSet romSet))

View File

@@ -1,15 +1,27 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using RomRepoMgr.Database;
using RomRepoMgr.Database.Models;
namespace RomRepoMgr.Core.Filesystem
{
public class Vfs : IDisposable
{
Fuse _fuse;
Winfsp _winfsp;
readonly ConcurrentDictionary<long, RomSet> _romSetsCache;
Fuse _fuse;
ConcurrentDictionary<string, long> _rootDirectoryCache;
Winfsp _winfsp;
public Vfs()
{
_rootDirectoryCache = new ConcurrentDictionary<string, long>();
_romSetsCache = new ConcurrentDictionary<long, RomSet>();
}
public static bool IsAvailable => Winfsp.IsAvailable || Fuse.IsAvailable;
@@ -69,5 +81,59 @@ namespace RomRepoMgr.Core.Filesystem
internal string[] SplitPath(string path) =>
path.Split(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "\\" : "/",
StringSplitOptions.RemoveEmptyEntries);
void FillRootDirectoryCache()
{
using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);
ConcurrentDictionary<string, long> rootCache = new ConcurrentDictionary<string, long>();
foreach(RomSet set in ctx.RomSets)
{
string name;
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
name = set.Name.Replace('/', '').Replace('<', '\uFF1C').Replace('>', '\uFF1E').
Replace(':', '\uFF1A').Replace('"', '\u2033').Replace('\\', '').Replace('|', '').
Replace('?', '').Replace('*', '');
if(rootCache.ContainsKey(name))
name = Path.GetFileNameWithoutExtension(set.Filename)?.Replace('/', '').Replace('<', '\uFF1C').
Replace('>', '\uFF1E').Replace(':', '\uFF1A').Replace('"', '\u2033').
Replace('\\', '').Replace('|', '').Replace('?', '').Replace('*', '');
}
else
{
name = set.Name.Replace('/', '');
if(rootCache.ContainsKey(name))
name = Path.GetFileNameWithoutExtension(set.Filename)?.Replace('/', '');
}
if(name == null ||
rootCache.ContainsKey(name))
name = Path.GetFileNameWithoutExtension(set.Sha384);
if(name == null)
continue;
rootCache[name] = set.Id;
_romSetsCache[set.Id] = set;
}
_rootDirectoryCache = rootCache;
}
internal long GetRomSetId(string name)
{
if(_rootDirectoryCache.Count == 0)
FillRootDirectoryCache();
if(!_rootDirectoryCache.TryGetValue(name, out long romSetId))
return -1;
return romSetId;
}
}
}