using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.IO.MemoryMappedFiles; using System.Threading; using System.Runtime.InteropServices; using SystemX.Net.BaseProtocol; using SystemX.Common.Serialization; using static SystemX.Net.Platform.Common.Util.LogMessage; namespace SystemX.Net.Platform.SystemX.Common { [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable] public struct InfoLogMappedPacket { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024, ArraySubType = UnmanagedType.Bool)] public bool[] bLogDataReady; } //------------------------------------------------------------------------------------------ [StructLayout(LayoutKind.Sequential, Pack = 1), Serializable] public struct LogMappedPacket { //Use State [MarshalAs(UnmanagedType.Bool)] public bool bSectionUse; //Host [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objLogType; //This File Process Result 1 [MarshalAs(UnmanagedType.Bool)] public bool bLogFileReadComplete; //This File Process Result 2 [MarshalAs(UnmanagedType.Bool)] public bool bLogFileProcessComplete; //Number [MarshalAs(UnmanagedType.I4)] public int nNumber; //Use Log Process Time [MarshalAs(UnmanagedType.Bool)] public bool bShowCpLogProcessTime; //COMMAND 포트 번호 [MarshalAs(UnmanagedType.I4)] public int nCommandPort; //STREAM 포트 번호 [MarshalAs(UnmanagedType.I4)] public int nStreamPort; //Station ID [MarshalAs(UnmanagedType.I4)] public int nStationID; //Host [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_64[] objHost; //Section [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_64[] objSection; //Option File Name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_64[] objOptionFileName; //Option File Name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objOptionFileExtension; //Station Name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_64[] objStationName; //Prod P [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objProdPNo; //Prod C [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objProdCNo; //Test Type [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objTestType; //Test Code [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objTestCode; //Version [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objVersion; //Prod Code [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_16[] objProdCode; //Test List Variant No [MarshalAs(UnmanagedType.I4)] public int nTestListVariantNo; //Test List Load Cnt ID [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public STRING_256[] objResultTestListCntID; public byte[] Data() { return ucLogData; } //Test List Variant No [MarshalAs(UnmanagedType.I4)] public int nLogDataSize; //Log File 1MB 까지 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024000, ArraySubType = UnmanagedType.U1)] public byte[] ucLogData; } //------------------------------------------------------------------------------------------ public class CMapParameter { public string strSetEnterMutexName; public string strSetAccessMutexName; public string strSetPath; public string strSetFileName; public string strSetMapName; } public class SharedMemory { //Keep the mutex as static to prevent early garbage collection public const int nMaxStationSize = 8; //Keep the mutex as static to prevent early garbage collection public const int nMaxInfoFullAccessSize = 1024; protected byte[] ucCurrentArr; protected int nSize; private bool bDisposed; protected CMapParameter ParameterMap; public SharedMemory(CMapParameter SetParameter) { bDisposed = false; ParameterMap = new CMapParameter(); ParameterMap.strSetEnterMutexName = SetParameter.strSetEnterMutexName; ParameterMap.strSetAccessMutexName = SetParameter.strSetAccessMutexName; ParameterMap.strSetPath = SetParameter.strSetPath; ParameterMap.strSetFileName = SetParameter.strSetFileName; ParameterMap.strSetMapName = SetParameter.strSetMapName; } protected byte[] StructToByte(object obj) { int size = Marshal.SizeOf(obj); byte[] arr = new byte[size]; IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(obj, ptr, true); Marshal.Copy(ptr, arr, 0, size); Marshal.FreeHGlobal(ptr); return arr; } protected T ByteToStruct(byte[] buffer) where T : struct { int size = Marshal.SizeOf(typeof(T)); if (size > buffer.Length) throw new Exception(); IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.Copy(buffer, 0, ptr, size); T obj = (T)Marshal.PtrToStructure(ptr, typeof(T)); Marshal.FreeHGlobal(ptr); return obj; } } public class LogSharedMemory : SharedMemory, IDisposable { //private static object _numLock; //private static Mutex _mutex; private static Mutex _mutexSub; private bool bDisposed; public LogSharedMemory(CMapParameter SetParameter) : base(SetParameter) { bDisposed = false; } static LogSharedMemory() { } public void Set(int nPos, LogMappedPacket value) { bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName + nPos.ToString("D03"), out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName + nPos.ToString("D03")); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("LogSharedMemory.Set failed Mutex WaitOne()."); } // try { ucCurrentArr = StructToByte(value); nSize = ucCurrentArr.Count(); //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateFromFile( @ParameterMap.strSetPath + ParameterMap.strSetFileName + nPos.ToString("D03"), //file location FileMode.OpenOrCreate, //create new file if not exist, open if exist ParameterMap.strSetMapName + nPos.ToString("D03"), //map name nSize * nMaxStationSize)) //size { //update the number to memory view using (var stream = memMapFile.CreateViewStream()) using (var writer = new BinaryWriter(stream)) { writer.Seek(value.nStationID * nSize, SeekOrigin.Begin); writer.Write(ucCurrentArr); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : LogSharedMemory.Set[1]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : LogSharedMemory.Set[2]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file //if (_mutex != null) // _mutex.ReleaseMutex(); } } public bool CheckFile(int nPos) { bool bCheckResult = false; bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName + nPos.ToString("D03"), out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName + nPos.ToString("D03")); } else { bSubMutexResult = _mutexSub.WaitOne(100); if (bSubMutexResult == false) throw new Exception("LogSharedMemory.CheckFile failed Mutex WaitOne()."); } // if (File.Exists(@ParameterMap.strSetPath + ParameterMap.strSetFileName + nPos.ToString("D03"))) bCheckResult = true; else bCheckResult = false; } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : LogSharedMemory.CheckFile] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); bCheckResult = false; } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } return bCheckResult; } public LogMappedPacket? Get(int nPos, int nStPos, out bool bFindProcessNeedLogResult, int nSetSize = int.MinValue) { LogMappedPacket? GetMappedFile = null; bFindProcessNeedLogResult = false; byte[] ucGetArr = null; bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName + nPos.ToString("D03"), out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName + nPos.ToString("D03")); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("LogSharedMemory.Get failed Mutex WaitOne()."); } // try { if (nSetSize != int.MinValue) nSize = nSetSize; //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateFromFile( @ParameterMap.strSetPath + ParameterMap.strSetFileName + nPos.ToString("D03"), //file location FileMode.Open, //create new file if not exist, open if exist ParameterMap.strSetMapName + nPos.ToString("D03"), //map name nSize * nMaxStationSize)) //size { //get last number from memory view using (var stream = memMapFile.CreateViewStream()) using (var reader = new BinaryReader(stream)) { stream.Seek(nStPos * nSize, SeekOrigin.Begin); ucGetArr = reader.ReadBytes(nSize); GetMappedFile = ByteToStruct(ucGetArr); if (GetMappedFile.Value.bSectionUse) { if (GetMappedFile.Value.bLogFileReadComplete == false) bFindProcessNeedLogResult = true; } } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : LogSharedMemory.Get[1]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { /*if (File.Exists(@"D:\CpServerXLogSharedMemoryMap" + nPos.ToString("D03"))) File.Delete(@"D:\CpServerXLogSharedMemoryMap" + nPos.ToString("D03"));*/ //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : LogSharedMemory.Get[2]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file /* if (_mutex != null) _mutex.ReleaseMutex(); */ } return GetMappedFile; } public void Dispose() { if (!bDisposed) { //Manage //Unmanage // if (_mutexSub != null) { _mutexSub.Dispose(); _mutexSub = null; } bDisposed = true; } } } public class InfoLogSharedMemory : SharedMemory, IDisposable { private static Mutex _mutex; private static Mutex _mutexSub; //private static object _numLock; private bool bDisposed; public InfoLogSharedMemory(CMapParameter SetParameter) : base(SetParameter) { bDisposed = false; } static InfoLogSharedMemory() { } public void Set(InfoLogMappedPacket value) { bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName, out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("InfoLogSharedMemory.Set failed Mutex WaitOne()."); } // try { ucCurrentArr = StructToByte(value); nSize = ucCurrentArr.Count(); //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateFromFile( @ParameterMap.strSetPath + ParameterMap.strSetFileName, //file location FileMode.OpenOrCreate, //create new file if not exist, open if exist ParameterMap.strSetMapName, //map name nSize)) //size { //update the number to memory view using (var stream = memMapFile.CreateViewStream()) using (var writer = new BinaryWriter(stream)) { writer.Seek(0, SeekOrigin.Begin); writer.Write(ucCurrentArr); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Set InfoLogMappedPacket[1]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Set InfoLogMappedPacket[2]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file } } public void Set(bool[] value) { bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName, out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("InfoLogSharedMemory.Set failed Mutex WaitOne()."); } // try { InfoLogMappedPacket InfoLogMapFile = new InfoLogMappedPacket(); int nSetSize = Marshal.SizeOf(InfoLogMapFile); byte[] ucSetLogArray = new byte[nSetSize]; InfoLogMapFile = (InfoLogMappedPacket)SystemXNetSerialization.RawDeSerialize(ucSetLogArray, InfoLogMapFile.GetType()); Array.Copy(value, 0, InfoLogMapFile.bLogDataReady, 0, nMaxInfoFullAccessSize); ucCurrentArr = StructToByte(InfoLogMapFile); nSize = ucCurrentArr.Count(); //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateFromFile( @ParameterMap.strSetPath + ParameterMap.strSetFileName, //file location FileMode.OpenOrCreate, //create new file if not exist, open if exist ParameterMap.strSetMapName, //map name nSize)) //size { //update the number to memory view using (var stream = memMapFile.CreateViewStream()) using (var writer = new BinaryWriter(stream)) { writer.Seek(0, SeekOrigin.Begin); writer.Write(ucCurrentArr); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Set bool[][1]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Set bool[][2]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file } } public bool ForceCheckFile() { bool bCheckResult = false; bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName, out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("InfoLogSharedMemory.CheckFile failed Mutex WaitOne()."); } // if (File.Exists(@ParameterMap.strSetPath + ParameterMap.strSetFileName)) bCheckResult = true; else bCheckResult = false; } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.CheckFile] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); bCheckResult = false; } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } return bCheckResult; } public bool CheckExistsInfoFile() { if (File.Exists(@ParameterMap.strSetPath + ParameterMap.strSetFileName)) return true; else return false; } public bool CheckFile() { bool bCheckResult = false; bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName, out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName); } else { bSubMutexResult = _mutexSub.WaitOne(100); if (bSubMutexResult == false) throw new Exception("InfoLogSharedMemory.CheckFile failed Mutex WaitOne()."); } // if (File.Exists(@ParameterMap.strSetPath + ParameterMap.strSetFileName)) bCheckResult = true; else bCheckResult = false; } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.CheckFile] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); bCheckResult = false; } finally { //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } return bCheckResult; } public bool[] Get(out bool bFindInfoLogResult, int nSetSize = int.MinValue) { bFindInfoLogResult = false; bool[] bGetInfoLogStation = new bool[nMaxInfoFullAccessSize]; byte[] ucGetArr = null; bool bSubMutexResult = true; try { if (!Mutex.TryOpenExisting(ParameterMap.strSetAccessMutexName, out _mutexSub)) { _mutexSub = new Mutex(true, ParameterMap.strSetAccessMutexName); } else { bSubMutexResult = _mutexSub.WaitOne(); if (bSubMutexResult == false) throw new Exception("InfoLogSharedMemory.Get failed Mutex WaitOne()."); } // try { if (nSetSize != int.MinValue) nSize = nSetSize; //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateFromFile( @ParameterMap.strSetPath + ParameterMap.strSetFileName, //file location FileMode.Open, //create new file if not exist, open if exist ParameterMap.strSetMapName, //map name nSize)) //size { //get last number from memory view using (var stream = memMapFile.CreateViewStream()) using (var reader = new BinaryReader(stream)) { stream.Seek(0, SeekOrigin.Begin); ucGetArr = reader.ReadBytes(nSize); InfoLogMappedPacket GetInfoMappedFile = ByteToStruct(ucGetArr); Array.Copy(GetInfoMappedFile.bLogDataReady, 0, bGetInfoLogStation, 0, nMaxInfoFullAccessSize); bFindInfoLogResult = true; } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Get[1]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { /*if (File.Exists(@"D:\CpServerXLogSharedMemoryMap" + nPos.ToString("D03"))) File.Delete(@"D:\CpServerXLogSharedMemoryMap" + nPos.ToString("D03"));*/ //release the mutex for other process to access the memory mapped file if (bSubMutexResult) { if (_mutexSub != null) _mutexSub.ReleaseMutex(); } } } catch (Exception e) { MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + " [SystemX.Net.Platform.SystemX.Common : InfoLogSharedMemory.Get[2]] " + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG); } finally { //release the mutex for other process to access the memory mapped file } return bGetInfoLogStation; } public void Dispose() { if (!bDisposed) { //Manage // //Unmanag if (_mutexSub != null) { _mutexSub.Dispose(); _mutexSub = null; } bDisposed = true; } } } }