using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JWH;
using TIBCO.Rendezvous;
namespace JWH.TIB
{
public class ListenerInfo : IDisposable
{
public static int NextID = 1;
#region [ Event ] =====================================================
public delegate void OnReceivedHandler(ListenerInfo sender, MessageReceivedEventArgs args);
public delegate void OnEventHandler(ListenerInfo sender, TibRendezvousEventArgs args);
public event OnReceivedHandler OnReceivedMessage;
public event OnEventHandler OnReceivedEvent;
#endregion
#region [ Properties ] ================================================
public int ID { get; protected set; } = 0;
public XLogger Logger { get; set; } = XLogger.Instance;
public string Name { get; set; } = string.Empty;
public string Subject { get; set; } = string.Empty;
public Listener Listener { get; set; } = null;
public Queue Queue { get { return this?.Listener?.Queue; } }
protected Dispatcher Dispatcher { get; set; } = null;
protected Thread QueueDispatchThread { get; set; } = null;
protected bool QueueDispatchFlag { get; set; } = false;
protected double DispatchInterval { get; set; } = -1;
#endregion
#region [ Constructor ] ===============================================
public ListenerInfo()
{
this.ID = NextID++;
}
~ListenerInfo()
{
this.Dispose();
}
public void Dispose()
{
try
{
if (this.Dispatcher != null)
{
this.Dispatcher.Destroy();
this.Dispatcher = null;
}
if (this.QueueDispatchThread != null)
{
this.QueueDispatchFlag = false;
if (this.QueueDispatchThread.ThreadState != ThreadState.Stopped) this.QueueDispatchThread.Abort();
this.QueueDispatchThread = null;
}
if (this.Listener != null)
{
this.Listener.Destroy();
this.Listener = null;
}
}
catch (Exception ex)
{
this.Logger.Fatal(ex);
throw ex;
}
}
#endregion
#region [ Method ] ====================================================
protected void Raise_ReceivedData(MessageReceivedEventArgs args)
{
this.OnReceivedMessage?.Invoke(this, args);
}
protected void Raise_ReceivedEvent(TibRendezvousEventArgs args)
{
this.OnReceivedEvent?.Invoke(this, args);
}
///
/// 비정상 종료시, 내부 쓰레드가 종료되지 않는다.
///
///
public bool Dispatch()
{
try
{
if (this.Listener == null) return false;
if (this.Listener.Queue == null) return false;
if (this.QueueDispatchThread != null) return false;
this.Dispatcher = new Dispatcher(this.Listener.Queue);
return true;
}
catch (Exception ex)
{
throw ex;
}
}
///
/// Queue.Dispatch() or Queue.TimedDispatch(interval)
///
///
///
public bool QueueDispatch(double interval = -1)
{
try
{
if (this.Listener == null) return false;
if (this.Listener.Queue == null) return false;
if (this.Dispatcher != null) return false;
this.DispatchInterval = interval;
if (this.QueueDispatchThread != null) this.QueueDispatchThread.Abort();
this.QueueDispatchThread = new Thread(new ThreadStart(this.QueueDispatch_Threading));
this.QueueDispatchThread.IsBackground = true;
this.QueueDispatchThread.Start();
return true;
}
catch (Exception ex)
{
throw ex;
}
}
protected void QueueDispatch_Threading()
{
try
{
this.Logger.Debug($"Start {this.Subject}");
this.QueueDispatchFlag = true;
while (this.QueueDispatchFlag)
{
try
{
if (this.DispatchInterval > 0) this.Queue.TimedDispatch(this.DispatchInterval);
else this.Queue.Dispatch();
//this.Logger.Info($"Queue.Count is {this.Queue.Count}");
}
catch (RendezvousException ex)
{
this.Logger.Fatal(ex);
}
catch (Exception ex)
{
this.Logger.Fatal(ex);
}
}
this.QueueDispatchFlag = false;
this.QueueDispatchThread = null;
this.Logger.Debug($"Finish");
}
catch (Exception ex)
{
// Tread Exception...!
throw ex;
}
}
public virtual void ReceivedMessage(object sender, MessageReceivedEventArgs eventArgs)
{
this.Raise_ReceivedData(eventArgs);
}
#endregion
}
public class TibRendezvousEventArgs : EventArgs
{
public Message Message { get; private set; } = null;
public string SendSubject { get; private set; } = string.Empty;
public string ReplySubject { get; private set; } = string.Empty;
public string Class { get; private set; } = string.Empty;
public string Source { get; private set; } = string.Empty;
public string Name { get; private set; } = string.Empty;
public Dictionary Properties { get; private set; } = new Dictionary();
public TibRendezvousEventArgs()
{
}
public TibRendezvousEventArgs(Message message)
{
this.Message = message;
this.SendSubject = message.SendSubject;
this.ReplySubject = message.ReplySubject;
for (uint i = 0; i < message.FieldCount; i++)
{
MessageField field = message.GetFieldByIndex(i);
if (string.Compare(field.Name, "ADV_CLASS", true) == 0) { this.Class = field.Value.ToString(); continue; }
if (string.Compare(field.Name, "ADV_SOURCE", true) == 0) { this.Source = field.Value.ToString(); continue; }
if (string.Compare(field.Name, "ADV_NAME", true) == 0) { this.Name = field.Value.ToString(); continue; }
if (field.Value?.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)field.Value;
if (dt.Kind != DateTimeKind.Local)
{
TimeZoneInfo localZone = TimeZoneInfo.Local;
DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(dt, TimeZoneInfo.Local);
this.Properties[field.Name] = localTime;
continue;
}
}
this.Properties[field.Name] = field.Value;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
//sb.Append($"[{this.SendSubject}] ");
//if (!string.IsNullOrEmpty(this.ReplySubject)) sb.Append($"From {this.ReplySubject}: ");
//sb.AppendLine();
sb.Append($"ADV_CLASS='{this.Class}' ");
sb.Append($"ADV_SOURCE='{this.Source}' ");
sb.Append($"ADV_NAME='{this.Name}' ");
foreach (KeyValuePair pair in this.Properties)
sb.Append($"({pair.Value?.GetType().Name}){pair.Key}='{pair.Value?.ToString()}' ");
return sb.ToString();
}
}
}