This commit is contained in:
Jöran Malek 2023-11-24 21:02:26 +01:00
parent 8909fb8b57
commit 762bf513f4
2 changed files with 102 additions and 14 deletions

View file

@ -0,0 +1,6 @@
namespace pdns_dhcp.Kea;
public class KeaDhcpLeaseFileReader
{
}

View file

@ -1,12 +1,18 @@
using System.Threading.Channels;
using Microsoft.Extensions.Hosting;
using pdns_dhcp.Options;
namespace pdns_dhcp.Kea;
public abstract class KeaDhcpLeaseWatcher : BackgroundService
public abstract class KeaDhcpLeaseWatcher : IHostedService
{
private readonly FileSystemWatcher _fsw;
private readonly string _leaseFile;
private Channel<FileSystemEventArgs>? _eventChannel;
private Task? _executeTask;
private CancellationTokenSource? _stoppingCts;
protected KeaDhcpServerOptions Options { get; }
@ -26,31 +32,107 @@ public abstract class KeaDhcpLeaseWatcher : BackgroundService
throw new ArgumentException($"{nameof(options.Leases)} must point to a file in an existing path.", nameof(options));
}
_fsw = new(leaseDirectory, leaseFile.ToString());
_leaseFile = leaseFile.ToString();
_fsw = new(leaseDirectory, _leaseFile);
_fsw.Changed += OnLeaseChanged;
_fsw.Created += OnLeaseChanged;
_fsw.Deleted += OnLeaseChanged;
_fsw.Renamed += OnLeaseRenamed;
_fsw.Error += OnLeaseError;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
_stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
_executeTask = Reading(_stoppingCts.Token);
return _executeTask is { IsCompleted: true } completed ? completed : Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (_executeTask is null)
{
return;
}
_fsw.EnableRaisingEvents = false;
try
{
_stoppingCts!.Cancel();
}
finally
{
TaskCompletionSource taskCompletionSource = new();
using (cancellationToken.Register(s => ((TaskCompletionSource)s!).SetCanceled(), taskCompletionSource))
{
await Task.WhenAny(_executeTask, taskCompletionSource.Task).ConfigureAwait(continueOnCapturedContext: false);
}
}
}
private async Task Reading(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using CancellationTokenSource loopCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
_eventChannel = Channel.CreateUnbounded<FileSystemEventArgs>();
_fsw.EnableRaisingEvents = true;
ValueTask reader = default;
try
{
await foreach (var @event in _eventChannel.Reader.ReadAllAsync(loopCts.Token))
{
switch (@event)
{
case { ChangeType: WatcherChangeTypes.Created }:
case RenamedEventArgs { ChangeType: WatcherChangeTypes.Renamed } renamed when renamed.Name == _leaseFile:
reader = FileReader(loopCts.Token);
break;
case { ChangeType: WatcherChangeTypes.Deleted }:
case RenamedEventArgs { ChangeType: WatcherChangeTypes.Renamed } renamed when renamed.OldName == _leaseFile:
loopCts.Cancel();
break;
case { ChangeType: WatcherChangeTypes.Changed }:
break;
}
}
}
catch { }
finally
{
_eventChannel.Writer.TryComplete();
try
{
await reader.ConfigureAwait(continueOnCapturedContext: false);
}
catch { }
}
}
ValueTask FileReader(CancellationToken stoppingToken)
{
return ValueTask.CompletedTask;
}
}
private void OnLeaseChanged(object sender, FileSystemEventArgs e)
{
throw new NotImplementedException();
var writer = _eventChannel?.Writer;
if (writer?.TryWrite(e) != false)
{
return;
}
var write = writer.WriteAsync(e);
if (write.IsCompleted)
{
return;
}
write.GetAwaiter().GetResult();
}
private void OnLeaseError(object sender, ErrorEventArgs e)
{
throw new NotImplementedException();
}
private void OnLeaseRenamed(object sender, RenamedEventArgs e)
{
throw new NotImplementedException();
_eventChannel?.Writer.Complete(e.GetException());
}
}