Watcher
This commit is contained in:
parent
8909fb8b57
commit
762bf513f4
2 changed files with 102 additions and 14 deletions
6
src/pdns-dhcp/Kea/KeaDhcpLeaseFileReader.cs
Normal file
6
src/pdns-dhcp/Kea/KeaDhcpLeaseFileReader.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace pdns_dhcp.Kea;
|
||||||
|
|
||||||
|
public class KeaDhcpLeaseFileReader
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
|
using System.Threading.Channels;
|
||||||
|
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
using pdns_dhcp.Options;
|
using pdns_dhcp.Options;
|
||||||
|
|
||||||
namespace pdns_dhcp.Kea;
|
namespace pdns_dhcp.Kea;
|
||||||
|
|
||||||
public abstract class KeaDhcpLeaseWatcher : BackgroundService
|
public abstract class KeaDhcpLeaseWatcher : IHostedService
|
||||||
{
|
{
|
||||||
private readonly FileSystemWatcher _fsw;
|
private readonly FileSystemWatcher _fsw;
|
||||||
|
private readonly string _leaseFile;
|
||||||
|
private Channel<FileSystemEventArgs>? _eventChannel;
|
||||||
|
private Task? _executeTask;
|
||||||
|
private CancellationTokenSource? _stoppingCts;
|
||||||
|
|
||||||
protected KeaDhcpServerOptions Options { get; }
|
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));
|
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.Changed += OnLeaseChanged;
|
||||||
_fsw.Created += OnLeaseChanged;
|
|
||||||
_fsw.Deleted += OnLeaseChanged;
|
|
||||||
_fsw.Renamed += OnLeaseRenamed;
|
|
||||||
_fsw.Error += OnLeaseError;
|
_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)
|
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)
|
private void OnLeaseError(object sender, ErrorEventArgs e)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_eventChannel?.Writer.Complete(e.GetException());
|
||||||
}
|
|
||||||
|
|
||||||
private void OnLeaseRenamed(object sender, RenamedEventArgs e)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue