isolate exclusive folder access pattern into separate class

This commit is contained in:
Krzysztof Wicher 2017-01-19 16:43:54 -08:00
parent e271b4a818
commit 8ef670161b

View file

@ -138,34 +138,6 @@ namespace Microsoft.DotNet.TestFramework
return new DirectoryInfo(Path.Combine(baseDirectory, callingMethod + identifier, _assetName));
}
private IEnumerable<FileInfo> LoadInventory(FileInfo file)
{
file.Refresh();
if (!file.Exists)
{
throw new ArgumentException("Inventory file should exist.");
}
var inventory = new List<FileInfo>();
foreach (var p in File.ReadAllLines(file.FullName))
{
inventory.Add(new FileInfo(p));
}
return inventory;
}
private void SaveInventory(FileInfo file, IEnumerable<FileInfo> inventory)
{
_dataDirectory.Refresh();
if (!_dataDirectory.Exists)
{
_dataDirectory.Create();
}
File.WriteAllLines(file.FullName, inventory.Select((fi) => fi.FullName).ToList());
}
private IEnumerable<FileInfo> GetFileList()
{
return _root.GetFiles("*.*", SearchOption.AllDirectories)
@ -191,27 +163,21 @@ namespace Microsoft.DotNet.TestFramework
preInventory = beforeAction();
}
Task.Run(async () => await ConcurrencyUtilities.ExecuteWithFileLockedAsync<object>(
_dataDirectory.FullName,
lockedToken =>
ExclusiveFolderAccess.Do(_dataDirectory, (folder) => {
file.Refresh();
if (file.Exists)
{
file.Refresh();
if (file.Exists)
{
inventory = LoadInventory(file);
}
else
{
action();
inventory = folder.LoadInventory(file);
}
else
{
action();
inventory = GetFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName));
inventory = GetFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName));
SaveInventory(file, inventory);
}
return Task.FromResult(new Object());
},
CancellationToken.None)).Wait();
folder.SaveInventory(file, inventory);
}
});
return inventory;
}
@ -286,7 +252,10 @@ namespace Microsoft.DotNet.TestFramework
return;
}
var trackedFiles = _inventoryFiles.AllInventoryFiles.SelectMany(f => LoadInventory(f));
IEnumerable<FileInfo> trackedFiles = null;
ExclusiveFolderAccess.Do(_dataDirectory, (folder) => {
trackedFiles = _inventoryFiles.AllInventoryFiles.SelectMany(f => folder.LoadInventory(f));
});
var assetFiles = GetFileList();
@ -316,7 +285,7 @@ namespace Microsoft.DotNet.TestFramework
return;
}
var updatedSourceFiles = LoadInventory(_inventoryFiles.Source)
var updatedSourceFiles = ExclusiveFolderAccess.Read(_inventoryFiles.Source)
.Where(f => f.LastWriteTime > earliestDataDirectoryTimestamp);
if (updatedSourceFiles.Any())
@ -340,5 +309,65 @@ namespace Microsoft.DotNet.TestFramework
throw new DirectoryNotFoundException($"Directory not found at '{_root.FullName}'");
}
}
private class ExclusiveFolderAccess
{
private DirectoryInfo _directory;
private ExclusiveFolderAccess(DirectoryInfo directory)
{
_directory = directory;
}
public static void Do(DirectoryInfo directory, Action<ExclusiveFolderAccess> action)
{
Task.Run(async () => await ConcurrencyUtilities.ExecuteWithFileLockedAsync<object>(
directory.FullName,
lockedToken =>
{
action(new ExclusiveFolderAccess(directory));
return Task.FromResult(new Object());
},
CancellationToken.None)).Wait();
}
public static IEnumerable<FileInfo> Read(FileInfo file)
{
IEnumerable<FileInfo> ret = null;
Do(file.Directory, (folder) => {
ret = folder.LoadInventory(file);
});
return ret;
}
public IEnumerable<FileInfo> LoadInventory(FileInfo file)
{
file.Refresh();
if (!file.Exists)
{
throw new ArgumentException("Inventory file should exist.");
}
var inventory = new List<FileInfo>();
foreach (var p in File.ReadAllLines(file.FullName))
{
inventory.Add(new FileInfo(p));
}
return inventory;
}
public void SaveInventory(FileInfo file, IEnumerable<FileInfo> inventory)
{
_directory.Refresh();
if (!_directory.Exists)
{
_directory.Create();
}
File.WriteAllLines(file.FullName, inventory.Select((fi) => fi.FullName).ToList());
}
}
}
}