mirror of
https://github.com/claunia/romrepomgr.git
synced 2025-12-16 19:24:51 +00:00
Move root directory cache to VFS.
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user