Files
Print_server/Inspectron.Epson/Queue/PrintServer.cs

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");
}
}