130 lines
4.0 KiB
C#
130 lines
4.0 KiB
C#
using System.Collections.Concurrent;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Inspectron.Epson.Queue;
|
|
|
|
public class PrintServer
|
|
{
|
|
private readonly IPrintService _printService;
|
|
private readonly ILogger _logger;
|
|
private readonly IJobStatusReporter _statusReporter;
|
|
private readonly Inspectron.Epson.PrintServer.Telemetry.IInsinTelemetry _telemetry;
|
|
private readonly ConcurrentDictionary<string, PrinterQueue> _printerQueues;
|
|
private readonly SemaphoreSlim _printDiscoveryLock = new(1, 1);
|
|
private int _readerCount = 0;
|
|
private readonly object _readerCountLock = new();
|
|
|
|
public PrintServer(IPrintService printService, ILogger logger, IJobStatusReporter statusReporter, Inspectron.Epson.PrintServer.Telemetry.IInsinTelemetry telemetry)
|
|
{
|
|
_printService = printService;
|
|
_logger = logger;
|
|
_statusReporter = statusReporter;
|
|
_telemetry = telemetry;
|
|
_printerQueues = new ConcurrentDictionary<string, PrinterQueue>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquires a read lock for print operations. Multiple print operations can run concurrently.
|
|
/// </summary>
|
|
public void EnterPrintLock()
|
|
{
|
|
_logger.LogDebug("Entering print lock");
|
|
lock (_readerCountLock)
|
|
{
|
|
_readerCount++;
|
|
if (_readerCount == 1)
|
|
{
|
|
_printDiscoveryLock.Wait();
|
|
}
|
|
}
|
|
_logger.LogDebug("Entered print lock");
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Releases the read lock after a print operation completes.
|
|
/// </summary>
|
|
public void ExitPrintLock()
|
|
{
|
|
_logger.LogDebug("Exiting print lock");
|
|
lock (_readerCountLock)
|
|
{
|
|
_readerCount--;
|
|
if (_readerCount == 0)
|
|
{
|
|
_printDiscoveryLock.Release();
|
|
}
|
|
}
|
|
_logger.LogDebug("Exited print lock");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquires a write lock for discovery operations. This blocks until all print operations complete
|
|
/// and prevents new print operations from starting.
|
|
/// </summary>
|
|
public async Task EnterDiscoveryLockAsync()
|
|
{
|
|
_logger.LogDebug("Entering discovery lock");
|
|
await _printDiscoveryLock.WaitAsync();
|
|
_logger.LogDebug("Entered discovery lock");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Releases the write lock after discovery completes.
|
|
/// </summary>
|
|
public void ExitDiscoveryLock()
|
|
{
|
|
_logger.LogDebug("Exiting discovery lock");
|
|
_printDiscoveryLock.Release();
|
|
_logger.LogDebug("Exited discovery lock");
|
|
}
|
|
|
|
public void RegisterPrinter(string printerIp)
|
|
{
|
|
var queue = new PrinterQueue(printerIp, _printService, _logger, this, _statusReporter, _telemetry);
|
|
if (_printerQueues.TryAdd(printerIp, queue))
|
|
{
|
|
queue.Start();
|
|
Console.WriteLine($"Printer {printerIp} registered");
|
|
}
|
|
}
|
|
|
|
public void UnregisterPrinter(string printerIp)
|
|
{
|
|
if (_printerQueues.TryRemove(printerIp, out var queue))
|
|
{
|
|
queue.StopAsync().Wait();
|
|
Console.WriteLine($"Printer {printerIp} unregistered");
|
|
}
|
|
}
|
|
|
|
public void SubmitJob(string printerIp, PrintJob job)
|
|
{
|
|
if (_printerQueues.TryGetValue(printerIp, out var queue))
|
|
{
|
|
queue.Enqueue(job);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning( $"Printer {printerIp} not found. Job cannot be submitted.");
|
|
_statusReporter.ReportStatusAsync(job, PrintJobStatus.Failed);
|
|
}
|
|
}
|
|
|
|
public Dictionary<string, int> GetQueueStatus()
|
|
{
|
|
var status = new Dictionary<string, int>();
|
|
foreach (var kvp in _printerQueues)
|
|
{
|
|
status[kvp.Key] = kvp.Value.QueueLength;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
public async Task ShutdownAsync()
|
|
{
|
|
var stopTasks = _printerQueues.Values.Select(q => q.StopAsync());
|
|
await Task.WhenAll(stopTasks);
|
|
Console.WriteLine("Print server shut down");
|
|
}
|
|
} |