//============================================================== // Copyright (C) 2019 Inc. All rights reserved. // //============================================================== // Create by 种道洋 at 2019/12/27 18:45:02. // Version 1.0 // 种道洋 //============================================================== using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Cdy.Tag { /// /// /// public class DataFileManager { #region ... Variables ... private Dictionary> mTimeFileMaps = new Dictionary>(); /// /// /// private Dictionary mLogFileMaps = new Dictionary(); /// /// 记录所有变量历史记录中最后的时间 /// internal static Dictionary CurrentDateTime = new Dictionary(); /// /// /// private string mDatabaseName; /// /// 数据文件扩展名 /// public const string DataFileExtends = ".dbd"; /// /// /// public const string LogFileExtends = ".log"; /// /// /// public const int FileHeadSize = 84; private System.IO.FileSystemWatcher hisDataWatcher; private System.IO.FileSystemWatcher logDataWatcher; private object mLocker = new object(); private ManualResetEvent mResetEvent = new ManualResetEvent(false); private bool mIsClosed = false; private Dictionary mFileCach = new Dictionary(); private Dictionary mHisFileCach = new Dictionary(); private int mResetCount = 0; private Thread mFileProcessThread; #endregion ...Variables... #region ... Events ... #endregion ...Events... #region ... Constructor... /// /// /// public DataFileManager(string dbname) { mDatabaseName = dbname; } #endregion ...Constructor... #region ... Properties ... /// /// 单个文件内变量的个数 /// public int TagCountOneFile { get; set; } = 100000; /// /// /// public string PrimaryHisDataPath { get; set; } /// /// /// public string PrimaryLogDataPath { get; set; } /// /// /// public string BackHisDataPath { get; set; } #endregion ...Properties... #region ... Methods ... /// /// /// /// private string GetPrimaryHisDataPath() { return string.IsNullOrEmpty(PrimaryHisDataPath) ? PathHelper.helper.GetDataPath(this.mDatabaseName,"HisData") : System.IO.Path.IsPathRooted(PrimaryHisDataPath) ? PrimaryHisDataPath : PathHelper.helper.GetDataPath(this.mDatabaseName,PrimaryHisDataPath); } /// /// /// /// private string GetPrimaryLogDataPath() { return string.IsNullOrEmpty(PrimaryLogDataPath)?PathHelper.helper.GetDataPath(this.mDatabaseName, "Log"): System.IO.Path.IsPathRooted(PrimaryLogDataPath) ? PrimaryLogDataPath : PathHelper.helper.GetDataPath(this.mDatabaseName, PrimaryLogDataPath); } /// /// /// /// private string GetBackHisDataPath() { return string.IsNullOrEmpty(BackHisDataPath) ? PathHelper.helper.GetDataPath(this.mDatabaseName, "HisData") : System.IO.Path.IsPathRooted(BackHisDataPath) ? BackHisDataPath : PathHelper.helper.GetDataPath(this.mDatabaseName, BackHisDataPath); } /// /// /// public async Task Int() { string datapath = GetPrimaryHisDataPath(); await Scan(datapath); if (System.IO.Directory.Exists(datapath)) { hisDataWatcher = new System.IO.FileSystemWatcher(GetPrimaryHisDataPath()); hisDataWatcher.Changed += HisDataWatcher_Changed; hisDataWatcher.EnableRaisingEvents = true; } string logpath = GetPrimaryLogDataPath(); ScanLogFile(logpath); if (System.IO.Directory.Exists(logpath)) { logDataWatcher = new System.IO.FileSystemWatcher(logpath); logDataWatcher.Changed += LogDataWatcher_Changed; logDataWatcher.EnableRaisingEvents = true; } foreach (var vv in this.mTimeFileMaps) { foreach (var vvv in vv.Value) { vvv.Value.UpdateLastDatetime(); } } //await Scan(GetBackHisDataPath()); } /// /// /// public void Start() { mIsClosed= false; mFileProcessThread = new Thread(FileProcess); mFileProcessThread.IsBackground = true; mFileProcessThread.Start(); } /// /// /// public void Stop() { mIsClosed = true; mResetEvent.Close(); while (mFileProcessThread.IsAlive) Thread.Sleep(1); } /// /// /// private void FileProcess() { List> ltmp = null; while (!mIsClosed) { mResetEvent.WaitOne(); mResetEvent.Reset(); if (mIsClosed) break; mResetCount = 0; while (mResetCount<10) { Thread.Sleep(100); mResetCount++; } if(mFileCach.Count>0) { lock(mLocker) { ltmp = mFileCach.ToList(); mFileCach.Clear(); } foreach(var vv in ltmp) { LoggerService.Service.Info("DataFileMananger", "LogFile " + vv.Value + " add to FileCach!"); ParseLogFile(vv.Key); } } if(mHisFileCach.Count>0) { lock (mLocker) { ltmp = this.mHisFileCach.ToList(); mHisFileCach.Clear(); } foreach (var vv in ltmp) { var vifno = new System.IO.FileInfo(vv.Key); if (vv.Value == System.IO.WatcherChangeTypes.Created) { LoggerService.Service.Info("DataFileMananger", "HisDataFile " + vv.Key + " is Created & will be add to dataFileCach!"); ParseFileName(vifno); } else { LoggerService.Service.Info("DataFileMananger", "HisDataFile " + vv.Key + " is changed & will be processed!"); var vfile = CheckAndGetDataFile(vv.Key); if (vfile != null) { vfile.UpdateLastDatetime(); } else { ParseFileName(vifno); } } } } } } /// /// /// /// /// private void LogDataWatcher_Changed(object sender, System.IO.FileSystemEventArgs e) { mResetEvent.Set(); mResetCount = 0; if (e.ChangeType == System.IO.WatcherChangeTypes.Deleted) { if(mLogFileMaps.ContainsKey(e.FullPath)) { mLogFileMaps.Remove(e.FullPath); } } else { lock (mLocker) { if (!mFileCach.ContainsKey(e.FullPath)) { mFileCach.Add(e.FullPath, e.ChangeType); } } } } /// /// /// /// /// private void HisDataWatcher_Changed(object sender, System.IO.FileSystemEventArgs e) { mResetEvent.Set(); mResetCount = 0; if (e.ChangeType == System.IO.WatcherChangeTypes.Created) { lock (mLocker) { if(!mHisFileCach.ContainsKey(e.FullPath)) { var vifno = new System.IO.FileInfo(e.FullPath); if (vifno.Extension == DataFileExtends) { mHisFileCach.Add(e.FullPath, e.ChangeType); } } } } else if(e.ChangeType == System.IO.WatcherChangeTypes.Changed) { lock (mLocker) { if (!mHisFileCach.ContainsKey(e.FullPath)) { var vifno = new System.IO.FileInfo(e.FullPath); if (vifno.Extension == DataFileExtends) { mHisFileCach.Add(e.FullPath, e.ChangeType); } } } } } /// /// /// /// public void ScanLogFile(string path) { System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path); if (dir.Exists) { foreach (var vv in dir.GetFiles()) { if (vv.Extension == LogFileExtends) { ParseLogFile(vv.FullName); } } //foreach (var vv in dir.GetDirectories()) //{ // await ScanLogFile(vv.FullName); //} } } /// /// 搜索文件 /// /// public async Task Scan(string path) { System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path); if (dir.Exists) { foreach (var vv in dir.GetFiles()) { if (vv.Extension == DataFileExtends) { ParseFileName(vv); } } foreach (var vv in dir.GetDirectories()) { await Scan(vv.FullName); } } } /// /// /// /// private void ParseLogFile(string sfileName) { var vname = System.IO.Path.GetFileNameWithoutExtension(sfileName); DateTime dt = new DateTime(int.Parse(vname.Substring(0, 4)), int.Parse(vname.Substring(4, 2)), int.Parse(vname.Substring(6, 2)), int.Parse(vname.Substring(8, 2)), int.Parse(vname.Substring(10, 2)), int.Parse(vname.Substring(12, 2))); int timelen = int.Parse(vname.Substring(14, 3)); if(!mLogFileMaps.ContainsKey(sfileName)) { mLogFileMaps.Add(sfileName, new LogFileInfo() { FileName = sfileName, StartTime = dt, EndTime = dt.AddSeconds(timelen) }); } } private DataFileInfo CheckAndGetDataFile(string file) { string sname = file.Replace(DataFileExtends, ""); string stime = sname.Substring(sname.Length - 12, 12); int yy = 0, mm = 0, dd = 0; int id = -1; int.TryParse(sname.Substring(sname.Length - 15, 3), out id); if (id == -1) return null; if (!int.TryParse(stime.Substring(0, 4), out yy)) { return null; } if (!int.TryParse(stime.Substring(4, 2), out mm)) { return null; } if (!int.TryParse(stime.Substring(6, 2), out dd)) { return null; } int hhspan = int.Parse(stime.Substring(8, 2)); int hhind = int.Parse(stime.Substring(10, 2)); int hh = hhspan * hhind; DateTime startTime = new DateTime(yy, mm, dd, hh, 0, 0); try { if (mTimeFileMaps.ContainsKey(id)) { return mTimeFileMaps[id][yy].GetDataFile(startTime); } } catch(Exception ex) { LoggerService.Service.Erro("DataFileMananger", ex.StackTrace); } return null; } /// /// /// /// private void ParseFileName(System.IO.FileInfo file) { string sname = file.Name.Replace(DataFileExtends, ""); string stime = sname.Substring(sname.Length - 12, 12); int yy=0, mm=0, dd=0; int id = -1; int.TryParse(sname.Substring(sname.Length - 15, 3), out id); if (id == -1) return; if (!int.TryParse(stime.Substring(0, 4),out yy)) { return; } if (!int.TryParse(stime.Substring(4, 2), out mm)) { return; } if (!int.TryParse(stime.Substring(6, 2), out dd)) { return; } int hhspan = int.Parse(stime.Substring(8, 2)); int hhind = int.Parse(stime.Substring(10, 2)); int hh = hhspan * hhind; DateTime startTime = new DateTime(yy, mm, dd, hh, 0, 0); YearTimeFile yt = new YearTimeFile() { TimeKey = yy }; if(mTimeFileMaps.ContainsKey(id)) { if (mTimeFileMaps[id].ContainsKey(yy)) { yt = mTimeFileMaps[id][yy]; } else { mTimeFileMaps[id].Add(yy, yt); } } else { mTimeFileMaps.Add(id, new Dictionary()); mTimeFileMaps[id].Add(yy, yt); } yt.AddFile(startTime, new TimeSpan(hhspan, 0, 0), new DataFileInfo() { Duration = new TimeSpan(hhspan, 0, 0), StartTime = startTime, FileName = file.FullName,FId= mDatabaseName + id }); } /// /// /// /// /// private LogFileInfo GetLogDataFile(DateTime time) { foreach(var vv in mLogFileMaps.Values.ToArray()) { if (vv.StartTime <= time && time < vv.EndTime) return vv; } return null; } /// /// /// /// /// /// private bool CheckDataInLogFile(DateTime time,int id) { string sname = mDatabaseName + (id/ TagCountOneFile); if(CurrentDateTime.ContainsKey(sname)) return CurrentDateTime[sname] < time; else { return false; } } /// /// /// /// /// /// public DataFileInfo GetDataFile(DateTime time,int Id) { int id = Id / TagCountOneFile; if (CheckDataInLogFile(time,id)) { //如果查询时间,比最近更新的时间还要新,则需要查询日志文件 return null; } else { if (mTimeFileMaps.ContainsKey(id) && mTimeFileMaps[id].ContainsKey(time.Year)) { return mTimeFileMaps[id][time.Year].GetDataFile(time); } } return null; } /// /// /// /// /// /// /// public List GetDataFiles(DateTime starttime, DateTime endtime, out Tuple logFileTimes, int Id) { DateTime dt = DateTime.MinValue; var vfiles = GetDataFiles(starttime, endtime - starttime, Id); foreach (var vv in vfiles) { dt = vv.LastTime>dt?vv.LastTime:dt; } logFileTimes = new Tuple(dt, endtime); return vfiles; } /// /// /// /// /// /// /// public List GetDataFiles(DateTime startTime, TimeSpan span, int Id) { List re = new List(); int id = Id / TagCountOneFile; if (mTimeFileMaps.ContainsKey(id)) { var nxtYear = new DateTime(startTime.Year+1, 1, 1); if (nxtYear > startTime + span) { int mon = startTime.Year; if (mTimeFileMaps[id].ContainsKey(mon)) { re.AddRange((mTimeFileMaps[id][mon]).GetDataFiles(startTime, span)); } } else { int mon = startTime.Year; if (mTimeFileMaps[id].ContainsKey(mon)) { re.AddRange((mTimeFileMaps[id][mon]).GetDataFiles(startTime, span)); } re.AddRange(GetDataFiles(nxtYear, startTime + span - nxtYear,Id)); } } return re; } /// /// /// /// /// /// public SortedDictionary GetDataFiles(List times, List logFileTimes,int Id) { SortedDictionary re = new SortedDictionary(); foreach(var vv in times) { if (CheckDataInLogFile(vv, Id)) { logFileTimes.Add(vv); } else { re.Add(vv, GetDataFile(vv, Id)); } } return re; } /// /// /// /// /// /// public SortedDictionary GetLogDataFiles(List times) { SortedDictionary re = new SortedDictionary(); foreach (var vvd in times) { re.Add(vvd, GetLogDataFile(vvd)); } return re; } /// /// /// /// /// /// /// public List GetLogDataFiles(DateTime startTime, DateTime endtime) { List re = new List(); foreach (var vv in mLogFileMaps.ToArray()) { if ((vv.Value.StartTime >= startTime && vv.Value.StartTime < endtime) || (vv.Value.EndTime >= startTime && vv.Value.EndTime < endtime)) { re.Add(vv.Value); } } return re; } #endregion ...Methods... #region ... Interfaces ... #endregion ...Interfaces... } }