1050 lines
35 KiB
C#
1050 lines
35 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using SystemX.Common;
|
|
using SystemX.Common.Archive;
|
|
using SystemX.Common.Serialization;
|
|
using SystemX.Net.Comm;
|
|
using SystemX.Net.BaseProtocol;
|
|
using SystemX.Common.Protocol;
|
|
using System.Collections.Concurrent;
|
|
|
|
using static SystemX.Net.Platform.Common.Util.LogMessage;
|
|
|
|
namespace SystemX.Net.Schedule
|
|
{
|
|
//
|
|
// 요약:
|
|
// Socket error information
|
|
public class CommonScheduleException : Exception
|
|
{
|
|
public CommonScheduleException()
|
|
{
|
|
}
|
|
|
|
public CommonScheduleException(string message)
|
|
: base(message)
|
|
{
|
|
}
|
|
|
|
public CommonScheduleException(string message, Exception inner)
|
|
: base(message, inner)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class PacketFlowControl : IDisposable
|
|
{
|
|
public const byte CommonErrCode = 128;
|
|
|
|
public const byte TransferResultToken = 127;
|
|
|
|
public const byte TestListResultToken = 126;
|
|
|
|
public const byte CommInfoAutoToken = 125;
|
|
|
|
public const byte CommInfoManualToken = 124;
|
|
|
|
private const int m_iLmtCnt = 0;
|
|
|
|
private enum QUEUE_TYPE
|
|
{
|
|
SEND = 0,
|
|
RECEIVE = 1,
|
|
}
|
|
|
|
private string m_strLoadPos;
|
|
private string m_strFilePos;
|
|
|
|
private Task taskSendQueue;
|
|
private bool m_bThreadSendBlock;
|
|
|
|
private Task taskRecvQueue;
|
|
private bool m_bThreadRecvBlock;
|
|
|
|
private XSchedule xSchedule;
|
|
private XDataSchedule xDataSchedule;
|
|
|
|
private SystemXSocket refControlSocket;
|
|
|
|
private XPacket LastSendInfo;
|
|
private XPacket LastRecvInfo;
|
|
|
|
private FlowControlType _fct;
|
|
|
|
private DateTime LastDT;
|
|
private byte[] LastByte;
|
|
private int nLastLabel;
|
|
|
|
private int m_iNumber;
|
|
//
|
|
private CancellationTokenSource CTS;
|
|
private CancellationToken CT;
|
|
//
|
|
public ScheduleLabelManage STM;
|
|
|
|
private PacketCalculate PacketAnalyzerWait;
|
|
|
|
public bool bTargetListenFlow;
|
|
|
|
public PacketFlowControl(FlowControlType fct, SystemXSocket refSocket)
|
|
{
|
|
bTargetListenFlow = false;
|
|
|
|
CTS = new CancellationTokenSource();
|
|
CT = CTS.Token;
|
|
|
|
STM = new ScheduleLabelManage();
|
|
STM.SetManageLabel();
|
|
|
|
_fct = fct;
|
|
|
|
refControlSocket = refSocket;
|
|
|
|
m_iNumber = refControlSocket.nSocketNumber;
|
|
|
|
m_strLoadPos = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;
|
|
m_strLoadPos += @"\Restore\" + fct.ToString() + @"\";
|
|
|
|
if (Directory.Exists(m_strLoadPos) == false)
|
|
Directory.CreateDirectory(m_strLoadPos);
|
|
|
|
m_strFilePos = m_strLoadPos + m_iNumber.ToString("D2") + ".QRC";
|
|
|
|
taskSendQueue = null;
|
|
m_bThreadSendBlock = false;
|
|
|
|
taskRecvQueue = null;
|
|
m_bThreadRecvBlock = false;
|
|
|
|
xSchedule = new XSchedule();
|
|
|
|
//패킷 복구 기능 임시 제거
|
|
//ReadRestore();
|
|
|
|
taskSendQueue = new Task(new Action(WatchSendQueue), CT);
|
|
taskSendQueue.Start();
|
|
|
|
taskRecvQueue = new Task(new Action(WatchRecvQueue), CT);
|
|
taskRecvQueue.Start();
|
|
|
|
LastSendInfo = null;
|
|
LastRecvInfo = null;
|
|
|
|
PacketAnalyzerWait = new PacketCalculate();
|
|
PacketAnalyzerWait.WorkerReportsProgress = true;
|
|
PacketAnalyzerWait.WorkerSupportsCancellation = true;
|
|
PacketAnalyzerWait.PacketAnalyzerCompleted += calculatorPacket_CalculateCompleted;
|
|
}
|
|
|
|
~PacketFlowControl()
|
|
{
|
|
}
|
|
|
|
public void SetRefSocketPacketClear()
|
|
{
|
|
refControlSocket.SetRefSocketPacketClear();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
CTS.Cancel();
|
|
|
|
// dispose managed resource (종결자를 가진 객체의 자원 해제)
|
|
if (taskSendQueue != null)
|
|
{
|
|
taskSendQueue.ContinueWith(t =>
|
|
{
|
|
if (bTargetListenFlow == false)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
|
|
@"taskSendQueue " + m_iNumber.ToString("D2") + " END. [Systemx.Net.Schedule : PacketFlowControl.Dispose(TRUE)]",
|
|
ConsoleColor.White,
|
|
LogMessageLevel.DEBUG);
|
|
}
|
|
});
|
|
m_bThreadSendBlock = true;
|
|
|
|
taskSendQueue.ConfigureAwait(false);
|
|
//taskSendQueue.Wait();
|
|
}
|
|
if (taskRecvQueue != null)
|
|
{
|
|
taskRecvQueue.ContinueWith(t =>
|
|
{
|
|
if (bTargetListenFlow == false)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
|
|
@"taskRecvQueue " + m_iNumber.ToString("D2") + " END. [Systemx.Net.Schedule : PacketFlowControl.Dispose(TRUE)]",
|
|
ConsoleColor.White,
|
|
LogMessageLevel.DEBUG);
|
|
}
|
|
});
|
|
|
|
m_bThreadRecvBlock = true;
|
|
|
|
taskRecvQueue.ConfigureAwait(false);
|
|
//taskRecvQueue.Wait();
|
|
}
|
|
|
|
PacketAnalyzerWait.PacketAnalyzerCompleted -= calculatorPacket_CalculateCompleted;
|
|
|
|
RawStoreQueueClear();
|
|
|
|
//패킷 백엄 기능 임시 제거
|
|
//WriteRestore();
|
|
|
|
// do releasing unmanaged resource (종결자가 없는 객체의 자원 해제)
|
|
// i.e. close file handle of operating systems
|
|
|
|
// suppress calling of Finalizer
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
|
|
private void ReadRestore()
|
|
{
|
|
xDataSchedule = new XDataSchedule();
|
|
|
|
using (FileStream fs = new FileStream(m_strFilePos, FileMode.OpenOrCreate, FileAccess.Read))
|
|
{
|
|
fs.Seek(0, SeekOrigin.Begin);
|
|
|
|
byte[] ucCompressQueueData = new byte[fs.Length];
|
|
int iReadCount = fs.Read(ucCompressQueueData, 0, (int)fs.Length);
|
|
|
|
if (iReadCount > 0)
|
|
{
|
|
byte[] ucDeCompressQueueData = XDataArchive.DecompressDeflateByteToByte(ucCompressQueueData);
|
|
xDataSchedule = SystemXNetSerialization.ByteArrayToObject<XDataSchedule>(ucDeCompressQueueData);
|
|
}
|
|
}
|
|
|
|
File.Delete(m_strFilePos);
|
|
|
|
//
|
|
foreach (byte[] ucData in xDataSchedule.SendQueue)
|
|
{
|
|
XPacket tpNew = new XPacket();
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = true;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = null;
|
|
|
|
xSchedule.SendQueue.Enqueue(tpNew);
|
|
}
|
|
foreach (byte[] ucData in xDataSchedule.ReplySendQueue)
|
|
{
|
|
XPacket tpNew = new XPacket();
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = false;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = null;
|
|
|
|
xSchedule.ReplySendQueue.Enqueue(tpNew);
|
|
}
|
|
foreach (byte[] ucData in xDataSchedule.SendRawSetQueue)
|
|
{
|
|
XPacket tpNew = new XPacket();
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = false;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = null;
|
|
|
|
xSchedule.SendQueue.Enqueue(tpNew);
|
|
xSchedule.SendRawSetQueue.Enqueue(tpNew);
|
|
}
|
|
foreach (byte[] ucData in xDataSchedule.RecvQueue)
|
|
{
|
|
XPacket tpNew = new XPacket();
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = true;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = null;
|
|
|
|
xSchedule.RecvQueue.Enqueue(tpNew);
|
|
}
|
|
}
|
|
|
|
private void WriteRestore()
|
|
{
|
|
xDataSchedule = new XDataSchedule();
|
|
|
|
xDataSchedule.SendQueue.Clear();
|
|
xDataSchedule.ReplySendQueue.Clear();
|
|
xDataSchedule.SendRawSetQueue.Clear();
|
|
|
|
xDataSchedule.RecvQueue.Clear();
|
|
|
|
foreach (XPacket XPData in xSchedule.SendQueue.ToList<XPacket>())
|
|
{
|
|
xDataSchedule.SendQueue.Add(XPData.ucPacketBytes);
|
|
}
|
|
foreach (XPacket XPData in xSchedule.ReplySendQueue.ToList<XPacket>())
|
|
{
|
|
xDataSchedule.ReplySendQueue.Add(XPData.ucPacketBytes);
|
|
}
|
|
foreach (XPacket XPData in xSchedule.SendRawSetQueue.ToList<XPacket>())
|
|
{
|
|
xDataSchedule.SendRawSetQueue.Add(XPData.ucPacketBytes);
|
|
}
|
|
foreach (XPacket XPData in xSchedule.RecvQueue.ToList<XPacket>())
|
|
{
|
|
xDataSchedule.RecvQueue.Add(XPData.ucPacketBytes);
|
|
}
|
|
|
|
using (FileStream fs = new FileStream(m_strFilePos, FileMode.OpenOrCreate, FileAccess.Write))
|
|
{
|
|
byte[] ucQueueData = SystemXNetSerialization.ObjectToByteArray(xDataSchedule);
|
|
byte[] ucCompressQueueData = XDataArchive.CompressDeflateByteToByte(ucQueueData);
|
|
|
|
fs.Seek(0, SeekOrigin.Begin);
|
|
|
|
fs.Write(ucCompressQueueData, 0, ucCompressQueueData.Length);
|
|
}
|
|
}
|
|
|
|
private void WriteRestore(string strFilePos, XPacket GetPacket)
|
|
{
|
|
using (FileStream fs = new FileStream(strFilePos, FileMode.OpenOrCreate, FileAccess.Write))
|
|
{
|
|
byte[] ucQueueData = SystemXNetSerialization.ObjectToByteArray(GetPacket);
|
|
byte[] ucCompressQueueData = XDataArchive.CompressDeflateByteToByte(ucQueueData);
|
|
|
|
fs.Seek(0, SeekOrigin.Begin);
|
|
|
|
fs.Write(ucCompressQueueData, 0, ucCompressQueueData.Length);
|
|
}
|
|
}
|
|
|
|
private async void WatchSendQueue()
|
|
{
|
|
await Task.Delay(250).ConfigureAwait(false);
|
|
|
|
while (!m_bThreadSendBlock)
|
|
{
|
|
try
|
|
{
|
|
CT.ThrowIfCancellationRequested();
|
|
}
|
|
catch (OperationCanceledException CancelEx)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Work Canceled. [Systemx.Net.Schedule : PacketFlowControl.WatchSendQueue]\r\n" + CancelEx.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
|
|
|
|
break;
|
|
}
|
|
//
|
|
try
|
|
{
|
|
QuerySendFirstDetect();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//throw new CommonScheduleException("General Queue Schedule failed.[Systemx.Net.Schedule : PacketFlowControl.WatchSendQueue]");
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"General Queue Schedule failed.[Systemx.Net.Schedule : PacketFlowControl.WatchSendQueue]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
|
|
}
|
|
|
|
await Task.Delay(10).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
private async void WatchRecvQueue()
|
|
{
|
|
await Task.Delay(250).ConfigureAwait(false);
|
|
|
|
while (!m_bThreadRecvBlock)
|
|
{
|
|
try
|
|
{
|
|
CT.ThrowIfCancellationRequested();
|
|
}
|
|
catch (OperationCanceledException CancelEx)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Work Canceled. [Systemx.Net.Schedule : PacketFlowControl.WatchRecvQueue]\r\n" + CancelEx.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
|
|
|
|
break;
|
|
}
|
|
//
|
|
try
|
|
{
|
|
XPacket getPacket = QueryRecvFirstDetect();
|
|
|
|
if (getPacket != null)
|
|
RecvCaculationRun(getPacket);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//throw new CommonScheduleException("General Queue Schedule failed.[Systemx.Net.Schedule : PacketFlowControl.WatchRecvQueue]");
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"General Queue Schedule failed.[Systemx.Net.Schedule : PacketFlowControl.WatchRecvQueue]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
|
|
}
|
|
|
|
await Task.Delay(10).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
public void RecvCaculationRun(XPacket Packet)
|
|
{
|
|
if (Packet != null)
|
|
{
|
|
PacketAnalyzerWait.WorkerReportsProgress = true;
|
|
PacketAnalyzerWait.WorkerSupportsCancellation = true;
|
|
|
|
PacketAnalyzerWait.CalculateAsync(Packet);
|
|
}
|
|
}
|
|
|
|
void calculatorPacket_ProgressChanged(object sender, PacketProgressChangedEventArgs e)
|
|
{
|
|
;//e.ProgressPercentage;
|
|
}
|
|
|
|
void calculatorPacket_CalculateCompleted(object sender, PacketAnalyzerCompletedEventArgs e)
|
|
{
|
|
//Cancel
|
|
if (e.Cancelled)
|
|
{
|
|
RecvPacketCycle();
|
|
}
|
|
else
|
|
{
|
|
//Success
|
|
if (e.Error == null)
|
|
{
|
|
XData getXData = (XData)e.Result;
|
|
|
|
byte ngetLabel = getXData.nLabel;
|
|
|
|
xSchedule.RecvResultData.Enqueue(getXData);
|
|
|
|
if (getXData.nLabel >= 0 &&
|
|
getXData.nLabel < STM.GetLabelSize())
|
|
STM.SetLabel(ngetLabel, getXData);
|
|
|
|
SetRecvPacketDrop();
|
|
}
|
|
else
|
|
{
|
|
RecvPacketCycle();
|
|
}
|
|
}
|
|
}
|
|
|
|
public XData GetResultPacketData()
|
|
{
|
|
XData getXData = null;
|
|
|
|
if (xSchedule.RecvResultData.IsEmpty == false)
|
|
{
|
|
if (xSchedule.RecvResultData.TryDequeue(out getXData) == false)
|
|
getXData = null;
|
|
}
|
|
|
|
return getXData;
|
|
}
|
|
public XPacket GetCurrentSendProcessData()
|
|
{
|
|
if (LastSendInfo != null)
|
|
return LastSendInfo;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public XPacket GetCurrentRecvProcessData()
|
|
{
|
|
if (LastRecvInfo != null)
|
|
return LastRecvInfo;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public int GetSendQueueSize()
|
|
{
|
|
return xSchedule.SendQueue.Count();
|
|
}
|
|
|
|
public int GetRecvQueueSize()
|
|
{
|
|
return xSchedule.RecvQueue.Count();
|
|
}
|
|
|
|
private XPacket RetryDequeue(ConcurrentQueue<XPacket> cq)
|
|
{
|
|
XPacket getXPacket = null;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
if (cq.TryDequeue(out getXPacket))
|
|
break;
|
|
else
|
|
getXPacket = null;
|
|
}
|
|
|
|
return getXPacket;
|
|
}
|
|
|
|
private bool RetryPeek(ConcurrentQueue<XPacket> cq)
|
|
{
|
|
XPacket getXPacket = null;
|
|
|
|
bool bResult = true;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
if (cq.TryPeek(out getXPacket))
|
|
{
|
|
bResult = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
bResult = false;
|
|
|
|
getXPacket = null;
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
private void RawStoreQueueClear()
|
|
{
|
|
XPacket GetxPacket;
|
|
while (true)
|
|
{
|
|
if (xSchedule.SendRawSetQueue.IsEmpty)
|
|
break;
|
|
|
|
if (xSchedule.SendRawSetQueue.TryDequeue(out GetxPacket))
|
|
;//
|
|
else
|
|
{
|
|
GetxPacket = RetryDequeue(xSchedule.SendRawSetQueue);
|
|
|
|
if (GetxPacket != null)
|
|
;//
|
|
}
|
|
}
|
|
}
|
|
|
|
public int getRawQueueCnt()
|
|
{
|
|
return xSchedule.SendRawSetQueue.Count;
|
|
}
|
|
|
|
public void RawStoreQueuePOP()
|
|
{
|
|
XPacket StorePacket;
|
|
|
|
int iPopNum = 0;
|
|
int iDequeueCnt = 0;
|
|
|
|
DateTime dtSend;
|
|
|
|
if (xSchedule.SendRawSetQueue.IsEmpty == false)
|
|
{
|
|
StorePacket = xSchedule.SendRawSetQueue.ElementAt(0);
|
|
dtSend = StorePacket.dtPacketTime;
|
|
|
|
for (int i = 0; i < xSchedule.SendRawSetQueue.Count; i++)
|
|
{
|
|
StorePacket = xSchedule.SendRawSetQueue.ElementAt(i);
|
|
|
|
if (dtSend.Ticks == StorePacket.dtPacketTime.Ticks)
|
|
iPopNum++;
|
|
else
|
|
break;
|
|
}
|
|
while (true)
|
|
{
|
|
if (xSchedule.SendRawSetQueue.IsEmpty)
|
|
break;
|
|
|
|
if (xSchedule.SendRawSetQueue.TryDequeue(out StorePacket))
|
|
iDequeueCnt++;
|
|
else
|
|
{
|
|
StorePacket = RetryDequeue(xSchedule.SendRawSetQueue);
|
|
|
|
if (StorePacket != null)
|
|
iDequeueCnt++;
|
|
}
|
|
|
|
if (iDequeueCnt >= iPopNum)
|
|
break;
|
|
}
|
|
|
|
if (xSchedule.SendRawSetQueue.IsEmpty == false)
|
|
{
|
|
StorePacket = xSchedule.SendRawSetQueue.ElementAt(0);
|
|
|
|
if (dtSend.Ticks > StorePacket.dtPacketTime.Ticks)
|
|
{
|
|
while (true)
|
|
{
|
|
if (xSchedule.SendRawSetQueue.IsEmpty)
|
|
break;
|
|
|
|
if (xSchedule.SendRawSetQueue.TryPeek(out StorePacket))
|
|
{
|
|
if (dtSend.Ticks > StorePacket.dtPacketTime.Ticks)
|
|
{
|
|
if (xSchedule.SendRawSetQueue.TryDequeue(out StorePacket) == false)
|
|
RetryDequeue(xSchedule.SendRawSetQueue);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (RetryPeek(xSchedule.SendRawSetQueue))
|
|
{
|
|
if (dtSend.Ticks > StorePacket.dtPacketTime.Ticks)
|
|
{
|
|
if (xSchedule.SendRawSetQueue.TryDequeue(out StorePacket) == false)
|
|
RetryDequeue(xSchedule.SendRawSetQueue);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public byte InsertSendQueue(DateTime dtPacket, byte[] ucData, SendRecvCallEvent CallProcess, byte ucSetSendLabel)
|
|
{
|
|
bool bInsertResult = true;
|
|
|
|
byte ucLabel = ucSetSendLabel;
|
|
|
|
XPacket tpNew;
|
|
|
|
try
|
|
{
|
|
try
|
|
{
|
|
tpNew = new XPacket();
|
|
|
|
if (dtPacket == null)
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
else
|
|
tpNew.dtPacketTime = dtPacket;
|
|
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = true;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = CallProcess;
|
|
tpNew.nLabel = ucLabel;
|
|
|
|
xSchedule.SendQueue.Enqueue(tpNew);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
bInsertResult = false;
|
|
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Data packet queue insert fail. [Systemx.Net.Schedule : PacketFlowControl.InsertSendQueue]\r\n" + e.Message, ConsoleColor.Red, LogMessageLevel.DEBUG);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (bInsertResult == false) ucLabel = CommonErrCode;
|
|
}
|
|
|
|
return ucLabel;
|
|
}
|
|
|
|
public byte InsertSendQueue(DateTime dtPacket, byte[] ucData, SendRecvCallEvent CallProcess, bool bUseLabel = false, bool bResponsCall = true, bool bRawData = false)
|
|
{
|
|
bool bInsertResult = true;
|
|
|
|
byte nLabel = 0;
|
|
|
|
XPacket tpNew;
|
|
|
|
try
|
|
{
|
|
try
|
|
{
|
|
if (bUseLabel)
|
|
nLabel = STM.GetLabel();
|
|
|
|
tpNew = new XPacket();
|
|
|
|
if (dtPacket == null)
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
else
|
|
tpNew.dtPacketTime = dtPacket;
|
|
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = bResponsCall;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = CallProcess;
|
|
tpNew.nLabel = nLabel;
|
|
|
|
if (bResponsCall)
|
|
{
|
|
xSchedule.SendQueue.Enqueue(tpNew);
|
|
|
|
if (bRawData)
|
|
xSchedule.SendRawSetQueue.Enqueue(tpNew);
|
|
}
|
|
else
|
|
xSchedule.ReplySendQueue.Enqueue(tpNew);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
bInsertResult = false;
|
|
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Data packet queue insert fail. [Systemx.Net.Schedule : PacketFlowControl.InsertSendQueue]\r\n" + e.Message, ConsoleColor.Red, LogMessageLevel.DEBUG);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (bInsertResult == false) nLabel = CommonErrCode;
|
|
}
|
|
|
|
return nLabel;
|
|
}
|
|
|
|
public byte InsertSendQueue(DateTime dtPacket, byte[] ucData, SendRecvCallEvent CallProcess, int nSelectSendLabel, bool bResponsCall = true, bool bRawData = false)
|
|
{
|
|
bool bInsertResult = true;
|
|
|
|
byte nLabel = 0;
|
|
|
|
XPacket tpNew;
|
|
|
|
try
|
|
{
|
|
try
|
|
{
|
|
nLabel = STM.GetLabel(nSelectSendLabel);
|
|
|
|
tpNew = new XPacket();
|
|
|
|
if (dtPacket == null)
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
else
|
|
tpNew.dtPacketTime = dtPacket;
|
|
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = bResponsCall;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = CallProcess;
|
|
tpNew.nLabel = nLabel;
|
|
|
|
if (bResponsCall)
|
|
{
|
|
xSchedule.SendQueue.Enqueue(tpNew);
|
|
|
|
if (bRawData)
|
|
xSchedule.SendRawSetQueue.Enqueue(tpNew);
|
|
}
|
|
else
|
|
xSchedule.ReplySendQueue.Enqueue(tpNew);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
bInsertResult = false;
|
|
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Data packet queue insert fail. [Systemx.Net.Schedule : PacketFlowControl.InsertSendQueue]\r\n" + e.Message, ConsoleColor.Red, LogMessageLevel.DEBUG);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (bInsertResult == false) nLabel = CommonErrCode;
|
|
}
|
|
|
|
return nLabel;
|
|
}
|
|
|
|
public void InsertRecvQueue(byte[] ucData, SendRecvCallEvent CallProcess, byte nLabel, bool bResponsCall = true)
|
|
{
|
|
XPacket tpNew = new XPacket();
|
|
tpNew.dtPacketTime = DateTime.Now;
|
|
tpNew.iRetryNum = 0;
|
|
tpNew.bReplayPacket = bResponsCall;
|
|
tpNew.ucPacketBytes = ucData;
|
|
tpNew.deleCallEvt = CallProcess;
|
|
tpNew.nLabel = nLabel;
|
|
|
|
xSchedule.RecvQueue.Enqueue(tpNew);
|
|
}
|
|
|
|
public XPacket QuerySendFirstDetect()
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.SendQueue.IsEmpty == false && LastSendInfo == null)
|
|
{
|
|
if (xSchedule.SendQueue.TryPeek(out getInfo))
|
|
{
|
|
try
|
|
{
|
|
byte[] ucSendByte = new byte[getInfo.ucPacketBytes.Count() + 1];
|
|
ucSendByte[0] = (byte)getInfo.nLabel;
|
|
|
|
Array.Copy(getInfo.ucPacketBytes, 0, ucSendByte, 1, getInfo.ucPacketBytes.Count());
|
|
|
|
if (refControlSocket.BeginSend(ucSendByte))
|
|
{
|
|
if (getInfo.bReplayPacket)
|
|
{
|
|
LastSendInfo = getInfo;
|
|
|
|
LastDT = DateTime.Now;
|
|
LastByte = LastSendInfo.ucPacketBytes;
|
|
nLastLabel = LastSendInfo.nLabel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//소켓 자체가 전송 실패시(소켓 에러 - 연결 해제 및 기타 등등) 이전 내역 패킷 및 현재 큐 제거
|
|
SetSendPacketDrop();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"SendQueue control failed.[Systemx.Net.Schedule : PacketFlowControl.QuerySendFirstDetect]\r\n" + ex.Message, ConsoleColor.Red, LogMessageLevel.FATAL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
if (LastSendInfo != null)
|
|
{
|
|
TimeSpan dateDiff = DateTime.Now - LastDT;
|
|
double dGetms = dateDiff.TotalMilliseconds;
|
|
|
|
if (dGetms >= 20000.0)
|
|
LastSendInfo = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"LastSendInfo control failed.[Systemx.Net.Schedule : PacketFlowControl.QuerySendFirstDetect]\r\n" + ex.Message, ConsoleColor.Red, LogMessageLevel.FATAL);
|
|
}
|
|
|
|
if (xSchedule.ReplySendQueue.IsEmpty == false)
|
|
{
|
|
if (xSchedule.ReplySendQueue.TryPeek(out getInfo))
|
|
{
|
|
try
|
|
{
|
|
byte[] ucSendByte = new byte[getInfo.ucPacketBytes.Count() + 1];
|
|
ucSendByte[0] = (byte)getInfo.nLabel;
|
|
|
|
Array.Copy(getInfo.ucPacketBytes, 0, ucSendByte, 1, getInfo.ucPacketBytes.Count());
|
|
|
|
if (refControlSocket.BeginSend(ucSendByte))
|
|
{
|
|
if (xSchedule.ReplySendQueue.TryDequeue(out getInfo) == false)
|
|
RetryDequeue(xSchedule.ReplySendQueue);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"ReplySendQueue control failed.[Systemx.Net.Schedule : PacketFlowControl.QuerySendFirstDetect]\r\n" + ex.Message, ConsoleColor.Red, LogMessageLevel.FATAL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return getInfo;
|
|
}
|
|
|
|
public XPacket QueryRecvFirstDetect()
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.RecvQueue.IsEmpty == false && LastRecvInfo == null)
|
|
{
|
|
if (xSchedule.RecvQueue.TryPeek(out getInfo))
|
|
LastRecvInfo = getInfo;
|
|
}
|
|
|
|
return getInfo;
|
|
}
|
|
|
|
public XPacket GetSendPacketPeek()
|
|
{
|
|
if (xSchedule.SendQueue.IsEmpty == false)
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.SendQueue.TryPeek(out getInfo))
|
|
return getInfo;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public XPacket GetRecvPacketPeek()
|
|
{
|
|
if (xSchedule.RecvQueue.IsEmpty == false)
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.RecvQueue.TryPeek(out getInfo))
|
|
LastRecvInfo = getInfo;
|
|
|
|
return getInfo;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public XPacket SetSendPacketDrop()
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.SendQueue.IsEmpty == false)
|
|
{
|
|
if (xSchedule.SendQueue.TryDequeue(out getInfo))
|
|
LastSendInfo = null;
|
|
else
|
|
SetSendPacketDrop();
|
|
}
|
|
else
|
|
LastSendInfo = null;
|
|
|
|
return getInfo;
|
|
}
|
|
|
|
public XPacket SetRecvPacketDrop()
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.RecvQueue.IsEmpty == false)
|
|
{
|
|
if (xSchedule.RecvQueue.TryDequeue(out getInfo))
|
|
LastRecvInfo = null;
|
|
else
|
|
SetRecvPacketDrop();
|
|
}
|
|
else
|
|
LastRecvInfo = null;
|
|
|
|
return getInfo;
|
|
}
|
|
|
|
public void SendPacketCycle()
|
|
{
|
|
if (LastSendInfo != null)
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.SendQueue.TryDequeue(out getInfo))
|
|
{
|
|
if (ReferenceEquals(LastSendInfo, getInfo))
|
|
{
|
|
DateTime SetTime = getInfo.dtPacketTime;
|
|
int iCycle = getInfo.iRetryNum;
|
|
bool bGetResponsCall = getInfo.bReplayPacket;
|
|
byte[] ucData = getInfo.ucPacketBytes;
|
|
SendRecvCallEvent CallEvent = getInfo.deleCallEvt;
|
|
byte nGetLabel = getInfo.nLabel;
|
|
|
|
if (iCycle < m_iLmtCnt)
|
|
{
|
|
iCycle += 1;
|
|
|
|
XPacket setNewInfo = new XPacket();
|
|
setNewInfo.dtPacketTime = SetTime;
|
|
setNewInfo.iRetryNum = iCycle;
|
|
setNewInfo.bReplayPacket = bGetResponsCall;
|
|
setNewInfo.ucPacketBytes = ucData;
|
|
setNewInfo.deleCallEvt = CallEvent;
|
|
setNewInfo.nLabel = nGetLabel;
|
|
|
|
xSchedule.SendQueue.Enqueue(setNewInfo);
|
|
}
|
|
else
|
|
{
|
|
//실패한 패킷내용에 대해 기록 남기는 기능 추가
|
|
string strMakeDate = DateTime.Now.ToString(@"\\yyyy\\MM\\dd\\");
|
|
string strFilePos = m_strLoadPos + strMakeDate;
|
|
|
|
Directory.CreateDirectory(strFilePos);
|
|
|
|
strFilePos += @"SendProcessErrorPacket_" + DateTime.Now.ToString("yyMMddHHmmssfff") + "_" + m_iNumber.ToString("D2") + ".EPH";
|
|
|
|
;// WriteRestore(strFilePos, getInfo);
|
|
}
|
|
|
|
LastSendInfo = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RecvPacketCycle()
|
|
{
|
|
if (LastRecvInfo != null)
|
|
{
|
|
XPacket getInfo = null;
|
|
|
|
if (xSchedule.RecvQueue.TryDequeue(out getInfo))
|
|
{
|
|
if (ReferenceEquals(LastRecvInfo, getInfo))
|
|
{
|
|
DateTime SetTime = getInfo.dtPacketTime;
|
|
int iCycle = getInfo.iRetryNum;
|
|
bool bGetResponsCall = getInfo.bReplayPacket;
|
|
byte[] ucData = getInfo.ucPacketBytes;
|
|
SendRecvCallEvent CallEvent = getInfo.deleCallEvt;
|
|
byte nGetLabel = getInfo.nLabel;
|
|
|
|
iCycle += 1;
|
|
|
|
if (iCycle < m_iLmtCnt)
|
|
{
|
|
iCycle += 1;
|
|
|
|
XPacket setNewInfo = new XPacket();
|
|
setNewInfo.dtPacketTime = SetTime;
|
|
setNewInfo.iRetryNum = iCycle;
|
|
setNewInfo.bReplayPacket = bGetResponsCall;
|
|
setNewInfo.ucPacketBytes = ucData;
|
|
setNewInfo.deleCallEvt = CallEvent;
|
|
setNewInfo.nLabel = nGetLabel;
|
|
|
|
xSchedule.RecvQueue.Enqueue(setNewInfo);
|
|
}
|
|
else
|
|
{
|
|
//실패한 패킷내용에 대해 기록 남기는 기능 추가
|
|
string strMakeDate = DateTime.Now.ToString(@"\\yyyy\\MM\\dd\\");
|
|
string strFilePos = m_strLoadPos + strMakeDate;
|
|
|
|
Directory.CreateDirectory(strFilePos);
|
|
|
|
strFilePos += @"RecvProcessErrorPacket_" + DateTime.Now.ToString("yyMMddHHmmssfff") + "_" + m_iNumber.ToString("D2") + ".EPH";
|
|
|
|
;// WriteRestore(strFilePos, getInfo);
|
|
}
|
|
|
|
LastRecvInfo = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|