From b2b0ff90cfac1b59f654ef758f523c6cd9507758 Mon Sep 17 00:00:00 2001 From: Candy Date: Fri, 7 Feb 2020 16:31:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E4=B8=AA=E6=96=87=E4=BB=B6=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E6=8C=87=E5=AE=9A=E6=95=B0=E9=87=8F=E7=9A=84=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E7=9A=84=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DataRunner/His/Compress/CompressEnginer.cs | 104 ++++- DataRunner/His/HisQuery/DataFileManager.cs | 48 ++- DataRunner/His/HisQuery/QuerySerivce.cs | 48 +-- .../His/HisQuery/TimeFile/MinuteTimeFile.cs | 2 +- DataRunner/His/Serise/SeriseEnginer.cs | 372 +----------------- DataRunner/Runner.cs | 2 + Mars/.vs/Mars/DesignTimeBuild/.dtbcache | Bin 3406784 -> 3406784 bytes Mars/.vs/Mars/v16/.suo | Bin 300544 -> 301568 bytes Mars/.vs/Mars/v16/Server/sqlite3/storage.ide | Bin 3960832 -> 3964928 bytes 9 files changed, 151 insertions(+), 425 deletions(-) diff --git a/DataRunner/His/Compress/CompressEnginer.cs b/DataRunner/His/Compress/CompressEnginer.cs index eaef8f4..9d0c1ed 100644 --- a/DataRunner/His/Compress/CompressEnginer.cs +++ b/DataRunner/His/Compress/CompressEnginer.cs @@ -65,6 +65,11 @@ namespace Cdy.Tag #region ... Properties ... + /// + /// 单个文件内变量的个数 + /// + public int TagCountOneFile { get; set; } = 100000; + #endregion ...Properties... #region ... Methods ... @@ -74,8 +79,10 @@ namespace Cdy.Tag /// public void CalMemory(long size) { - /* 内存结构:head+数据区指针+数据区 - head:数据大小(4)+变量数量(4)+起始时间(8) + /* 内存结构:Head+[DataRegion] + * Head:数据区域个数(4)+时间(8)+[区域ID(4)+区域地址(8)] + * DataRegion:region head+数据区指针+数据区 + region head:数据大小(4)+变量数量(4) 数据区指针:[ID(4) + address(4)] 数据区:[data block] data block:size+compressType+data @@ -177,6 +184,16 @@ namespace Cdy.Tag /// private void Compress() { + + /* 内存结构:Head+[DataRegion] + * Head:数据区域个数(4)+时间(8)+[区域ID(4)+区域地址(8)] + * DataRegion:region head+数据区指针+数据区 + region head:数据大小(4)+变量数量(4) + 数据区指针:[ID(4) + address(4)] + 数据区:[data block] + data block:size+compressType+data + */ + //读取变量个数 int count = mSourceMemory.ReadInt(9); @@ -188,11 +205,39 @@ namespace Cdy.Tag //源内存数据块头部信息偏移地址 int offset = 21; - //压缩后内存头大小 - int headoffset = 16; + int mLastDataRegionId = -1; + Dictionary Drids = new Dictionary(); + //记录每个数据区域内ID的个数 + Dictionary mDRcount = new Dictionary(); + //计算数据区域个数 + for(int i=0;i= 0) + { + mTargetMemory.WriteInt(mHeadAddress, mDataPosition);//写入上一个区域数据块的大小 + mTargetMemory.WriteInt(mHeadAddress + 4, mDRcount[mLastDataRegionId]);//写入变量个数 + } + + Drids[rid] = mHeadAddress = mDataPosition; + headoffset = mHeadAddress + 8; + mDataPosition = headoffset + mDRcount[rid] * 8 + 8; + mLastDataRegionId = rid; + } + //压缩数据 - var size = CompressBlockMemory(qaddr, mDataPosition,len); - + size = CompressBlockMemory(qaddr, mDataPosition, len); + //更新头部指针区域数据 //写入变量ID - mTargetMemory.WriteInt(headoffset,id); + mTargetMemory.WriteInt(headoffset, id); //写入数据区地址 mTargetMemory.WriteInt(headoffset + 4, mDataPosition); - ////写入数据区大小 - //mTargetMemory.WriteInt(headoffset + 8, size); - - offset += 12; headoffset += 8; - //headoffset += 12; + offset += 12; mDataPosition += size; } - mTargetMemory.WriteInt(0, mDataPosition);//写入数据的大小 - mTargetMemory.WriteInt(4, count);//写入变量数量 - mTargetMemory.WriteDatetime(8, mCurrentTime);//写入时间 + if (count > 0) + { + mTargetMemory.WriteInt(mHeadAddress, mDataPosition);//写入上一个区域数据块的大小 + mTargetMemory.WriteInt(mHeadAddress + 4, mDRcount[mLastDataRegionId]);//写入变量个数 + } + + mTargetMemory.WriteInt(0, Drids.Count); + mTargetMemory.WriteDatetime(4, mCurrentTime); + //更新数据区域地址 + offset = 12; + foreach (var vid in Drids) + { + mTargetMemory.WriteInt(offset, vid.Key); + mTargetMemory.WriteLong(offset+4, vid.Value); + offset += 12; + } } /// diff --git a/DataRunner/His/HisQuery/DataFileManager.cs b/DataRunner/His/HisQuery/DataFileManager.cs index 36f72ac..82775f5 100644 --- a/DataRunner/His/HisQuery/DataFileManager.cs +++ b/DataRunner/His/HisQuery/DataFileManager.cs @@ -21,7 +21,7 @@ namespace Cdy.Tag #region ... Variables ... - private Dictionary mTimeFileMaps = new Dictionary(); + private Dictionary> mTimeFileMaps = new Dictionary>(); private string mDatabaseName; @@ -45,6 +45,11 @@ namespace Cdy.Tag #region ... Properties ... + /// + /// 单个文件内变量的个数 + /// + public int TagCountOneFile { get; set; } + #endregion ...Properties... #region ... Methods ... @@ -68,7 +73,7 @@ namespace Cdy.Tag { foreach (var vv in dir.GetFiles()) { - if (vv.Extension == SeriseEnginer.DataFileExtends) + if (vv.Extension == SeriseFileItem.DataFileExtends) { ParseFileName(vv); } @@ -86,10 +91,16 @@ namespace Cdy.Tag /// private void ParseFileName(System.IO.FileInfo file) { - string sname = file.Name.Replace(SeriseEnginer.DataFileExtends,""); + string sname = file.Name.Replace(SeriseFileItem.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; @@ -112,14 +123,23 @@ namespace Cdy.Tag YearTimeFile yt = new YearTimeFile() { TimeKey = yy }; - if (mTimeFileMaps.ContainsKey(yy)) + if(mTimeFileMaps.ContainsKey(id)) { - yt = mTimeFileMaps[yy]; + if (mTimeFileMaps[id].ContainsKey(yy)) + { + yt = mTimeFileMaps[id][yy]; + } + else + { + mTimeFileMaps[id].Add(yy, yt); + } } else { - mTimeFileMaps.Add(yy, yt); + mTimeFileMaps.Add(id, new Dictionary()); + mTimeFileMaps[id].Add(yy, yt); } + yt.AddMonth(mm).AddDay(dd).AddHour(hh).AddMinutes().ForEach(e=> { e.AddFile(file.FullName); }); } @@ -129,11 +149,13 @@ namespace Cdy.Tag /// /// /// - public MinuteTimeFile GetFile(DateTime time) + public MinuteTimeFile GetFile(DateTime time,int Id) { - if(mTimeFileMaps.ContainsKey(time.Year)) + int id = Id / TagCountOneFile; + + if (mTimeFileMaps.ContainsKey(id) && mTimeFileMaps[id].ContainsKey(time.Year)) { - return mTimeFileMaps[time.Year].GetFile(time); + return mTimeFileMaps[id][time.Year].GetFile(time); } return null; } @@ -144,13 +166,13 @@ namespace Cdy.Tag /// /// /// - public List GetFiles(DateTime starttime,DateTime endtime) + public List GetFiles(DateTime starttime,DateTime endtime,int Id) { List re = new List(); DateTime sstart = starttime; while (sstart <= endtime) { - re.Add(GetFile(sstart)); + re.Add(GetFile(sstart,Id)); sstart = sstart.AddMinutes(1); } return re; @@ -161,12 +183,12 @@ namespace Cdy.Tag /// /// /// - public Dictionary GetFiles(List times) + public Dictionary GetFiles(List times,int Id) { Dictionary re = new Dictionary(); foreach(var vv in times) { - re.Add(vv,GetFile(vv)); + re.Add(vv,GetFile(vv,Id)); } return re; } diff --git a/DataRunner/His/HisQuery/QuerySerivce.cs b/DataRunner/His/HisQuery/QuerySerivce.cs index c2b69b1..2186b63 100644 --- a/DataRunner/His/HisQuery/QuerySerivce.cs +++ b/DataRunner/His/HisQuery/QuerySerivce.cs @@ -56,7 +56,7 @@ namespace Cdy.Tag /// public void ReadValue(int id,List times,QueryValueMatchType type,HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach(var vv in vfiles) @@ -97,7 +97,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -139,7 +139,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -180,7 +180,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -221,7 +221,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -262,7 +262,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -303,7 +303,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -344,7 +344,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -387,7 +387,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -429,7 +429,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -471,7 +471,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -512,7 +512,7 @@ namespace Cdy.Tag /// public void ReadValue(int id, List times, QueryValueMatchType type, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(times); + var vfiles = GetFileManager().GetFiles(times, id); MinuteTimeFile mPreFile = null; List mtime = new List(); foreach (var vv in vfiles) @@ -553,7 +553,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id,DateTime startTime,DateTime endTime,HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime,id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart,out eend); @@ -570,7 +570,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -587,7 +587,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -604,7 +604,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -621,7 +621,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -638,7 +638,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -655,7 +655,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -672,7 +672,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -689,7 +689,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -706,7 +706,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -723,7 +723,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); @@ -740,7 +740,7 @@ namespace Cdy.Tag /// public void ReadAllValue(int id, DateTime startTime, DateTime endTime, HisQueryResult result) { - var vfiles = GetFileManager().GetFiles(startTime, endTime); + var vfiles = GetFileManager().GetFiles(startTime, endTime, id); vfiles.ForEach(e => { DateTime sstart, eend; e.GetTimeSpan(startTime, endTime, out sstart, out eend); diff --git a/DataRunner/His/HisQuery/TimeFile/MinuteTimeFile.cs b/DataRunner/His/HisQuery/TimeFile/MinuteTimeFile.cs index 3517270..ee2e67b 100644 --- a/DataRunner/His/HisQuery/TimeFile/MinuteTimeFile.cs +++ b/DataRunner/His/HisQuery/TimeFile/MinuteTimeFile.cs @@ -124,7 +124,7 @@ namespace Cdy.Tag using (var ss = DataFileSeriserManager.manager.GetDefaultFileSersie()) { ss.OpenFile(mDataFile); - long offset = SeriseEnginer.FileHeadSize; + long offset = SeriseFileItem.FileHeadSize; DateTime time; do { diff --git a/DataRunner/His/Serise/SeriseEnginer.cs b/DataRunner/His/Serise/SeriseEnginer.cs index bc5855e..e0c23ba 100644 --- a/DataRunner/His/Serise/SeriseEnginer.cs +++ b/DataRunner/His/Serise/SeriseEnginer.cs @@ -54,58 +54,8 @@ namespace Cdy.Tag private DateTime mCurrentTime; - //private DataFileSeriserbase mFileWriter; - - //private MemoryBlock mHeadMemory; - - private VarintCodeMemory mTagIdMemoryCach; - - //变量ID校验和 - private long mTagIdSum; - - private int mTagCount = 0; - - ///// - ///// 变量的数据指针的相对起始地址 - ///// - //private Dictionary> mIdAddrs = new Dictionary>(); - private SeriseFileItem[] mSeriseFile; - /// - /// - /// - private bool mNeedUpdateTagHeads = false; - - /// - /// 当前数据区首地址 - /// - private long mCurrentDataRegion = 0; - - /// - /// 上一个数据区域首地址 - /// - private long mPreDataRegion = 0; - - /// - /// - /// - private string mCurrentFileName = string.Empty; - - /// - /// - /// - private int mFileStartHour = 0; - - /// - /// 数据文件扩展名 - /// - public const string DataFileExtends = ".dbd"; - - /// - /// 文件头大小 - /// - public const int FileHeadSize = 72; #endregion ...Variables... @@ -143,7 +93,7 @@ namespace Cdy.Tag /// /// 单个文件内变量的个数 /// - public int TagCountOneFile { get; set; } + public int TagCountOneFile { get; set; } = 100000; /// /// 数据库名称 @@ -177,56 +127,8 @@ namespace Cdy.Tag mSeriseFile[i].FileWriter = DataFileSeriserManager.manager.GetSeriser(DataSeriser).New(); mSeriseFile[i].Init(); } - - - //mIdAddrs.Clear(); - //long offset = GetDataRegionHeaderLength() + CalTagIdsSize(); - //int blockcount = FileDuration * 60 / BlockDuration; - //var vv = ServiceLocator.Locator.Resolve(); - //var tags = vv.ListAllTags().OrderBy(e => e.Id); - - //double fileCount = tags.Count() / (TagCountOneFile*1.0); - //fileCount = Math.Floor(fileCount); - - //for(int i=0;i<(int)fileCount;i++) - //{ - // mIdAddrs.Add(i, new Dictionary()); - //} - //foreach (var vtag in tags) - //{ - // mIdAddrs[vtag.Id/TagCountOneFile].Add(vtag.Id, offset); - // offset += (blockcount * 8); - //} } - ///// - ///// 计算变量Id集合所占的大小 - ///// - ///// - //private int CalTagIdsSize() - //{ - // if (mTagIdMemoryCach != null) mTagIdMemoryCach.Dispose(); - // var aids = ServiceLocator.Locator.Resolve().ListAllTags().OrderBy(e => e.Id).ToArray(); - - // mTagIdSum = 0; - - // mTagIdMemoryCach = new VarintCodeMemory((int)(aids.Count() * 4 * 1.2)); - // if (aids.Length > 0) - // { - // int preids = aids[0].Id; - // mTagIdSum += preids; - // mTagIdMemoryCach.WriteInt32(preids); - // for (int i = 1; i < aids.Length; i++) - // { - // var id = aids[i].Id; - // mTagIdMemoryCach.WriteInt32(id - preids); - // mTagIdSum += id; - // preids = id; - // } - // } - // return mTagIdMemoryCach.Position + 4; - //} - /// /// /// @@ -249,9 +151,6 @@ namespace Cdy.Tag resetEvent.Set(); closedEvent.WaitOne(); - //mIdAddrs.Clear(); - //mFileWriter = null; - mProcessMemory = null; foreach (var vv in mSeriseFile) { @@ -259,8 +158,6 @@ namespace Cdy.Tag } mSeriseFile = null; - //mHeadMemory = null; - resetEvent.Dispose(); closedEvent.Dispose(); } @@ -295,222 +192,6 @@ namespace Cdy.Tag closedEvent.Set(); } - ///// - ///// 搜索最后一个数据区域 - ///// - ///// - //private long SearchLastDataRegion() - //{ - // long offset = FileHeadSize; - // while (true) - // { - // var nextaddr = mFileWriter.ReadLong(offset + 8); - // if (nextaddr <= 0) - // { - // break; - // } - // else - // { - // offset = nextaddr; - // } - // } - // mPreDataRegion = offset; - - // mFileWriter.GoToEnd(); - // mCurrentDataRegion = mFileWriter.Length; - - // return 0; - //} - - ///// - ///// - ///// - ///// - ///// - //private string GetDataPath(DateTime time) - //{ - // return System.IO.Path.Combine(PathHelper.helper.GetDataPath("HisData"),GetFileName(time)); - //} - - ///// - ///// 检查文件是否存在 - ///// - ///// - //private bool CheckFile(DateTime time) - //{ - // if (!CheckInSameFile(time)) - // { - // if (mNeedUpdateTagHeads) - // { - // Init(); - // mNeedUpdateTagHeads = false; - // } - // mFileWriter.Flush(); - // mFileWriter.Close(); - - // string sfile = GetDataPath(time); - // if (mFileWriter.CreatOrOpenFile(sfile)) - // { - // AppendFileHeader(time, this.DatabaseName); - // //新建文件 - // mCurrentDataRegion = FileHeadSize; - // mPreDataRegion = -1; - // AppendDataRegionHeader(); - // } - // else - // { - // if (mFileWriter.Length < 8) - // { - // AppendFileHeader(time, this.DatabaseName); - // //新建文件 - // mCurrentDataRegion = FileHeadSize; - // mPreDataRegion = -1; - // AppendDataRegionHeader(); - // } - // else - // { - // //打开已有文件 - // SearchLastDataRegion(); - // AppendDataRegionHeader(); - // } - // } - // } - // else - // { - // if (mNeedUpdateTagHeads) - // { - // Init(); - // SearchLastDataRegion(); - // AppendDataRegionHeader(); - // mNeedUpdateTagHeads = false; - // } - // } - // return true; - //} - - ///// - ///// - ///// - ///// - ///// - ///// - //public bool CheckInSameFile(DateTime time1) - //{ - // return GetFileName(time1) == mCurrentFileName; - //} - - ///// - ///// - ///// - ///// - ///// - //public string GetFileName(DateTime time) - //{ - // return DatabaseName + time.ToString("yyyyMMdd") + FileDuration.ToString("D2") + (time.Hour/ FileDuration).ToString("D2")+ DataFileExtends; - //} - - ///// - ///// - ///// - ///// - //private int GetDataRegionHeaderLength() - //{ - // //头部结构:Pre DataRegion(8) + Next DataRegion(8) + Datatime(8)+ tagcount(4)+ tagid sum(8)+file duration(4)+block duration(4)+Time tick duration(4) - // return 8 + 8 + 8 + 4 + 8 + 4 + 4 + 4; - //} - - ///// - ///// - ///// - //private void AppendFileHeader(DateTime time, string databaseName) - //{ - // DateTime date = new DateTime(time.Year, time.Month, time.Day, ((time.Hour/FileDuration) * FileDuration), 0, 0); - // mFileWriter.Write(date, 0); - // byte[] nameBytes = new byte[64]; - // var ntmp = Encoding.UTF8.GetBytes(databaseName); - // Buffer.BlockCopy(ntmp, 0, nameBytes, 0, Math.Min(64, ntmp.Length)); - // mFileWriter.Write(nameBytes, 8); - //} - - ///// - ///// - ///// - //private void AppendDataRegionHeader() - //{ - // var size = GeneratorDataRegionHeader(); - // mFileWriter.Append(mHeadMemory.Buffers, 0, size); - - // //更新上个DataRegion 的Next DataRegion Pointer 指针 - // if (mPreDataRegion>=0) - // { - // mFileWriter.Write(mCurrentDataRegion, mPreDataRegion + 8); - // } - - // mPreDataRegion = mCurrentDataRegion; - - - //} - - ///// - ///// 生成文件头部 - ///// 偏移位置 - ///// - //private int GeneratorDataRegionHeader() - //{ - // //文件头部结构:Pre DataRegion(8) + Next DataRegion(8) + Datatime(8)+tagcount(4)+ tagid sum(8) +file duration(4)+ block duration(4)+Time tick duration(4)+ { len + [tag id]}+ [data blockpoint(8)] - // int blockcount = FileDuration * 60 / BlockDuration; - // int len = GetDataRegionHeaderLength() + mTagCount * (blockcount * 4); - // len += mTagIdMemoryCach.Position + 4; - - // if (mHeadMemory != null) - // { - // if (len > mHeadMemory.Length) - // { - // mHeadMemory.ReAlloc(len); - // } - // else - // { - // mHeadMemory.Clear(); - // } - // } - // else - // { - // mHeadMemory = new MemoryBlock(len); - // } - - // mHeadMemory.Position = 0; - // mHeadMemory.Write((long)mPreDataRegion);//更新Pre DataRegion 指针 - // mHeadMemory.Write((long)0); //更新Next DataRegion 指针 - // mHeadMemory.Write(mCurrentTime); //写入时间 - // mHeadMemory.Write(mTagCount); //写入变量个数 - - // mHeadMemory.Write(mTagIdSum); //写入Id 校验和 - - // mHeadMemory.Write(FileDuration); //写入文件持续时间 - // mHeadMemory.Write(BlockDuration); //写入数据块持续时间 - // mHeadMemory.Write(HisEnginer.MemoryTimeTick); //写入时间间隔 - - // //写入变量编号列表 - // mHeadMemory.Write(mTagIdMemoryCach.Position);//写入压缩后的数组的长度 - // mHeadMemory.Write(mTagIdMemoryCach.Buffer, 0, mTagIdMemoryCach.Position);//写入压缩数据 - - // return len; - - //} - - ///// - ///// 更新数据块文件指针 - ///// - ///// - ///// - //public void UpdateDataBlockPointer(int id, long datapointer, DateTime dateTime) - //{ - // int bindex = ((dateTime.Hour - mFileStartHour) * 60 + dateTime.Minute)/ BlockDuration; - // int icount = id / TagCountOneFile; - // long ids = mCurrentDataRegion + mIdAddrs[icount][id] + bindex * 8; //当前数据区域地址+数据指针的起始地址+指针偏移 - // mFileWriter.Write(BitConverter.GetBytes(datapointer), ids); - //} - /// /// 执行存储到磁盘 /// @@ -535,58 +216,8 @@ namespace Cdy.Tag Parallel.ForEach(memoryAddrs, (keyval) => { mSeriseFile[keyval.Key].SaveToFile(mProcessMemory, keyval.Value,mCurrentTime); }); - - //var totalsize = mProcessMemory.ReadInt(0); - //var count = mProcessMemory.ReadInt(4); - //var time = mProcessMemory.ReadDateTime(8); - //mTagCount = count; - //mCurrentTime = time; - //int offset = 16; - ////判断变量的ID列表是否被修改了 - //for (int i=0;i - ///// - ///// - //public void Flush() - //{ - // mFileWriter.Flush(); - //} - #endregion ...Methods... #region ... Interfaces ... @@ -989,7 +620,6 @@ namespace Cdy.Tag var totalsize = mProcessMemory.ReadInt(dataOffset); var count = mProcessMemory.ReadInt(dataOffset + 4); - //var time = mProcessMemory.ReadDateTime(dataOffset + 8); mTagCount = count; mCurrentTime = time; long offset = 8 + dataOffset; diff --git a/DataRunner/Runner.cs b/DataRunner/Runner.cs index 24a4394..3c20adf 100644 --- a/DataRunner/Runner.cs +++ b/DataRunner/Runner.cs @@ -133,6 +133,7 @@ namespace Cdy.Tag InitPath(); mHisFileManager = new DataFileManager(mDatabaseName); + mHisFileManager.TagCountOneFile = mHisDatabase.Setting.TagCountOneFile; var task = mHisFileManager.Int(); @@ -147,6 +148,7 @@ namespace Cdy.Tag hisEnginer.Init(); compressEnginer = new CompressEnginer(hisEnginer.CurrentMemory.Length); + compressEnginer.TagCountOneFile = mHisDatabase.Setting.TagCountOneFile; seriseEnginer = new SeriseEnginer() { DatabaseName = database }; seriseEnginer.FileDuration = mHisDatabase.Setting.FileDataDuration; diff --git a/Mars/.vs/Mars/DesignTimeBuild/.dtbcache b/Mars/.vs/Mars/DesignTimeBuild/.dtbcache index 2495c72169f514af2e9ea27dd01f2b0dfa4fc420..78b6c2aa07cd978b703c0de61b437971dce3293f 100644 GIT binary patch delta 250 zcmWl|Jx&5a7=Yn`x*{rye&7fS>p$qCfQj4Kns^xxfSn1GX(>qd0ut2Q*43x+2RFRs9b0Vko)6X^1gp0%(UQ}W*Rr8yQ_I%3crG>Bw9Yf0 hv%w~PUhtAvHk)3*&x}d}cKFCAcG+X!s^mF-T?2H|b1DD; delta 262 zcmWN|yH3JT0D$38Y6VnmrPSjEti?-}iwX%7D~S)$SCGkcU~_=8IG8Z>75W0?j4hKR z9ej{(?dU&zI_3@cd0~xL?64sH_5Q8&u!a3^2q9FL=cp#!4iUc=ivqJZE(P diff --git a/Mars/.vs/Mars/v16/.suo b/Mars/.vs/Mars/v16/.suo index b811c3081b233dc9254f0c9d2669813613d92aaa..aea73493baac52015744d540603b07140cd194c9 100644 GIT binary patch delta 21743 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 O_}cg<{LyN;>Hh(NW@WYj delta 21308 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