Properly handle multiple mount/unmount requests.

This commit is contained in:
Paul Chote
2016-01-20 22:47:09 +00:00
parent fcccc0f5f9
commit cbfd9bb921

View File

@@ -19,7 +19,8 @@ namespace OpenRA.FileSystem
{ {
public class FileSystem public class FileSystem
{ {
public readonly List<IReadOnlyPackage> MountedPackages = new List<IReadOnlyPackage>(); public IEnumerable<IReadOnlyPackage> MountedPackages { get { return mountedPackages.Keys; } }
readonly Dictionary<IReadOnlyPackage, int> mountedPackages = new Dictionary<IReadOnlyPackage, int>();
static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>(); static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>();
@@ -70,12 +71,6 @@ namespace OpenRA.FileSystem
return new Folder(filename, order); return new Folder(filename, order);
} }
public void Mount(IReadOnlyPackage mount)
{
if (!MountedPackages.Contains(mount))
MountedPackages.Add(mount);
}
public void Mount(string name) public void Mount(string name)
{ {
var optional = name.StartsWith("~"); var optional = name.StartsWith("~");
@@ -84,8 +79,7 @@ namespace OpenRA.FileSystem
name = Platform.ResolvePath(name); name = Platform.ResolvePath(name);
Action a = () => MountInner(OpenPackage(name, order++)); Action a = () => Mount(OpenPackage(name, order++));
if (optional) if (optional)
try { a(); } try { a(); }
catch { } catch { }
@@ -93,35 +87,55 @@ namespace OpenRA.FileSystem
a(); a();
} }
void MountInner(IReadOnlyPackage package) public void Mount(IReadOnlyPackage package)
{ {
MountedPackages.Add(package); var mountCount = 0;
if (mountedPackages.TryGetValue(package, out mountCount))
foreach (var filename in package.AllFileNames())
{ {
var packageList = fileIndex[filename]; // Package is already mounted
if (!packageList.Contains(package)) // Increment the mount count and bump up the file loading priority
packageList.Add(package); mountedPackages[package] = mountCount + 1;
foreach (var filename in package.AllFileNames())
{
fileIndex[filename].Remove(package);
fileIndex[filename].Add(package);
}
}
else
{
// Mounting the package for the first time
mountedPackages.Add(package, 1);
foreach (var filename in package.AllFileNames())
fileIndex[filename].Add(package);
} }
} }
public bool Unmount(IReadOnlyPackage package) public bool Unmount(IReadOnlyPackage package)
{ {
foreach (var packagesForFile in fileIndex.Values) var mountCount = 0;
packagesForFile.RemoveAll(p => p == package); if (!mountedPackages.TryGetValue(package, out mountCount))
return false;
if (MountedPackages.Contains(package)) if (--mountCount <= 0)
{
foreach (var packagesForFile in fileIndex.Values)
packagesForFile.RemoveAll(p => p == package);
mountedPackages.Remove(package);
package.Dispose(); package.Dispose();
}
else
mountedPackages[package] = mountCount;
return MountedPackages.RemoveAll(p => p == package) > 0; return true;
} }
public void UnmountAll() public void UnmountAll()
{ {
foreach (var package in MountedPackages) foreach (var package in mountedPackages.Keys)
package.Dispose(); package.Dispose();
MountedPackages.Clear(); mountedPackages.Clear();
fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>()); fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
} }
@@ -179,9 +193,9 @@ namespace OpenRA.FileSystem
// Ask each package individually // Ask each package individually
IReadOnlyPackage package; IReadOnlyPackage package;
if (explicitPackage && !string.IsNullOrEmpty(packageName)) if (explicitPackage && !string.IsNullOrEmpty(packageName))
package = MountedPackages.Where(x => x.Name == packageName).MaxByOrDefault(x => x.Priority); package = mountedPackages.Keys.Where(x => x.Name == packageName).MaxByOrDefault(x => x.Priority);
else else
package = MountedPackages.Where(x => x.Exists(filename)).MaxByOrDefault(x => x.Priority); package = mountedPackages.Keys.Where(x => x.Exists(filename)).MaxByOrDefault(x => x.Priority);
if (package != null) if (package != null)
{ {
@@ -201,10 +215,10 @@ namespace OpenRA.FileSystem
var divide = name.Split(':'); var divide = name.Split(':');
var packageName = divide.First(); var packageName = divide.First();
var filename = divide.Last(); var filename = divide.Last();
return MountedPackages.Where(n => n.Name == packageName).Any(f => f.Exists(filename)); return mountedPackages.Keys.Where(n => n.Name == packageName).Any(f => f.Exists(filename));
} }
else else
return MountedPackages.Any(f => f.Exists(name)); return mountedPackages.Keys.Any(f => f.Exists(name));
} }
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e) public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)