diff --git a/Common/Cdy.Tag/DatabaseSerise.cs b/Common/Cdy.Tag/DatabaseSerise.cs index bc788bd566c718b97cb4d8b83df6195d70fec0d1..19959362427fe51b392f2a878faf0455ce87d99e 100644 --- a/Common/Cdy.Tag/DatabaseSerise.cs +++ b/Common/Cdy.Tag/DatabaseSerise.cs @@ -157,6 +157,24 @@ namespace Cdy.Tag new RealDatabaseSerise() { Database = Dbase.RealDatabase }.Save(); new HisDatabaseSerise() { Database = Dbase.HisDatabase }.Save(); new SecuritySerise() { Document = Dbase.Security }.Save(); + SaveRDDCSecurity(Dbase.Name); + } + + /// + /// + /// + /// + private void SaveRDDCSecurity(string databaseName) + { + string sfile = PathHelper.helper.GetDataPath(databaseName, "RDDC.cfg"); + if(!System.IO.File.Exists(sfile)) + { + XElement xx = new XElement("RDDC"); + xx.SetAttributeValue("Enable", false); + xx.SetAttributeValue("Port", 7000); + xx.SetAttributeValue("RemoteIp", "127.0.0.1"); + xx.Save(sfile); + } } #endregion ...Methods... diff --git a/RunTime/DBRuntime/His/Compress/CompressEnginer2.cs b/RunTime/DBRuntime/His/Compress/CompressEnginer2.cs index 1910afa68ee9b75402690c83cf46bbda0b5c9666..4f0efe4a0073c0c08514864f2d0227da8bc1ee7b 100644 --- a/RunTime/DBRuntime/His/Compress/CompressEnginer2.cs +++ b/RunTime/DBRuntime/His/Compress/CompressEnginer2.cs @@ -19,7 +19,7 @@ namespace Cdy.Tag /// /// /// - public class CompressEnginer2 : IDataCompress2 + public class CompressEnginer2 : IDataCompress2,IDisposable { #region ... Variables ... @@ -84,7 +84,9 @@ namespace Cdy.Tag /// public void Init() { + mHisTagService = ServiceLocator.Locator.Resolve(); CompressMemory2.TagCountPerMemory = TagCountOneFile; + foreach (var vm in mTargetMemorys) { vm.Value.Dispose(); @@ -146,15 +148,12 @@ namespace Cdy.Tag public void Start() { mIsClosed = false; - mHisTagService = ServiceLocator.Locator.Resolve(); - - Init(); + //Init(); resetEvent = new ManualResetEvent(false); closedEvent = new ManualResetEvent(false); mCompressThread = new Thread(ThreadPro); mCompressThread.IsBackground = true; mCompressThread.Start(); - } /// @@ -166,18 +165,8 @@ namespace Cdy.Tag resetEvent.Set(); closedEvent.WaitOne(); - mSourceMemory = null; - mHisTagService = null; - resetEvent.Dispose(); closedEvent.Dispose(); - - foreach(var vv in mTargetMemorys) - { - while (vv.Value.IsBusy()) Thread.Sleep(1); - vv.Value.Dispose(); - } - mTargetMemorys.Clear(); } /// @@ -284,6 +273,22 @@ namespace Cdy.Tag } + /// + /// + /// + public void Dispose() + { + + foreach (var vv in mTargetMemorys) + { + while (vv.Value.IsBusy()) Thread.Sleep(1); + vv.Value.Dispose(); + } + mTargetMemorys.Clear(); + mSourceMemory = null; + mHisTagService = null; + } + #endregion ...Methods... #region ... Interfaces ... diff --git a/RunTime/DBRuntime/His/HisEnginer2.cs b/RunTime/DBRuntime/His/HisEnginer2.cs index c47efce028a53ce62ee1cc023b5e9bff78b0e883..b649c504477bdd6225c87df90eeb7bae40bcf7f0 100644 --- a/RunTime/DBRuntime/His/HisEnginer2.cs +++ b/RunTime/DBRuntime/His/HisEnginer2.cs @@ -20,7 +20,7 @@ namespace Cdy.Tag /// /// 历史数据引擎2 /// - public class HisEnginer2 : IHisEngine2 + public class HisEnginer2 : IHisEngine2,IDisposable { #region ... Variables ... @@ -238,9 +238,7 @@ namespace Cdy.Tag sw.Start(); if (mRealEnginer != null) { - //if (mManager == null) - // mManager = new Cdy.Tag.HisDatabaseSerise().Load(); - + mLastProcesser = new TimerMemoryCacheProcesser2() { Id = 0 }; mRecordTimerProcesser.Clear(); mRecordTimerProcesser.Add(mLastProcesser); @@ -333,6 +331,12 @@ namespace Cdy.Tag } long ltmp = sw.ElapsedMilliseconds; AllocMemory(); + + if (LogManager != null) + { + LogManager.InitHeadData(); + } + sw.Stop(); LoggerService.Service.Info("HisEnginer", "生成对象耗时:"+ltmp+" 内存分配耗时:"+(sw.ElapsedMilliseconds-ltmp)); } @@ -635,12 +639,9 @@ namespace Cdy.Tag var abuffer = new HisDataMemoryBlock(ss) { TimerAddress=0, ValueAddress = valueOffset, QualityAddress = qulityOffset,Id=1 }; var bbuffer = new HisDataMemoryBlock(ss) { TimerAddress = 0, ValueAddress = valueOffset, QualityAddress = qulityOffset,Id=2 }; - //abuffer.Clear(); - //bbuffer.Clear(); mMergeMemory1.AddTagAddress(vv.Value.Id, abuffer); mMergeMemory2.AddTagAddress(vv.Value.Id, bbuffer); - // addressoffset.Add(vv.Value.Id, new Tuple(storeHeadSize,valueOffset, qulityOffset,ss)); storeHeadSize += ss; var css = CalCachDatablockSize(vv.Value.TagType, vv.Value.Type, blockheadsize, out valueOffset,out qulityOffset); @@ -650,23 +651,12 @@ namespace Cdy.Tag vv.Value.HisValueMemory1 = cbuffer; vv.Value.HisValueMemory2 = dbuffer; - //cbuffer.Clear(); - //dbuffer.Clear(); mCachMemory1.AddTagAddress(vv.Value.Id, cbuffer); mCachMemory2.AddTagAddress(vv.Value.Id, dbuffer); - //vv.Value.BlockHeadStartAddr = cachHeadSize; - - //vv.Value.TimerValueStartAddr = vv.Value.BlockHeadStartAddr; - - //vv.Value.HisValueStartAddr = vv.Value.BlockHeadStartAddr + valueOffset; - - //vv.Value.HisQulityStartAddr = vv.Value.BlockHeadStartAddr + qulityOffset; - vv.Value.DataSize = css; cachHeadSize += css; - //vv.Value.Init(); } @@ -676,25 +666,10 @@ namespace Cdy.Tag CurrentMemory = mCachMemory1; - ClearMemoryHisData(mCachMemory1); - ClearMemoryHisData(mCachMemory2); - ClearMemoryHisData(mMergeMemory1); - ClearMemoryHisData(mMergeMemory2); - //mCachMemory1.Clear(); - //mCachMemory2.Clear(); - //mMergeMemory.Clear(); + } - ///// - ///// - ///// - //private void PrepareForReadyMemory() - //{ - // //写入时间 - // HisRunTag.StartTime = mLastProcessTime; - //} - private string FormateDatetime(DateTime datetime) { return datetime.ToString("yyyy-MM-dd HH:mm:ss.fff"); @@ -729,7 +704,17 @@ namespace Cdy.Tag { mIsClosed = false; mMegerProcessIsClosed = false; - + LoggerService.Service.Info("Record", "历史变量个数: " + this.mHisTags.Count); + + ClearMemoryHisData(mCachMemory1); + ClearMemoryHisData(mCachMemory2); + ClearMemoryHisData(mMergeMemory1); + ClearMemoryHisData(mMergeMemory2); + + mCachMemory1.MakeMemoryNoBusy(); + mCachMemory2.MakeMemoryNoBusy(); + mMergeMemory1.MakeMemoryNoBusy(); + mMergeMemory2.MakeMemoryNoBusy(); foreach (var vv in mRecordTimerProcesser) { @@ -741,13 +726,6 @@ namespace Cdy.Tag vv.Start(); } - LoggerService.Service.Info("Record", "历史变量个数: " + this.mHisTags.Count); - - mCachMemory1.MakeMemoryNoBusy(); - mCachMemory2.MakeMemoryNoBusy(); - mMergeMemory1.MakeMemoryNoBusy(); - mMergeMemory2.MakeMemoryNoBusy(); - mLastProcessTime = DateTime.Now; HisRunTag.StartTime = mLastProcessTime; CurrentMemory = mCachMemory1; @@ -758,7 +736,6 @@ namespace Cdy.Tag if (LogManager != null) { - LogManager.InitHeadData(); LogManager.Start(); } @@ -819,8 +796,7 @@ namespace Cdy.Tag { resetEvent.WaitOne(); resetEvent.Reset(); - //if (mIsClosed) return; - + if(mNeedSnapAllTag) { SnapeAllTag(); @@ -1133,32 +1109,13 @@ namespace Cdy.Tag foreach (var vv in mRecordTimerProcesser) { vv.Stop(); - vv.Dispose(); } - mRecordTimerProcesser.Clear(); - - foreach(var vv in mValueChangedProcesser) + foreach (var vv in mValueChangedProcesser) { vv.Stop(); - vv.Dispose(); } - mValueChangedProcesser.Clear(); - - if (LogManager != null) LogManager.Stop(); - SubmitLastDataToSave(); - - mIsClosed = true; - - mLastValueChangedProcesser = null; - mLastProcesser = null; - - mHisTags.Clear(); - - mCachMemory1?.Dispose(); - mCachMemory2?.Dispose(); - mMergeMemory1?.Dispose(); - mMergeMemory2?.Dispose(); + if (LogManager != null) LogManager.Stop(); } /// @@ -1211,7 +1168,36 @@ namespace Cdy.Tag return mHisTags.Values.ToList(); } - + /// + /// + /// + public void Dispose() + { + foreach (var vv in mRecordTimerProcesser) + { + vv.Dispose(); + } + mRecordTimerProcesser.Clear(); + + foreach (var vv in mValueChangedProcesser) + { + vv.Stop(); + vv.Dispose(); + } + mValueChangedProcesser.Clear(); + + mLastValueChangedProcesser = null; + mLastProcesser = null; + + mHisTags.Clear(); + + mCachMemory1?.Dispose(); + mCachMemory2?.Dispose(); + mMergeMemory1?.Dispose(); + mMergeMemory2?.Dispose(); + } + + #endregion ...Methods... diff --git a/RunTime/DBRuntime/His/SeriseEnginer2.cs b/RunTime/DBRuntime/His/SeriseEnginer2.cs index acaaa8d2fd450129d02cded6de44bab5dee5e0ce..b0976207c967d0ad3d1e37b2020295e9a2f753cd 100644 --- a/RunTime/DBRuntime/His/SeriseEnginer2.cs +++ b/RunTime/DBRuntime/His/SeriseEnginer2.cs @@ -38,7 +38,7 @@ namespace Cdy.Tag /// /// 序列话引擎 /// - public class SeriseEnginer2 : IDataSerialize2 + public class SeriseEnginer2 : IDataSerialize2, IDisposable { #region ... Variables ... @@ -128,7 +128,7 @@ namespace Cdy.Tag /// /// 当前工作的历史记录路径 /// - public static string HisDataPath{ get; set; } + public static string HisDataPath { get; set; } #endregion ...Properties... @@ -143,7 +143,7 @@ namespace Cdy.Tag { if (string.IsNullOrEmpty(HisDataPathPrimary) && string.IsNullOrEmpty(HisDataPathBack)) { - return PathHelper.helper.GetDataPath(this.DatabaseName,"HisData"); + return PathHelper.helper.GetDataPath(this.DatabaseName, "HisData"); } else { @@ -161,7 +161,7 @@ namespace Cdy.Tag /// /// /// - private void Init() + public void Init() { DataFileSeriserManager.manager.Init(); CompressUnitManager2.Manager.Init(); @@ -182,23 +182,11 @@ namespace Cdy.Tag } } - foreach(var vv in mSeriserFiles) + foreach (var vv in mSeriserFiles) { vv.Value.FileWriter = DataFileSeriserManager.manager.GetSeriser(DataSeriser).New(); vv.Value.Init(); } - - //var scount = tagCont / TagCountOneFile; - //scount = tagCont % TagCountOneFile > 0 ? scount + 1 : scount; - - //mSeriseFile = new SeriseFileItem[scount]; - - //for(int i=0;i @@ -207,7 +195,7 @@ namespace Cdy.Tag public void Start() { mIsClosed = false; - Init(); + //Init(); resetEvent = new ManualResetEvent(false); closedEvent = new ManualResetEvent(false); mCompressThread = new Thread(ThreadPro); @@ -223,14 +211,7 @@ namespace Cdy.Tag mIsClosed = true; resetEvent.Set(); closedEvent.WaitOne(); - if (mSeriserFiles != null) - { - foreach (var vv in mSeriserFiles) - { - vv.Value.Dispose(); - } - mSeriserFiles.Clear(); - } + resetEvent.Dispose(); closedEvent.Dispose(); @@ -293,37 +274,52 @@ namespace Cdy.Tag 2. 拷贝数据块 3. 更新数据块指针 */ -//#if DEBUG + //#if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); - LoggerService.Service.Info("SeriseEnginer", "********开始执行存储********",ConsoleColor.Cyan); -//#endif + LoggerService.Service.Info("SeriseEnginer", "********开始执行存储********", ConsoleColor.Cyan); + //#endif HisDataPath = SelectHisDataPath(); List mtmp; - lock(mWaitForProcessMemory) + lock (mWaitForProcessMemory) { mtmp = mWaitForProcessMemory.Values.ToList(); mWaitForProcessMemory.Clear(); } - foreach(var vv in mtmp) + foreach (var vv in mtmp) { mSeriserFiles[vv.Id].SaveToFile(vv, vv.CurrentTime); vv.Clear(); vv.MakeMemoryNoBusy(); } -//#if DEBUG + //#if DEBUG sw.Stop(); - LoggerService.Service.Info("SeriseEnginer", ">>>>>>>>>完成执行存储>>>>>>> Count:"+ mtmp.Count + " ElapsedMilliseconds:" + sw.ElapsedMilliseconds, ConsoleColor.Cyan); -//#endif + LoggerService.Service.Info("SeriseEnginer", ">>>>>>>>>完成执行存储>>>>>>> Count:" + mtmp.Count + " ElapsedMilliseconds:" + sw.ElapsedMilliseconds, ConsoleColor.Cyan); + //#endif } -#endregion ...Methods... + /// + /// + /// + public void Dispose() + { + if (mSeriserFiles != null) + { + foreach (var vv in mSeriserFiles) + { + vv.Value.Dispose(); + } + mSeriserFiles.Clear(); + } + } -#region ... Interfaces ... + #endregion ...Methods... -#endregion ...Interfaces... + #region ... Interfaces ... + + #endregion ...Interfaces... } diff --git a/RunTime/DBRuntime/RDDC/DataSync.cs b/RunTime/DBRuntime/RDDC/DataSync.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e6644af60d1a7bf854869a884a890b3ce88c2a4 --- /dev/null +++ b/RunTime/DBRuntime/RDDC/DataSync.cs @@ -0,0 +1,125 @@ +//============================================================== +// Copyright (C) 2020 Chongdaoyang Inc. All rights reserved. +// +//============================================================== +// Create by 种道洋 at 2020/8/17 20:23:20 . +// Version 1.0 +// CDYWORK +//============================================================== + +using Cdy.Tag; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace DBRuntime.RDDC +{ + /// + /// + /// + public class DataSync + { + + #region ... Variables ... + + private Thread mScanThread; + + private RDDCClient mClient; + + private bool mIsStoped = false; + + #endregion ...Variables... + + #region ... Events ... + + #endregion ...Events... + + #region ... Constructor... + + #endregion ...Constructor... + + #region ... Properties ... + + /// + /// + /// + public RDDCClient Client + { + get + { + return mClient; + } + set + { + mClient = value; + } + } + + + #endregion ...Properties... + + #region ... Methods ... + + /// + /// + /// + public void Start() + { + mScanThread = new Thread(ThreadPro); + mScanThread.IsBackground = true; + mScanThread.Start(); + } + + /// + /// + /// + private void ThreadPro() + { + while(!mIsStoped) + { + if (mClient.IsConnected) + { + SyncData(); + Thread.Sleep(100); + } + else + { + Thread.Sleep(500); + } + } + } + + /// + /// + /// + private void SyncData() + { + try + { + var realenginer = ServiceLocator.Locator.Resolve(); + var block = mClient.SyncRealData(); + var size = block.ReadInt(); + Buffer.BlockCopy(block.Array, block.ArrayOffset + block.ReaderIndex, (realenginer as RealEnginer).Memory, 0, size); + } + catch(Exception ex) + { + LoggerService.Service.Erro("DataSync", ex.Message); + } + } + + /// + /// + /// + public void Stop() + { + mIsStoped = true; + } + + #endregion ...Methods... + + #region ... Interfaces ... + + #endregion ...Interfaces... + } +} diff --git a/RunTime/DBRuntime/RDDC/RDDCManager.cs b/RunTime/DBRuntime/RDDC/RDDCManager.cs index 47e2997c325e200cb1d88f3f0fcc68c07320387d..4bf3192ae4de3b04c29b6b95ac101c1d541c75f2 100644 --- a/RunTime/DBRuntime/RDDC/RDDCManager.cs +++ b/RunTime/DBRuntime/RDDC/RDDCManager.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Xml.Linq; namespace DBRuntime { @@ -30,6 +31,7 @@ namespace DBRuntime private RDDCClient mClient; + private DataSync mSync; private bool mIsInited = false; @@ -52,6 +54,11 @@ namespace DBRuntime #region ... Properties ... + /// + /// + /// + public bool EnableRDDC { get; set; } + /// /// 当前状态 /// @@ -68,7 +75,7 @@ namespace DBRuntime public int Port { get; set; } /// - /// + /// 备机IP /// public string RemoteIp { get; set; } @@ -81,19 +88,46 @@ namespace DBRuntime #region ... Methods ... + /// + /// + /// + /// + public void Load(string databaseName) + { + string spath = PathHelper.helper.GetDataPath(databaseName, "RDDC.cfg"); + if(System.IO.File.Exists(spath)) + { + XElement xx = XElement.Load(spath); + EnableRDDC = bool.Parse(xx.Attribute("Enable")?.Value); + this.Port = int.Parse(xx.Attribute("Port")?.Value); + this.RemoteIp = xx.Attribute("RemoteIp")?.Value; + } + + } + /// /// /// public void Start() { mIsInited = false; - mServer = new RDDCDataService(); - mServer.Start(Port); + if (EnableRDDC) + { + mServer = new RDDCDataService(); + mServer.Start(Port); + + mClient = new RDDCClient(); + mClient.Connect(RemoteIp, Port); + mClient.PropertyChanged += MClient_PropertyChanged; - mClient = new RDDCClient(); - mClient.Connect(RemoteIp, Port); - mClient.PropertyChanged += MClient_PropertyChanged; - CheckWorkState(); + mSync = new DataSync() { Client = mClient }; + mSync.Start(); + CheckWorkState(); + } + else + { + CurrentState = WorkState.Primary; + } mIsInited = true; } @@ -116,10 +150,15 @@ namespace DBRuntime /// public void Stop() { + mSync.Stop(); mServer.Stop(); + mClient.PropertyChanged -= MClient_PropertyChanged; mClient.Close(); } + /// + /// + /// private void ProcessClientConnectChanged() { if (!mClient.IsConnected) @@ -170,9 +209,6 @@ namespace DBRuntime } } - - - /// /// /// diff --git a/RunTime/DBRuntime/Runner.cs b/RunTime/DBRuntime/Runner.cs index d2daaf9720793887e9b0c992acdb7048547b0034..310aab0f182a64ebf90efeb2b108f36a14a7eda4 100644 --- a/RunTime/DBRuntime/Runner.cs +++ b/RunTime/DBRuntime/Runner.cs @@ -85,6 +85,25 @@ namespace Cdy.Tag ValueConvertManager.manager.Registor(new LinerConvert()); } + /// + /// + /// + public Runner() + { + RDDCManager.Manager.SwitchWorkStateAction = new Func((state) => + { + if(state == WorkState.Primary) + { + + return SwitchToPrimary(); + } + else + { + return SwitchToStandby(); + } + }); + } + #endregion ...Constructor... #region ... Properties ... @@ -157,7 +176,10 @@ namespace Cdy.Tag CurrentDatabaseVersion = this.mRealDatabase.Version; CurrentDatabase = mRealDatabase.Name; CurrentDatabaseLastUpdateTime = mRealDatabase.UpdateTime; - sw.Stop(); + + RDDCManager.Manager.Load(mDatabaseName); + + sw.Stop(); LoggerService.Service.Info("LoadDatabase", "load " +mDatabaseName +" take " + sw.ElapsedMilliseconds.ToString() +" ms"); } @@ -256,12 +278,14 @@ namespace Cdy.Tag compressEnginer = new CompressEnginer2(); compressEnginer.TagCountOneFile = mHisDatabase.Setting.TagCountOneFile; + compressEnginer.Init(); seriseEnginer = new SeriseEnginer2() { DatabaseName = database }; seriseEnginer.FileDuration = mHisDatabase.Setting.FileDataDuration; seriseEnginer.BlockDuration = mHisDatabase.Setting.DataBlockDuration; seriseEnginer.TagCountOneFile = mHisDatabase.Setting.TagCountOneFile; seriseEnginer.DataSeriser = mHisDatabase.Setting.DataSeriser; + seriseEnginer.Init(); querySerivce = new QuerySerivce(this.mDatabaseName); @@ -332,6 +356,7 @@ namespace Cdy.Tag public async void StartAsync(string database,int port = 14330) { LoggerService.Service.Info("Runner", " 数据库 " + database+" 开始启动"); + RDDCManager.Manager.Start(); var re = await InitAsync(database); @@ -353,6 +378,44 @@ namespace Cdy.Tag LoggerService.Service.Info("Runner", " 数据库 " + database + " 启动完成"); } + /// + /// + /// + private bool SwitchToStandby() + { + try + { + hisEnginer.Stop(); + compressEnginer.Stop(); + seriseEnginer.Stop(); + DriverManager.Manager.Stop(); + } + catch + { + return false; + } + return true; + } + + /// + /// + /// + private bool SwitchToPrimary() + { + try + { + DriverManager.Manager.Start(); + seriseEnginer.Start(); + compressEnginer.Start(); + hisEnginer.Start(); + } + catch + { + return false; + } + return true; + } + /// /// 停止 @@ -364,7 +427,11 @@ namespace Cdy.Tag DriverManager.Manager.Stop(); compressEnginer.Stop(); seriseEnginer.Stop(); - // mSecurityRunner.Stop(); + + hisEnginer.Dispose(); + compressEnginer.Dispose(); + seriseEnginer.Dispose(); + mIsStarted = false; }