cs-codex-dist-tests/Framework/FileUtils/FileManager.cs

163 lines
4.7 KiB
C#
Raw Normal View History

2023-04-12 14:06:04 +00:00
using Logging;
using Utils;
2023-04-12 14:06:04 +00:00
namespace FileUtils
2023-04-12 14:06:04 +00:00
{
public interface IFileManager
{
2023-09-13 08:03:11 +00:00
TrackedFile CreateEmptyFile(string label = "");
TrackedFile GenerateFile(ByteSize size, string label = "");
2024-07-01 13:59:08 +00:00
TrackedFile GenerateFile(Action<IGenerateOption> options, string label = "");
2023-09-13 08:03:11 +00:00
void DeleteAllFiles();
void ScopedFiles(Action action);
T ScopedFiles<T>(Func<T> action);
2023-04-12 14:06:04 +00:00
}
2024-07-01 13:59:08 +00:00
public interface IGenerateOption
{
IGenerateOption Random(ByteSize size);
IGenerateOption StringRepeat(string str, ByteSize size);
IGenerateOption StringRepeat(string str, int times);
IGenerateOption ByteRepeat(byte[] bytes, ByteSize size);
IGenerateOption ByteRepeat(byte[] bytes, int times);
}
2023-04-12 14:06:04 +00:00
public class FileManager : IFileManager
{
2024-07-01 13:59:08 +00:00
private static readonly NumberSource folderNumberSource = new NumberSource(0);
2023-09-12 08:31:55 +00:00
private readonly ILog log;
2023-04-12 14:06:04 +00:00
private readonly string folder;
2023-09-12 11:32:06 +00:00
private readonly List<List<TrackedFile>> fileSetStack = new List<List<TrackedFile>>();
2023-04-12 14:06:04 +00:00
2024-07-01 13:59:08 +00:00
public const int ChunkSize = 1024 * 1024 * 100;
2023-09-12 08:31:55 +00:00
public FileManager(ILog log, string rootFolder)
2023-04-12 14:06:04 +00:00
{
folder = Path.Combine(rootFolder, folderNumberSource.GetNextNumber().ToString("D5"));
2023-04-12 14:06:04 +00:00
this.log = log;
}
2023-09-13 08:03:11 +00:00
public TrackedFile CreateEmptyFile(string label = "")
2023-04-12 14:06:04 +00:00
{
2023-09-21 08:33:09 +00:00
var path = Path.Combine(folder, Guid.NewGuid().ToString() + ".bin");
EnsureDirectory();
2023-09-12 11:32:06 +00:00
var result = new TrackedFile(log, path, label);
2023-04-12 14:06:04 +00:00
File.Create(result.Filename).Close();
if (fileSetStack.Any()) fileSetStack.Last().Add(result);
2023-04-12 14:06:04 +00:00
return result;
}
2024-07-01 13:59:08 +00:00
public TrackedFile GenerateFile(ByteSize size, string label = "")
{
return GenerateFile(o => o.Random(size), label);
}
public TrackedFile GenerateFile(Action<IGenerateOption> options, string label = "")
2023-04-12 14:06:04 +00:00
{
2023-06-07 07:59:00 +00:00
var sw = Stopwatch.Begin(log);
2024-07-01 13:59:08 +00:00
var result = RunGenerators(options, label);
2024-03-22 12:36:33 +00:00
sw.End($"Generated file {result.Describe()}.");
2023-04-12 14:06:04 +00:00
return result;
}
2023-09-13 08:03:11 +00:00
public void DeleteAllFiles()
2023-04-12 14:06:04 +00:00
{
DeleteDirectory();
2023-04-12 14:06:04 +00:00
}
public void ScopedFiles(Action action)
{
PushFileSet();
2024-04-01 18:40:03 +00:00
try
{
action();
}
finally
{
PopFileSet();
}
}
public T ScopedFiles<T>(Func<T> action)
{
PushFileSet();
2024-04-01 18:40:03 +00:00
try
{
return action();
}
finally
{
PopFileSet();
}
}
private void PushFileSet()
{
2023-09-12 11:32:06 +00:00
fileSetStack.Add(new List<TrackedFile>());
}
private void PopFileSet()
{
if (!fileSetStack.Any()) return;
var pop = fileSetStack.Last();
fileSetStack.Remove(pop);
foreach (var file in pop)
{
2023-09-21 08:33:09 +00:00
File.Delete(file.Filename);
}
2023-09-21 08:33:09 +00:00
// If the folder is now empty, delete it too.
if (!Directory.GetFiles(folder).Any()) DeleteDirectory();
}
2024-07-01 13:59:08 +00:00
private TrackedFile RunGenerators(Action<IGenerateOption> options, string label)
2023-06-07 07:59:00 +00:00
{
2023-09-13 08:03:11 +00:00
var result = CreateEmptyFile(label);
2024-07-01 13:59:08 +00:00
var generators = GetGenerators(options);
CheckSpaceAvailable(result, generators.GetRequiredSpace());
2023-06-07 07:59:00 +00:00
2024-07-01 13:59:08 +00:00
using var stream = new FileStream(result.Filename, FileMode.Append);
generators.Run(stream);
2023-06-07 07:59:00 +00:00
return result;
}
2024-07-01 13:59:08 +00:00
private GeneratorCollection GetGenerators(Action<IGenerateOption> options)
{
var result = new GeneratorCollection();
options(result);
return result;
}
private void CheckSpaceAvailable(TrackedFile testFile, long requiredSize)
2023-06-07 07:59:00 +00:00
{
var file = new FileInfo(testFile.Filename);
var drive = new DriveInfo(file.Directory!.Root.FullName);
var spaceAvailable = drive.TotalFreeSpace;
2024-07-01 13:59:08 +00:00
if (spaceAvailable < requiredSize)
2023-06-07 07:59:00 +00:00
{
2023-09-20 08:51:47 +00:00
var msg = $"Not enough disk space. " +
2024-07-01 13:59:08 +00:00
$"{Formatter.FormatByteSize(requiredSize)} required. " +
2023-06-07 07:59:00 +00:00
$"{Formatter.FormatByteSize(spaceAvailable)} available.";
log.Log(msg);
2023-09-20 08:51:47 +00:00
throw new Exception(msg);
2023-06-07 07:59:00 +00:00
}
}
private void EnsureDirectory()
{
2023-09-21 08:33:09 +00:00
Directory.CreateDirectory(folder);
}
private void DeleteDirectory()
{
2023-09-21 08:33:09 +00:00
if (Directory.Exists(folder)) Directory.Delete(folder, true);
}
2023-04-12 14:06:04 +00:00
}
}