Files
Ayay/SHH.CameraSdk/Core/Services/FileStorageService.cs

165 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Text.Json;
namespace SHH.CameraSdk;
public class FileStorageService : IStorageService
{
public int ProcessId { get; }
private readonly string _baseDir;
private readonly string _devicesPath;
private readonly string _systemLogPath; // 系统日志路径
private readonly string _logsDir; // 设备日志文件夹
// 【关键优化】双锁分离:配置读写和日志读写互不干扰
private readonly SemaphoreSlim _configLock = new SemaphoreSlim(1, 1);
private readonly SemaphoreSlim _logLock = new SemaphoreSlim(1, 1);
// JSON 配置 (保持不变)
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
IncludeFields = true,
PropertyNameCaseInsensitive = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString
};
public FileStorageService(int processId)
{
ProcessId = processId;
// 目录结构:
// App_Data/Process_1/
// ├── devices.json
// ├── system.log
// └── logs/
// ├── device_101.log
// └── device_102.log
_baseDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", $"Process_{processId}");
_devicesPath = Path.Combine(_baseDir, "devices.json");
_systemLogPath = Path.Combine(_baseDir, "system.log");
_logsDir = Path.Combine(_baseDir, "logs");
if (!Directory.Exists(_baseDir)) Directory.CreateDirectory(_baseDir);
if (!Directory.Exists(_logsDir)) Directory.CreateDirectory(_logsDir);
Console.WriteLine($"[Storage] 服务就绪 | 日志路径: {_systemLogPath}");
}
// ==================================================================
// 1. 设备配置管理 (使用 _configLock)
// ==================================================================
public async Task SaveDevicesAsync(IEnumerable<VideoSourceConfig> configs)
{
await _configLock.WaitAsync();
try
{
var json = JsonSerializer.Serialize(configs, _jsonOptions);
await File.WriteAllTextAsync(_devicesPath, json);
}
catch (Exception ex)
{
Console.WriteLine($"[Storage] ❌ 保存配置失败: {ex.Message}");
}
finally { _configLock.Release(); }
}
public async Task<List<VideoSourceConfig>> LoadDevicesAsync()
{
if (!File.Exists(_devicesPath)) return new List<VideoSourceConfig>();
await _configLock.WaitAsync();
try
{
var json = await File.ReadAllTextAsync(_devicesPath);
if (string.IsNullOrWhiteSpace(json)) return new List<VideoSourceConfig>();
var list = JsonSerializer.Deserialize<List<VideoSourceConfig>>(json, _jsonOptions);
return list ?? new List<VideoSourceConfig>();
}
catch (Exception ex)
{
Console.WriteLine($"[Storage] ❌ 读取配置失败: {ex.Message}");
return new List<VideoSourceConfig>();
}
finally { _configLock.Release(); }
}
// ==================================================================
// 2. 系统操作日志 (使用 _logLock)
// ==================================================================
public async Task AppendSystemLogAsync(string action, string ip, string path)
{
// 格式: [时间] | IP | 动作 路径
var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var line = $"[{time}] | {ip} | {action} {path}";
await _logLock.WaitAsync(); // 等待日志锁
try
{
// 追加写入 (Async)
await File.AppendAllTextAsync(_systemLogPath, line + Environment.NewLine);
}
catch { /* 忽略日志写入错误,别崩了主程序 */ }
finally { _logLock.Release(); }
}
public async Task<List<string>> GetSystemLogsAsync(int count)
{
if (!File.Exists(_systemLogPath)) return new List<string> { "暂无日志" };
await _logLock.WaitAsync();
try
{
// 读取所有行 (如果日志文件非常大这里建议优化为倒序读取但几MB以内没问题)
var lines = await File.ReadAllLinesAsync(_systemLogPath);
// 取最后 N 行,并反转(让最新的显示在最上面)
return lines.TakeLast(count).Reverse().ToList();
}
catch (Exception ex)
{
return new List<string> { $"读取失败: {ex.Message}" };
}
finally { _logLock.Release(); }
}
// ==================================================================
// 3. 设备审计日志 (使用 _logLock)
// ==================================================================
public async Task AppendDeviceLogAsync(int deviceId, string message)
{
var path = Path.Combine(_logsDir, $"device_{deviceId}.log");
var time = DateTime.Now.ToString("MM-dd HH:mm:ss");
var line = $"{time} > {message}";
await _logLock.WaitAsync(); // 复用日志锁防止多文件同时IO导致磁盘抖动
try
{
await File.AppendAllTextAsync(path, line + Environment.NewLine);
}
catch { }
finally { _logLock.Release(); }
}
public async Task<List<string>> GetDeviceLogsAsync(int deviceId, int count)
{
var path = Path.Combine(_logsDir, $"device_{deviceId}.log");
if (!File.Exists(path)) return new List<string>();
await _logLock.WaitAsync();
try
{
var lines = await File.ReadAllLinesAsync(path);
return lines.TakeLast(count).Reverse().ToList();
}
catch
{
return new List<string>();
}
finally { _logLock.Release(); }
}
}