You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.3 KiB
106 lines
3.3 KiB
// Author: Gockner, Simon
|
|
// Created: 2020-02-12
|
|
// Copyright(c) 2020 SimonG. All Rights Reserved.
|
|
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using GBase.FileHandling.Exceptions;
|
|
using GBase.Interfaces;
|
|
using GBase.Interfaces.FileHandling;
|
|
|
|
namespace GBase.FileHandling
|
|
{
|
|
/// <summary>
|
|
/// Internal file handler
|
|
/// </summary>
|
|
public class FileHandler : IFileHandler
|
|
{
|
|
/// <summary>
|
|
/// The file extension for all GBase tables
|
|
/// </summary>
|
|
public const string GBASE_TABLE_FILE_EXTENSION = "gb";
|
|
|
|
private readonly List<IGBaseFile> _files;
|
|
private string _path;
|
|
|
|
/// <summary>
|
|
/// Internal file handler
|
|
/// </summary>
|
|
public FileHandler()
|
|
{
|
|
_files = new List<IGBaseFile>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize this <see cref="IFileHandler"/>
|
|
/// </summary>
|
|
/// <param name="path">The path of the database</param>
|
|
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
|
|
/// <returns>True if successful, false if not</returns>
|
|
public async Task<bool> Init(string path, CancellationToken cancellationToken)
|
|
{
|
|
_path = path;
|
|
return true; //TODO: initialize existing files
|
|
}
|
|
|
|
public IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table)
|
|
{
|
|
string directoryPath = Path.Combine(_path, table.FolderName);
|
|
|
|
//create directory if it doesn't exist
|
|
Directory.CreateDirectory(directoryPath);
|
|
|
|
//create new entry file
|
|
string filePath = $"{Path.Combine(directoryPath, entry.ToString())}.{GBASE_TABLE_FILE_EXTENSION}";
|
|
FileStream entryFile = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); //TODO: Stream has to be disposed
|
|
|
|
IGBaseFile file = new GBaseFile(entry, entryFile, filePath);
|
|
_files.Add(file);
|
|
|
|
return file.UseFile();
|
|
}
|
|
|
|
public async Task<bool> DeleteEntryFile<T>(T entry)
|
|
{
|
|
IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
|
|
if (file == default)
|
|
return false;
|
|
|
|
await file.File.DisposeAsync();
|
|
File.Delete(file.FilePath);
|
|
return true;
|
|
}
|
|
|
|
public async Task<IGBaseFile> RequestEntryFile<T>(T entry)
|
|
{
|
|
IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
|
|
if (file == default)
|
|
throw new FileNotExistingException<T>();
|
|
|
|
if (file.InUse)
|
|
await Task.Delay(1000);
|
|
|
|
return file.UseFile();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose used resources asynchronously
|
|
/// </summary>
|
|
/// <returns>A <see cref="ValueTask"/> to await</returns>
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
while (_files.Any(f => f.InUse))
|
|
{
|
|
await Task.Delay(1000);
|
|
}
|
|
|
|
foreach (var file in _files)
|
|
{
|
|
await file.File.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
} |