using System;
using System.Collections.Generic;
using System.Linq;
using log4net;
using Plugin.DeviceDebug.Entity;
using Aging.Infrastructure.Contracts;
namespace Plugin.DeviceDebug.Model
{
///
/// 调试会话管理器 - 负责状态机转换和权限校验
///
public class DebugSessionManager
{
private static readonly ILog log = LogManager.GetLogger(typeof(DebugSessionManager));
private readonly DeviceDebugModel _model;
private readonly IResourceManager? _resourceManager;
// 内存中的活跃会话缓存
private readonly Dictionary _activeSessions = new();
public DebugSessionManager(DeviceDebugModel model, IResourceManager? resourceManager = null)
{
_model = model;
_resourceManager = resourceManager;
}
///
/// 打开会话(ReadOnly模式)
///
public DebugSession OpenSession(string deviceId, string operatorId, string operatorName, string effectiveVersion)
{
try
{
// 检查是否已有活跃会话
var existingSession = GetActiveSessionByDevice(deviceId);
if (existingSession != null)
{
log.Warn($"设备 {deviceId} 已有活跃会话: {existingSession.SessionId}");
return existingSession;
}
var session = new DebugSession
{
DeviceId = deviceId,
OperatorId = operatorId,
OperatorName = operatorName,
EffectiveVersion = effectiveVersion,
State = DebugSessionState.ReadOnly
};
// 持久化到数据库
_model.CreateSession(session);
// 更新内存缓存
_activeSessions[session.SessionId] = session;
log.Info($"打开会话: {session.SessionId}, 设备: {deviceId}, 操作员: {operatorName}");
return session;
}
catch (Exception ex)
{
log.Error($"打开会话失败: {ex.Message}", ex);
throw;
}
}
///
/// 请求进入维护模式(ReadOnly → AcquiringMaintenance)
/// 检查:设备是否有生产Reserved
///
public bool RequestMaintenance(string sessionId)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
return false;
}
// 验证状态转换
if (session.State != DebugSessionState.ReadOnly)
{
log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法请求维护模式");
return false;
}
// 检查设备是否有生产Reserved(与资源预约系统集成)
if (_resourceManager != null)
{
var resourceKey = new ResourceKey(session.DeviceId, "Generic");
var ownerToken = new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId);
try
{
var reservation = _resourceManager.ReserveAsync(
ownerToken, resourceKey, CancellationToken.None).GetAwaiter().GetResult();
session.ReservationRef = reservation.ReservationId;
}
catch (ResourceConflictException)
{
log.Warn($"设备 {session.DeviceId} 已被生产预约占用,拒绝维护请求");
return false;
}
}
else
{
// 降级模式:无 ResourceManager 时允许所有请求(向后兼容)
log.Warn("ResourceManager 未初始化,跳过资源预约检查");
}
// 状态转换
session.State = DebugSessionState.AcquiringMaintenance;
// 持久化
_model.UpdateSession(session);
log.Info($"会话 {sessionId} 请求维护模式");
return true;
}
catch (Exception ex)
{
log.Error($"请求维护模式失败: {ex.Message}", ex);
return false;
}
}
///
/// 激活维护模式(AcquiringMaintenance → MaintenanceActive)
///
public void ActivateMaintenance(string sessionId)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
throw new InvalidOperationException($"会话不存在: {sessionId}");
}
// 验证状态转换
if (session.State != DebugSessionState.AcquiringMaintenance)
{
log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法激活维护模式");
throw new InvalidOperationException($"会话 {sessionId} 当前状态为 {session.State},无法激活维护模式");
}
// 状态转换
session.State = DebugSessionState.MaintenanceActive;
// 持久化
_model.UpdateSession(session);
log.Info($"会话 {sessionId} 激活维护模式");
}
catch (Exception ex)
{
log.Error($"激活维护模式失败: {ex.Message}", ex);
throw;
}
}
///
/// 关闭会话(MaintenanceActive → Closing → Closed)
/// 执行安全状态检查
///
public void CloseSession(string sessionId)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
throw new InvalidOperationException($"会话不存在: {sessionId}");
}
// 验证状态转换(只有 MaintenanceActive 可以关闭)
if (session.State != DebugSessionState.MaintenanceActive)
{
log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法关闭");
throw new InvalidOperationException($"会话 {sessionId} 当前状态为 {session.State},无法关闭");
}
// 状态转换: MaintenanceActive → Closing
session.State = DebugSessionState.Closing;
_model.UpdateSession(session);
log.Debug($"会话 {sessionId} 进入关闭中状态");
// 执行安全状态检查:释放资源预约
if (_resourceManager != null && !string.IsNullOrEmpty(session.ReservationRef))
{
try
{
var resourceKey = new ResourceKey(session.DeviceId, "Generic");
var ownerToken = new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId);
_resourceManager.ReleaseReservationAsync(
ownerToken, resourceKey, CancellationToken.None).GetAwaiter().GetResult();
log.Info($"已释放设备 {session.DeviceId} 的资源预约");
}
catch (Exception ex)
{
log.Error($"释放资源预约失败: {ex.Message}", ex);
// 不阻止关闭流程,但记录警告
}
}
// 状态转换: Closing → Closed
session.State = DebugSessionState.Closed;
session.ClosedAt = DateTime.Now;
_model.UpdateSession(session);
// 从缓存中移除
_activeSessions.Remove(sessionId);
log.Info($"会话 {sessionId} 已关闭");
}
catch (Exception ex)
{
log.Error($"关闭会话失败: {ex.Message}", ex);
throw;
}
}
///
/// 故障处理(任意 → Faulted)
///
public void FaultSession(string sessionId, string errorMessage)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
return;
}
// 记录当前状态
var previousState = session.State;
// 状态转换
session.State = DebugSessionState.Faulted;
// 持久化
_model.UpdateSession(session);
log.Error($"会话 {sessionId} 发生故障,从 {previousState} 转为 Faulted: {errorMessage}");
}
catch (Exception ex)
{
log.Error($"标记故障状态失败: {ex.Message}", ex);
}
}
///
/// 标记需要恢复(任意 → RecoveryRequired)
///
public void MarkRecoveryRequired(string sessionId)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
return;
}
// 记录当前状态
var previousState = session.State;
// 状态转换
session.State = DebugSessionState.RecoveryRequired;
// 持久化
_model.UpdateSession(session);
log.Warn($"会话 {sessionId} 标记为需要恢复,从 {previousState} 转为 RecoveryRequired");
}
catch (Exception ex)
{
log.Error($"标记恢复状态失败: {ex.Message}", ex);
}
}
///
/// 验证命令是否允许执行(只有 MaintenanceActive 状态允许写操作)
///
public bool ValidateCommand(string sessionId, DebugCommand command)
{
try
{
if (!_activeSessions.TryGetValue(sessionId, out var session))
{
log.Warn($"会话不存在: {sessionId}");
return false;
}
// 只有 MaintenanceActive 状态允许写操作
bool allowed = session.State == DebugSessionState.MaintenanceActive;
if (!allowed)
{
log.Warn($"会话 {sessionId} 状态为 {session.State},拒绝执行命令: {command.CommandType}");
}
// 增加资源预约验证
if (allowed && _resourceManager != null)
{
var resourceKey = new ResourceKey(session.DeviceId, "Generic");
allowed = _resourceManager.ValidateOwner(
new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId),
resourceKey);
if (!allowed)
{
log.Warn($"会话 {sessionId} 资源预约验证失败,拒绝执行命令: {command.CommandType}");
}
}
return allowed;
}
catch (Exception ex)
{
log.Error($"验证命令失败: {ex.Message}", ex);
return false;
}
}
///
/// 获取会话状态
///
public DebugSessionState? GetSessionState(string sessionId)
{
try
{
if (_activeSessions.TryGetValue(sessionId, out var session))
{
return session.State;
}
// 从数据库查询
var dbSession = _model.GetSession(sessionId);
return dbSession?.State;
}
catch (Exception ex)
{
log.Error($"获取会话状态失败: {ex.Message}", ex);
return null;
}
}
///
/// 获取设备当前会话(如果有)
///
public DebugSession? GetActiveSessionByDevice(string deviceId)
{
try
{
// 先从内存缓存查找
var cachedSession = _activeSessions.Values
.FirstOrDefault(s => s.DeviceId == deviceId && s.State != DebugSessionState.Closed);
if (cachedSession != null)
{
return cachedSession;
}
// 从数据库查询
var activeSessions = _model.GetActiveSessionsByDevice(deviceId);
return activeSessions.FirstOrDefault();
}
catch (Exception ex)
{
log.Error($"获取设备活跃会话失败: {ex.Message}", ex);
return null;
}
}
}
}