using System;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Threading.Tasks;
|
using Microsoft.Extensions.Logging;
|
using WIDESEAWCS_S7Simulator.Core.Entities;
|
using WIDESEAWCS_S7Simulator.Core.Enums;
|
using WIDESEAWCS_S7Simulator.Core.Interfaces;
|
using WIDESEAWCS_S7Simulator.Core.Persistence;
|
using WIDESEAWCS_S7Simulator.Core.Server;
|
|
namespace WIDESEAWCS_S7Simulator.Core.Manager
|
{
|
/// <summary>
|
/// 仿真器实例管理器实现
|
/// 管理多个S7服务器实例的生命周期,提供线程安全的CRUD操作
|
/// </summary>
|
public class SimulatorInstanceManager : ISimulatorInstanceManager
|
{
|
private readonly ConcurrentDictionary<string, IS7ServerInstance> _instances = new();
|
private readonly IPersistenceService _persistenceService;
|
private readonly ILogger<SimulatorInstanceManager> _logger;
|
private readonly ILoggerFactory _loggerFactory;
|
|
/// <inheritdoc/>
|
public event EventHandler<InstanceStateChangedEventArgs>? InstanceStateChanged;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="persistenceService">持久化服务</param>
|
/// <param name="logger">日志记录器</param>
|
/// <param name="loggerFactory">日志工厂</param>
|
public SimulatorInstanceManager(
|
IPersistenceService persistenceService,
|
ILogger<SimulatorInstanceManager> logger,
|
ILoggerFactory loggerFactory)
|
{
|
_persistenceService = persistenceService ?? throw new ArgumentNullException(nameof(persistenceService));
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
}
|
|
/// <inheritdoc/>
|
public IReadOnlyList<IS7ServerInstance> GetAllInstances()
|
{
|
return _instances.Values.ToList().AsReadOnly();
|
}
|
|
/// <inheritdoc/>
|
public IS7ServerInstance? GetInstance(string instanceId)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
return null;
|
}
|
|
_instances.TryGetValue(instanceId, out var instance);
|
return instance;
|
}
|
|
/// <inheritdoc/>
|
public bool InstanceExists(string instanceId)
|
{
|
return !string.IsNullOrWhiteSpace(instanceId) && _instances.ContainsKey(instanceId);
|
}
|
|
/// <inheritdoc/>
|
public async Task<IS7ServerInstance> CreateInstanceAsync(InstanceConfig config)
|
{
|
if (config == null)
|
{
|
throw new ArgumentNullException(nameof(config));
|
}
|
|
// 如果没有提供ID,生成新的GUID
|
if (string.IsNullOrWhiteSpace(config.Id))
|
{
|
config.Id = Guid.NewGuid().ToString("N");
|
_logger.LogDebug("为实例生成新ID: {InstanceId}", config.Id);
|
}
|
|
// 检查ID是否已存在
|
if (_instances.ContainsKey(config.Id))
|
{
|
throw new InvalidOperationException($"实例ID {config.Id} 已存在");
|
}
|
|
try
|
{
|
// 创建实例
|
var instanceLogger = _loggerFactory.CreateLogger<S7ServerInstance>();
|
var instance = new S7ServerInstance(config, instanceLogger);
|
|
// 添加到字典
|
if (!_instances.TryAdd(config.Id, instance))
|
{
|
throw new InvalidOperationException($"无法将实例 {config.Id} 添加到管理器");
|
}
|
|
// 保存配置
|
await _persistenceService.SaveInstanceConfigAsync(config);
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = config.Id,
|
OldStatus = InstanceStatus.Stopped,
|
NewStatus = InstanceStatus.Stopped,
|
InstanceState = instance.GetState()
|
});
|
|
_logger.LogInformation("已创建实例 {InstanceId} ({InstanceName})", config.Id, config.Name);
|
return instance;
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "创建实例 {InstanceId} 时发生错误", config.Id);
|
throw;
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task<bool> StartInstanceAsync(string instanceId)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
_logger.LogWarning("尝试启动实例时提供了空ID");
|
return false;
|
}
|
|
if (!_instances.TryGetValue(instanceId, out var instance))
|
{
|
_logger.LogWarning("尝试启动不存在的实例 {InstanceId}", instanceId);
|
return false;
|
}
|
|
try
|
{
|
var oldState = instance.GetState();
|
var oldStatus = oldState.Status;
|
|
// 启动实例
|
var success = instance.Start();
|
|
if (success)
|
{
|
var newState = instance.GetState();
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = instanceId,
|
OldStatus = oldStatus,
|
NewStatus = newState.Status,
|
InstanceState = newState
|
});
|
|
_logger.LogInformation("实例 {InstanceId} 已启动", instanceId);
|
}
|
else
|
{
|
_logger.LogWarning("实例 {InstanceId} 启动失败", instanceId);
|
}
|
|
return success;
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "启动实例 {InstanceId} 时发生异常", instanceId);
|
return false;
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task StopInstanceAsync(string instanceId)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
_logger.LogWarning("尝试停止实例时提供了空ID");
|
return;
|
}
|
|
if (!_instances.TryGetValue(instanceId, out var instance))
|
{
|
_logger.LogWarning("尝试停止不存在的实例 {InstanceId}", instanceId);
|
return;
|
}
|
|
try
|
{
|
var oldState = instance.GetState();
|
var oldStatus = oldState.Status;
|
|
// 停止实例
|
instance.Stop();
|
|
// 同步内存数据到持久化存储
|
await _persistenceService.SaveMemoryDataAsync(instanceId, instance.MemoryStore);
|
|
var newState = instance.GetState();
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = instanceId,
|
OldStatus = oldStatus,
|
NewStatus = newState.Status,
|
InstanceState = newState
|
});
|
|
_logger.LogInformation("实例 {InstanceId} 已停止", instanceId);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "停止实例 {InstanceId} 时发生异常", instanceId);
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task<bool> RestartInstanceAsync(string instanceId)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
_logger.LogWarning("尝试重启实例时提供了空ID");
|
return false;
|
}
|
|
if (!_instances.TryGetValue(instanceId, out var instance))
|
{
|
_logger.LogWarning("尝试重启不存在的实例 {InstanceId}", instanceId);
|
return false;
|
}
|
|
try
|
{
|
var oldState = instance.GetState();
|
var oldStatus = oldState.Status;
|
|
// 重启实例
|
var success = instance.Restart();
|
|
if (success)
|
{
|
var newState = instance.GetState();
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = instanceId,
|
OldStatus = oldStatus,
|
NewStatus = newState.Status,
|
InstanceState = newState
|
});
|
|
_logger.LogInformation("实例 {InstanceId} 已重启", instanceId);
|
}
|
else
|
{
|
_logger.LogWarning("实例 {InstanceId} 重启失败", instanceId);
|
}
|
|
return success;
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "重启实例 {InstanceId} 时发生异常", instanceId);
|
return false;
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task DeleteInstanceAsync(string instanceId, bool deleteConfig = true)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
_logger.LogWarning("尝试删除实例时提供了空ID");
|
return;
|
}
|
|
if (!_instances.TryRemove(instanceId, out var instance))
|
{
|
_logger.LogWarning("尝试删除不存在的实例 {InstanceId}", instanceId);
|
return;
|
}
|
|
try
|
{
|
var oldState = instance.GetState();
|
|
// 停止实例
|
instance.Stop();
|
|
// 释放实例资源
|
instance.Dispose();
|
|
// 删除配置文件
|
if (deleteConfig)
|
{
|
await _persistenceService.DeleteInstanceConfigAsync(instanceId);
|
}
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = instanceId,
|
OldStatus = oldState.Status,
|
NewStatus = InstanceStatus.Stopped,
|
InstanceState = oldState
|
});
|
|
_logger.LogInformation("实例 {InstanceId} 已删除", instanceId);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "删除实例 {InstanceId} 时发生异常", instanceId);
|
}
|
}
|
|
/// <inheritdoc/>
|
public InstanceState? GetInstanceState(string instanceId)
|
{
|
if (string.IsNullOrWhiteSpace(instanceId))
|
{
|
return null;
|
}
|
|
if (!_instances.TryGetValue(instanceId, out var instance))
|
{
|
return null;
|
}
|
|
return instance.GetState();
|
}
|
|
/// <inheritdoc/>
|
public IReadOnlyList<InstanceState> GetAllInstanceStates()
|
{
|
return _instances.Values
|
.Select(i => i.GetState())
|
.ToList()
|
.AsReadOnly();
|
}
|
|
/// <inheritdoc/>
|
public async Task LoadSavedInstancesAsync(bool autoStart = true)
|
{
|
try
|
{
|
_logger.LogInformation("开始加载已保存的实例配置...");
|
|
// 加载所有配置
|
var configs = await _persistenceService.LoadAllInstanceConfigsAsync();
|
|
if (configs == null || configs.Count == 0)
|
{
|
_logger.LogInformation("没有找到已保存的实例配置");
|
return;
|
}
|
|
_logger.LogInformation("找到 {Count} 个已保存的实例配置", configs.Count);
|
|
foreach (var config in configs)
|
{
|
try
|
{
|
// 创建实例
|
var instanceLogger = _loggerFactory.CreateLogger<S7ServerInstance>();
|
var instance = new S7ServerInstance(config, instanceLogger);
|
|
// 添加到字典
|
if (_instances.TryAdd(config.Id, instance))
|
{
|
// 加载内存数据
|
try
|
{
|
await _persistenceService.LoadMemoryDataAsync(config.Id, instance.MemoryStore);
|
_logger.LogDebug("已加载实例 {InstanceId} 的内存数据", config.Id);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogWarning(ex, "加载实例 {InstanceId} 的内存数据时发生警告", config.Id);
|
}
|
|
// 如果配置了自动启动,则启动实例
|
if (autoStart && config.AutoStart)
|
{
|
_logger.LogInformation("自动启动实例 {InstanceId} ({InstanceName})", config.Id, config.Name);
|
var success = instance.Start();
|
if (success)
|
{
|
_logger.LogInformation("实例 {InstanceId} 自动启动成功", config.Id);
|
}
|
else
|
{
|
_logger.LogWarning("实例 {InstanceId} 自动启动失败", config.Id);
|
}
|
}
|
|
// 触发状态变化事件
|
OnInstanceStateChanged(new InstanceStateChangedEventArgs
|
{
|
InstanceId = config.Id,
|
OldStatus = InstanceStatus.Stopped,
|
NewStatus = instance.State.Status,
|
InstanceState = instance.GetState()
|
});
|
|
_logger.LogInformation("已加载实例 {InstanceId} ({InstanceName})", config.Id, config.Name);
|
}
|
else
|
{
|
_logger.LogWarning("实例 {InstanceId} 已存在,跳过加载", config.Id);
|
}
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "加载实例 {InstanceId} 时发生错误", config.Id);
|
}
|
}
|
|
_logger.LogInformation("实例加载完成,共加载 {Count} 个实例", _instances.Count);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "加载已保存的实例时发生异常");
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task StopAllInstancesAsync()
|
{
|
_logger.LogInformation("开始停止所有实例...");
|
|
var instanceIds = _instances.Keys.ToList();
|
|
foreach (var instanceId in instanceIds)
|
{
|
try
|
{
|
await StopInstanceAsync(instanceId);
|
}
|
catch (Exception ex)
|
{
|
_logger.LogError(ex, "停止实例 {InstanceId} 时发生异常", instanceId);
|
}
|
}
|
|
_logger.LogInformation("所有实例已停止");
|
}
|
|
/// <inheritdoc/>
|
public int GetRunningInstanceCount()
|
{
|
return _instances.Values.Count(i => i.State.Status == InstanceStatus.Running);
|
}
|
|
/// <inheritdoc/>
|
public int GetTotalInstanceCount()
|
{
|
return _instances.Count;
|
}
|
|
/// <summary>
|
/// 触发实例状态变化事件
|
/// </summary>
|
/// <param name="e">事件参数</param>
|
protected virtual void OnInstanceStateChanged(InstanceStateChangedEventArgs e)
|
{
|
InstanceStateChanged?.Invoke(this, e);
|
}
|
}
|
}
|