Files
CPXV2/SystemX.Net.CP.Platform/SystemX.Net.Platform/SystemX.Common/MemoryMappedFileControl.cs
2024-06-26 10:30:00 +09:00

772 lines
28 KiB
C#

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<T>(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<LogMappedPacket>(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<InfoLogMappedPacket>(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;
}
}
}
}