wenxiangchao
4 天以前 2e889843b4c171f2d6ad8e0d53084040703d11f6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
using System;
using System.Collections.Generic;
using System.Linq;
using log4net;
using Plugin.DeviceDebug.Entity;
using Aging.Infrastructure.Contracts;
 
namespace Plugin.DeviceDebug.Model
{
    /// <summary>
    /// 调试会话管理器 - 负责状态机转换和权限校验
    /// </summary>
    public class DebugSessionManager
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(DebugSessionManager));
        private readonly DeviceDebugModel _model;
        private readonly IResourceManager? _resourceManager;
 
        // 内存中的活跃会话缓存
        private readonly Dictionary<string, DebugSession> _activeSessions = new();
 
        public DebugSessionManager(DeviceDebugModel model, IResourceManager? resourceManager = null)
        {
            _model = model;
            _resourceManager = resourceManager;
        }
 
        /// <summary>
        /// 打开会话(ReadOnly模式)
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 请求进入维护模式(ReadOnly → AcquiringMaintenance)
        /// 检查:设备是否有生产Reserved
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 激活维护模式(AcquiringMaintenance → MaintenanceActive)
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 关闭会话(MaintenanceActive → Closing → Closed)
        /// 执行安全状态检查
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 故障处理(任意 → Faulted)
        /// </summary>
        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);
            }
        }
 
        /// <summary>
        /// 标记需要恢复(任意 → RecoveryRequired)
        /// </summary>
        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);
            }
        }
 
        /// <summary>
        /// 验证命令是否允许执行(只有 MaintenanceActive 状态允许写操作)
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 获取会话状态
        /// </summary>
        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;
            }
        }
 
        /// <summary>
        /// 获取设备当前会话(如果有)
        /// </summary>
        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;
            }
        }
    }
}