diff --git a/AcceptanceTest/TestBase.cs b/AcceptanceTest/TestBase.cs index 07acedab8..cc9dba3dd 100644 --- a/AcceptanceTest/TestBase.cs +++ b/AcceptanceTest/TestBase.cs @@ -2,6 +2,8 @@ using QuickFix; using System.IO; using System.Net; +using QuickFix.Logger; +using QuickFix.Store; namespace AcceptanceTest; diff --git a/Examples/Executor/Program.cs b/Examples/Executor/Program.cs index 1c38f7caf..a4c74ce31 100644 --- a/Examples/Executor/Program.cs +++ b/Examples/Executor/Program.cs @@ -4,6 +4,8 @@ using System.Runtime.ConstrainedExecution; using System.Text; using QuickFix; +using QuickFix.Logger; +using QuickFix.Store; namespace Executor { diff --git a/Examples/SimpleAcceptor/Program.cs b/Examples/SimpleAcceptor/Program.cs index 47b29441d..e880f4bfb 100644 --- a/Examples/SimpleAcceptor/Program.cs +++ b/Examples/SimpleAcceptor/Program.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Text; using QuickFix; +using QuickFix.Logger; +using QuickFix.Store; using QuickFix.Transport; namespace SimpleAcceptor diff --git a/Examples/TradeClient/Program.cs b/Examples/TradeClient/Program.cs index a79dca86c..cbf8cd616 100644 --- a/Examples/TradeClient/Program.cs +++ b/Examples/TradeClient/Program.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using QuickFix.Logger; +using QuickFix.Store; namespace TradeClient { @@ -31,8 +33,8 @@ static void Main(string[] args) { QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file); TradeClientApp application = new TradeClientApp(); - QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings); - QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings); + IMessageStoreFactory storeFactory = new FileStoreFactory(settings); + ILogFactory logFactory = new ScreenLogFactory(settings); QuickFix.Transport.SocketInitiator initiator = new QuickFix.Transport.SocketInitiator(application, storeFactory, settings, logFactory); // this is a developer-test kludge. do not emulate. diff --git a/QuickFIXn/AbstractInitiator.cs b/QuickFIXn/AbstractInitiator.cs index a02607ca3..915fef9fb 100644 --- a/QuickFIXn/AbstractInitiator.cs +++ b/QuickFIXn/AbstractInitiator.cs @@ -2,6 +2,8 @@ using System.Threading; using System.Collections.Generic; using System; +using QuickFix.Logger; +using QuickFix.Store; namespace QuickFix { diff --git a/QuickFIXn/ClientHandlerThread.cs b/QuickFIXn/ClientHandlerThread.cs index a5cbb074f..365d0372a 100755 --- a/QuickFIXn/ClientHandlerThread.cs +++ b/QuickFIXn/ClientHandlerThread.cs @@ -2,6 +2,7 @@ using System.Net.Sockets; using System.Threading; using System; +using QuickFix.Logger; namespace QuickFix { diff --git a/QuickFIXn/CompositeLog.cs b/QuickFIXn/CompositeLog.cs deleted file mode 100644 index f09a23a1c..000000000 --- a/QuickFIXn/CompositeLog.cs +++ /dev/null @@ -1,73 +0,0 @@ - -using System; - -namespace QuickFix -{ - /// - /// File log implementation - /// - internal class CompositeLog : ILog - { - private ILog[] logs_; - - private bool _disposed = false; - - public CompositeLog(ILog[] logs) - { - logs_ = logs; - } - - public void Clear() - { - DisposedCheck(); - foreach (var log in logs_) - log.Clear(); - } - - public void OnIncoming(string msg) - { - DisposedCheck(); - foreach (var log in logs_) - log.OnIncoming(msg); - } - - public void OnOutgoing(string msg) - { - DisposedCheck(); - foreach (var log in logs_) - log.OnOutgoing(msg); - } - - public void OnEvent(string s) - { - DisposedCheck(); - foreach (var log in logs_) - log.OnEvent(s); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - if (disposing) - { - foreach (var log in logs_) - log.Dispose(); - } - _disposed = true; - } - - private void DisposedCheck() - { - if (_disposed) - throw new System.ObjectDisposedException(this.GetType().Name); - } - - ~CompositeLog() => Dispose(false); - } -} diff --git a/QuickFIXn/CompositeLogFactory.cs b/QuickFIXn/CompositeLogFactory.cs deleted file mode 100644 index e83a969ae..000000000 --- a/QuickFIXn/CompositeLogFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace QuickFix -{ - /// - /// Allows multiple log factories to be used with QuickFIX/N. For example, you could log events to the console and also log all events and messages to a file. - /// - public class CompositeLogFactory : ILogFactory - { - private ILogFactory[] factories_; - - public CompositeLogFactory(ILogFactory[] factories) - { - factories_ = factories; - } - - /// - /// Creates a composite log - /// - /// session ID for the message store - /// - public ILog Create(SessionID sessionID) - { - return new CompositeLog(factories_.Select(f => f.Create(sessionID)).ToArray()); - } - } -} diff --git a/QuickFIXn/FileLog.cs b/QuickFIXn/FileLog.cs deleted file mode 100755 index 43401a07d..000000000 --- a/QuickFIXn/FileLog.cs +++ /dev/null @@ -1,147 +0,0 @@ - -using System; - -namespace QuickFix -{ - /// - /// File log implementation - /// - public class FileLog : ILog, System.IDisposable - { - private object sync_ = new object(); - - private System.IO.StreamWriter messageLog_; - private System.IO.StreamWriter eventLog_; - - private string messageLogFileName_; - private string eventLogFileName_; - - - public FileLog(string fileLogPath) - { - Init(fileLogPath, "GLOBAL"); - } - - public FileLog(string fileLogPath, SessionID sessionID) - { - Init(fileLogPath, Prefix(sessionID)); - } - - - private void Init(string fileLogPath, string prefix) - { - if (!System.IO.Directory.Exists(fileLogPath)) - System.IO.Directory.CreateDirectory(fileLogPath); - - messageLogFileName_ = System.IO.Path.Combine(fileLogPath, prefix + ".messages.current.log"); - eventLogFileName_ = System.IO.Path.Combine(fileLogPath, prefix + ".event.current.log"); - - messageLog_ = new System.IO.StreamWriter(messageLogFileName_,true); - eventLog_ = new System.IO.StreamWriter(eventLogFileName_,true); - - messageLog_.AutoFlush = true; - eventLog_.AutoFlush = true; - } - - public static string Prefix(SessionID sessionID) - { - System.Text.StringBuilder prefix = new System.Text.StringBuilder(sessionID.BeginString) - .Append('-').Append(sessionID.SenderCompID); - if (SessionID.IsSet(sessionID.SenderSubID)) - prefix.Append('_').Append(sessionID.SenderSubID); - if (SessionID.IsSet(sessionID.SenderLocationID)) - prefix.Append('_').Append(sessionID.SenderLocationID); - prefix.Append('-').Append(sessionID.TargetCompID); - if (SessionID.IsSet(sessionID.TargetSubID)) - prefix.Append('_').Append(sessionID.TargetSubID); - if (SessionID.IsSet(sessionID.TargetLocationID)) - prefix.Append('_').Append(sessionID.TargetLocationID); - - if (SessionID.IsSet(sessionID.SessionQualifier)) - prefix.Append('-').Append(sessionID.SessionQualifier); - - return prefix.ToString(); - } - - private void DisposedCheck() - { - if (_disposed) - throw new System.ObjectDisposedException(this.GetType().Name); - } - - #region Log Members - - public void Clear() - { - DisposedCheck(); - - lock (sync_) - { - messageLog_.Close(); - eventLog_.Close(); - - messageLog_ = new System.IO.StreamWriter(messageLogFileName_, false); - eventLog_ = new System.IO.StreamWriter(eventLogFileName_, false); - - messageLog_.AutoFlush = true; - eventLog_.AutoFlush = true; - } - } - - public void OnIncoming(string msg) - { - DisposedCheck(); - - lock (sync_) - { - messageLog_.WriteLine(Fields.Converters.DateTimeConverter.Convert(System.DateTime.UtcNow) + " : " + msg); - } - } - - public void OnOutgoing(string msg) - { - DisposedCheck(); - - lock (sync_) - { - messageLog_.WriteLine(Fields.Converters.DateTimeConverter.Convert(System.DateTime.UtcNow) + " : " + msg); - } - } - - public void OnEvent(string s) - { - DisposedCheck(); - - lock (sync_) - { - eventLog_.WriteLine(Fields.Converters.DateTimeConverter.Convert(System.DateTime.UtcNow) + " : "+ s); - } - } - - #endregion - - #region IDisposable Members - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private bool _disposed = false; - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - if (disposing) - { - if (messageLog_ != null) { messageLog_.Dispose(); } - if (eventLog_ != null) { eventLog_.Dispose(); } - - messageLog_ = null; - eventLog_ = null; - } - _disposed = true; - } - ~FileLog() => Dispose(false); - #endregion - } -} diff --git a/QuickFIXn/FileLogFactory.cs b/QuickFIXn/FileLogFactory.cs deleted file mode 100755 index 9bdc0371d..000000000 --- a/QuickFIXn/FileLogFactory.cs +++ /dev/null @@ -1,30 +0,0 @@ - -namespace QuickFix -{ - /// - /// Creates a message store that stores messages in a file - /// - public class FileLogFactory : ILogFactory - { - SessionSettings settings_; - - #region LogFactory Members - - public FileLogFactory(SessionSettings settings) - { - settings_ = settings; - } - - /// - /// Creates a file-based message store - /// - /// session ID for the message store - /// - public ILog Create(SessionID sessionID) - { - return new FileLog(settings_.Get(sessionID).GetString(SessionSettings.FILE_LOG_PATH), sessionID); - } - - #endregion - } -} diff --git a/QuickFIXn/FileStore.cs b/QuickFIXn/FileStore.cs deleted file mode 100755 index afb221af7..000000000 --- a/QuickFIXn/FileStore.cs +++ /dev/null @@ -1,310 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using QuickFix.Util; - -namespace QuickFix -{ - /// - /// File store implementation - /// - public class FileStore : IMessageStore - { - private class MsgDef - { - public long index { get; private set; } - public int size { get; private set; } - - public MsgDef(long index, int size) - { - this.index = index; - this.size = size; - } - } - - private string seqNumsFileName_; - private string msgFileName_; - private string headerFileName_; - private string sessionFileName_; - - private System.IO.FileStream seqNumsFile_; - private System.IO.FileStream msgFile_; - private System.IO.StreamWriter headerFile_; - - private MemoryStore cache_ = new MemoryStore(); - - System.Collections.Generic.Dictionary offsets_ = new Dictionary(); - - public static string Prefix(SessionID sessionID) - { - System.Text.StringBuilder prefix = new System.Text.StringBuilder(sessionID.BeginString) - .Append('-').Append(sessionID.SenderCompID); - if (SessionID.IsSet(sessionID.SenderSubID)) - prefix.Append('_').Append(sessionID.SenderSubID); - if (SessionID.IsSet(sessionID.SenderLocationID)) - prefix.Append('_').Append(sessionID.SenderLocationID); - prefix.Append('-').Append(sessionID.TargetCompID); - if (SessionID.IsSet(sessionID.TargetSubID)) - prefix.Append('_').Append(sessionID.TargetSubID); - if (SessionID.IsSet(sessionID.TargetLocationID)) - prefix.Append('_').Append(sessionID.TargetLocationID); - - if (SessionID.IsSet(sessionID.SessionQualifier)) - prefix.Append('-').Append(sessionID.SessionQualifier); - - return prefix.ToString(); - } - - public FileStore(string path, SessionID sessionID) - { - if (!System.IO.Directory.Exists(path)) - System.IO.Directory.CreateDirectory(path); - - string prefix = Prefix(sessionID); - - seqNumsFileName_ = System.IO.Path.Combine(path, prefix + ".seqnums"); - msgFileName_ = System.IO.Path.Combine(path, prefix + ".body"); - headerFileName_ = System.IO.Path.Combine(path, prefix + ".header"); - sessionFileName_ = System.IO.Path.Combine(path, prefix + ".session"); - open(); - } - - private void open() - { - close(); - - ConstructFromFileCache(); - InitializeSessionCreateTime(); - - seqNumsFile_ = new System.IO.FileStream(seqNumsFileName_, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); - msgFile_ = new System.IO.FileStream(msgFileName_, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); - headerFile_ = new System.IO.StreamWriter(headerFileName_, true); - } - - private void close() - { - seqNumsFile_?.Dispose(); - msgFile_?.Dispose(); - headerFile_?.Dispose(); - } - - private void PurgeSingleFile(System.IO.Stream stream, string filename) - { - if (stream != null) - stream.Close(); - if (System.IO.File.Exists(filename)) - System.IO.File.Delete(filename); - } - - private void PurgeSingleFile(System.IO.StreamWriter stream, string filename) - { - if (stream != null) - stream.Close(); - if (System.IO.File.Exists(filename)) - System.IO.File.Delete(filename); - } - - private void PurgeSingleFile(string filename) - { - if (System.IO.File.Exists(filename)) - System.IO.File.Delete(filename); - } - - private void PurgeFileCache() - { - PurgeSingleFile(seqNumsFile_, seqNumsFileName_); - PurgeSingleFile(msgFile_, msgFileName_); - PurgeSingleFile(headerFile_, headerFileName_); - PurgeSingleFile(sessionFileName_); - } - - - private void ConstructFromFileCache() - { - offsets_.Clear(); - if (System.IO.File.Exists(headerFileName_)) - { - using (System.IO.StreamReader reader = new System.IO.StreamReader(headerFileName_)) - { - string line; - while ((line = reader.ReadLine()) != null) - { - string[] headerParts = line.Split(','); - if (headerParts.Length == 3) - { - offsets_[Convert.ToUInt64(headerParts[0])] = new MsgDef( - Convert.ToInt64(headerParts[1]), Convert.ToInt32(headerParts[2])); - } - } - } - } - - if (System.IO.File.Exists(seqNumsFileName_)) - { - using (System.IO.StreamReader seqNumReader = new System.IO.StreamReader(seqNumsFileName_)) - { - string[] parts = seqNumReader.ReadToEnd().Split(':'); - if (parts.Length == 2) - { - cache_.NextSenderMsgSeqNum = Convert.ToUInt64(parts[0]); - cache_.NextTargetMsgSeqNum = Convert.ToUInt64(parts[1]); - } - } - } - } - - private void InitializeSessionCreateTime() - { - if (System.IO.File.Exists(sessionFileName_) && new System.IO.FileInfo(sessionFileName_).Length > 0) - { - using (System.IO.StreamReader reader = new System.IO.StreamReader(sessionFileName_)) - { - string s = reader.ReadToEnd(); - cache_.CreationTime = UtcDateTimeSerializer.FromString(s); - } - } - else - { - using (System.IO.StreamWriter writer = new System.IO.StreamWriter(sessionFileName_, false)) - { - writer.Write(UtcDateTimeSerializer.ToString(cache_.CreationTime.Value)); - } - } - } - - - #region MessageStore Members - - /// - /// Get messages within the range of sequence numbers - /// - /// - /// - /// - public void Get(SeqNumType startSeqNum, SeqNumType endSeqNum, List messages) - { - for (SeqNumType i = startSeqNum; i <= endSeqNum; i++) - { - if (offsets_.ContainsKey(i)) - { - msgFile_.Seek(offsets_[i].index, System.IO.SeekOrigin.Begin); - byte[] msgBytes = new byte[offsets_[i].size]; - msgFile_.Read(msgBytes, 0, msgBytes.Length); - - messages.Add(CharEncoding.DefaultEncoding.GetString(msgBytes)); - } - } - - } - - /// - /// Store a message - /// - /// - /// - /// - public bool Set(SeqNumType msgSeqNum, string msg) - { - msgFile_.Seek(0, System.IO.SeekOrigin.End); - - long offset = msgFile_.Position; - byte[] msgBytes = CharEncoding.DefaultEncoding.GetBytes(msg); - int size = msgBytes.Length; - - StringBuilder b = new StringBuilder(); - b.Append(msgSeqNum).Append(",").Append(offset).Append(",").Append(size); - headerFile_.WriteLine(b.ToString()); - headerFile_.Flush(); - - offsets_[msgSeqNum] = new MsgDef(offset, size); - - msgFile_.Write(msgBytes, 0, size); - msgFile_.Flush(); - - - return true; - } - - public SeqNumType NextSenderMsgSeqNum { - get { return cache_.NextSenderMsgSeqNum; } - set { - cache_.NextSenderMsgSeqNum = value; - setSeqNum(); - } - } - - public SeqNumType NextTargetMsgSeqNum { - get { return cache_.NextTargetMsgSeqNum; } - set { - cache_.NextTargetMsgSeqNum = value; - setSeqNum(); - } - } - - public void IncrNextSenderMsgSeqNum() - { - cache_.IncrNextSenderMsgSeqNum(); - setSeqNum(); - } - - public void IncrNextTargetMsgSeqNum() - { - cache_.IncrNextTargetMsgSeqNum(); - setSeqNum(); - } - - private void setSeqNum() - { - seqNumsFile_.Seek(0, System.IO.SeekOrigin.Begin); - System.IO.StreamWriter writer = new System.IO.StreamWriter(seqNumsFile_); - - writer.Write(NextSenderMsgSeqNum.ToString("D20") + " : " + NextTargetMsgSeqNum.ToString("D20") + " "); - writer.Flush(); - } - - public DateTime? CreationTime - { - get - { - return cache_.CreationTime; - } - } - - public void Reset() - { - cache_.Reset(); - PurgeFileCache(); - open(); - } - - public void Refresh() - { - cache_.Reset(); - open(); - } - - #endregion - - #region IDisposable Members - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - - } - private bool _disposed = false; - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - if (disposing) - { - close(); - } - _disposed = true; - } - - ~FileStore() => Dispose(false); - #endregion - } -} diff --git a/QuickFIXn/FileStoreFactory.cs b/QuickFIXn/FileStoreFactory.cs deleted file mode 100755 index b20f3c0eb..000000000 --- a/QuickFIXn/FileStoreFactory.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace QuickFix -{ - /// - /// Creates a message store that stores messages in a file - /// - public class FileStoreFactory : IMessageStoreFactory - { - private SessionSettings settings_; - - /// - /// Create the factory with configuration in session settings - /// - /// - public FileStoreFactory(SessionSettings settings) - { - settings_ = settings; - } - - /// - /// Creates a file-based message store - /// - /// session ID for the message store - /// - public IMessageStore Create(SessionID sessionID) - { - return new FileStore(settings_.Get(sessionID).GetString(SessionSettings.FILE_STORE_PATH), sessionID); - } - } -} diff --git a/QuickFIXn/ILog.cs b/QuickFIXn/ILog.cs deleted file mode 100755 index 5e2ca6956..000000000 --- a/QuickFIXn/ILog.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace QuickFix -{ - /// - /// Session log for messages and events - /// - public interface ILog : IDisposable - { - /// - /// Clears the log and removes any persistent log data - /// - void Clear(); - - /// - /// Logs an incoming message - /// - /// a raw FIX message - void OnIncoming(string msg); - - /// - /// Logs an outgoing message - /// - /// a raw FIX message - void OnOutgoing(string msg); - - /// - /// Logs a session event - /// - /// event description - void OnEvent(string s); - } -} diff --git a/QuickFIXn/ILogFactory.cs b/QuickFIXn/ILogFactory.cs deleted file mode 100755 index 581dd6671..000000000 --- a/QuickFIXn/ILogFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ - -namespace QuickFix -{ - /// - /// Used by a session to create a log implementation - /// - public interface ILogFactory - { - /// - /// Create a log implementation - /// - /// session ID usually used for configuration access - /// - ILog Create(SessionID sessionID); - } -} diff --git a/QuickFIXn/IMessageStore.cs b/QuickFIXn/IMessageStore.cs deleted file mode 100755 index 8ea8e7b84..000000000 --- a/QuickFIXn/IMessageStore.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System; - -namespace QuickFix -{ - - /// - /// Used by a Session to store and retrieve messages for resend purposes - /// - public interface IMessageStore : IDisposable - { - /// - /// Get messages within sequence number range (inclusive). Used for - /// message resend requests - /// - /// the starting message sequence number - /// the ending message sequence number - /// the retrieved messages (out parameter) - void Get(SeqNumType startSeqNum, SeqNumType endSeqNum, List messages); - - /// - /// Adds a raw fix message to the store with the give sequence number - /// - /// the sequence number - /// the raw FIX message string - /// true if successful, false otherwise - bool Set(SeqNumType msgSeqNum, string msg); - - SeqNumType NextSenderMsgSeqNum { get; set; } - SeqNumType NextTargetMsgSeqNum { get; set; } - - void IncrNextSenderMsgSeqNum(); - void IncrNextTargetMsgSeqNum(); - - - DateTime? CreationTime { get; } - - /// - /// Reset the message store. Sequence numbers are set back to 1 and stored - /// messages are erased. The session creation time is also set to the time of - /// the reset - /// - void Reset(); - - /// - /// Refreshes session state from a shared state storage (e.g. database, - /// file, ...). Refresh will not work for message stores without shared state - /// (e.g. MemoryStore). These stores should log a session error, at a minimum, - /// or throw an exception. - /// - void Refresh(); - } -} diff --git a/QuickFIXn/IMessageStoreFactory.cs b/QuickFIXn/IMessageStoreFactory.cs deleted file mode 100755 index b9c5600eb..000000000 --- a/QuickFIXn/IMessageStoreFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace QuickFix -{ - /// - /// Used by a Session to create a message store implementation - /// - public interface IMessageStoreFactory - { - /// - /// Creates a message store implementation - /// - /// the session ID, often used to access session configurations - /// the message store implementation - IMessageStore Create(SessionID sessionID); - } -} diff --git a/QuickFIXn/Logger/CompositeLog.cs b/QuickFIXn/Logger/CompositeLog.cs new file mode 100644 index 000000000..61722c144 --- /dev/null +++ b/QuickFIXn/Logger/CompositeLog.cs @@ -0,0 +1,72 @@ +#nullable enable +using System; + +namespace QuickFix.Logger; + +/// +/// File log implementation +/// +internal class CompositeLog : ILog +{ + private readonly ILog[] _logs; + + private bool _disposed = false; + + public CompositeLog(ILog[] logs) + { + _logs = logs; + } + + public void Clear() + { + DisposedCheck(); + foreach (var log in _logs) + log.Clear(); + } + + public void OnIncoming(string msg) + { + DisposedCheck(); + foreach (var log in _logs) + log.OnIncoming(msg); + } + + public void OnOutgoing(string msg) + { + DisposedCheck(); + foreach (var log in _logs) + log.OnOutgoing(msg); + } + + public void OnEvent(string s) + { + DisposedCheck(); + foreach (var log in _logs) + log.OnEvent(s); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + if (disposing) + { + foreach (var log in _logs) + log.Dispose(); + } + _disposed = true; + } + + private void DisposedCheck() + { + if (_disposed) + throw new ObjectDisposedException(GetType().Name); + } + + ~CompositeLog() => Dispose(false); +} diff --git a/QuickFIXn/Logger/CompositeLogFactory.cs b/QuickFIXn/Logger/CompositeLogFactory.cs new file mode 100644 index 000000000..f63c1d6fa --- /dev/null +++ b/QuickFIXn/Logger/CompositeLogFactory.cs @@ -0,0 +1,27 @@ +#nullable enable +using System.Linq; + +namespace QuickFix.Logger; + +/// +/// Allows multiple log factories to be used with QuickFIX/N. For example, you could log events to the console and also log all events and messages to a file. +/// +public class CompositeLogFactory : ILogFactory +{ + private readonly ILogFactory[] _factories; + + public CompositeLogFactory(ILogFactory[] factories) + { + _factories = factories; + } + + /// + /// Creates a composite log + /// + /// session ID for the message store + /// + public ILog Create(SessionID sessionID) + { + return new CompositeLog(_factories.Select(f => f.Create(sessionID)).ToArray()); + } +} diff --git a/QuickFIXn/Logger/FileLog.cs b/QuickFIXn/Logger/FileLog.cs new file mode 100755 index 000000000..d7addf67a --- /dev/null +++ b/QuickFIXn/Logger/FileLog.cs @@ -0,0 +1,144 @@ +#nullable enable +using System; +using QuickFix.Util; + +namespace QuickFix.Logger; + +/// +/// File log implementation +/// +public class FileLog : ILog +{ + private readonly object _sync = new(); + + private System.IO.StreamWriter _messageLog; + private System.IO.StreamWriter _eventLog; + + private readonly string _messageLogFileName; + private readonly string _eventLogFileName; + + /// + /// + /// + /// + /// All back or forward slashes in this path will be converted as needed to the running platform's preferred + /// path separator (i.e. "/" will become "\" on windows, else "\" will become "/" on all other platforms) + /// + /// + public FileLog(string fileLogPath, SessionID sessionId) + { + string prefix = Prefix(sessionId); + + string normalizedPath = StringUtil.FixSlashes(fileLogPath); + + if (!System.IO.Directory.Exists(normalizedPath)) + System.IO.Directory.CreateDirectory(normalizedPath); + + _messageLogFileName = System.IO.Path.Combine(normalizedPath, prefix + ".messages.current.log"); + _eventLogFileName = System.IO.Path.Combine(normalizedPath, prefix + ".event.current.log"); + + _messageLog = new System.IO.StreamWriter(_messageLogFileName, true); + _eventLog = new System.IO.StreamWriter(_eventLogFileName, true); + + _messageLog.AutoFlush = true; + _eventLog.AutoFlush = true; + } + + public static string Prefix(SessionID sessionId) + { + System.Text.StringBuilder prefix = new System.Text.StringBuilder(sessionId.BeginString) + .Append('-').Append(sessionId.SenderCompID); + if (SessionID.IsSet(sessionId.SenderSubID)) + prefix.Append('_').Append(sessionId.SenderSubID); + if (SessionID.IsSet(sessionId.SenderLocationID)) + prefix.Append('_').Append(sessionId.SenderLocationID); + prefix.Append('-').Append(sessionId.TargetCompID); + if (SessionID.IsSet(sessionId.TargetSubID)) + prefix.Append('_').Append(sessionId.TargetSubID); + if (SessionID.IsSet(sessionId.TargetLocationID)) + prefix.Append('_').Append(sessionId.TargetLocationID); + + if (SessionID.IsSet(sessionId.SessionQualifier)) + prefix.Append('-').Append(sessionId.SessionQualifier); + + return prefix.ToString(); + } + + private void DisposedCheck() + { + if (_disposed) + throw new ObjectDisposedException(GetType().Name); + } + + #region Log Members + + public void Clear() + { + DisposedCheck(); + + lock (_sync) + { + _messageLog.Close(); + _eventLog.Close(); + + _messageLog = new System.IO.StreamWriter(_messageLogFileName, false); + _eventLog = new System.IO.StreamWriter(_eventLogFileName, false); + + _messageLog.AutoFlush = true; + _eventLog.AutoFlush = true; + } + } + + public void OnIncoming(string msg) + { + DisposedCheck(); + + lock (_sync) + { + _messageLog.WriteLine(Fields.Converters.DateTimeConverter.Convert(DateTime.UtcNow) + " : " + msg); + } + } + + public void OnOutgoing(string msg) + { + DisposedCheck(); + + lock (_sync) + { + _messageLog.WriteLine(Fields.Converters.DateTimeConverter.Convert(DateTime.UtcNow) + " : " + msg); + } + } + + public void OnEvent(string s) + { + DisposedCheck(); + + lock (_sync) + { + _eventLog.WriteLine(Fields.Converters.DateTimeConverter.Convert(DateTime.UtcNow) + " : "+ s); + } + } + + #endregion + + #region IDisposable Members + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private bool _disposed = false; + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + if (disposing) + { + _messageLog.Dispose(); + _eventLog.Dispose(); + } + _disposed = true; + } + ~FileLog() => Dispose(false); + #endregion +} diff --git a/QuickFIXn/Logger/FileLogFactory.cs b/QuickFIXn/Logger/FileLogFactory.cs new file mode 100755 index 000000000..9b71e7ead --- /dev/null +++ b/QuickFIXn/Logger/FileLogFactory.cs @@ -0,0 +1,30 @@ +#nullable enable + +namespace QuickFix.Logger; + +/// +/// Creates a message store that stores messages in a file +/// +public class FileLogFactory : ILogFactory +{ + private readonly SessionSettings _settings; + + #region LogFactory Members + + public FileLogFactory(SessionSettings settings) + { + _settings = settings; + } + + /// + /// Creates a file-based message store + /// + /// session ID for the message store + /// + public ILog Create(SessionID sessionId) + { + return new FileLog(_settings.Get(sessionId).GetString(SessionSettings.FILE_LOG_PATH), sessionId); + } + + #endregion +} diff --git a/QuickFIXn/Logger/ILog.cs b/QuickFIXn/Logger/ILog.cs new file mode 100755 index 000000000..c77166dbc --- /dev/null +++ b/QuickFIXn/Logger/ILog.cs @@ -0,0 +1,32 @@ +using System; + +namespace QuickFix.Logger; + +/// +/// Session log for messages and events +/// +public interface ILog : IDisposable +{ + /// + /// Clears the log and removes any persistent log data + /// + void Clear(); + + /// + /// Logs an incoming message + /// + /// a raw FIX message + void OnIncoming(string msg); + + /// + /// Logs an outgoing message + /// + /// a raw FIX message + void OnOutgoing(string msg); + + /// + /// Logs a session event + /// + /// event description + void OnEvent(string s); +} diff --git a/QuickFIXn/Logger/ILogFactory.cs b/QuickFIXn/Logger/ILogFactory.cs new file mode 100755 index 000000000..c2ddb4376 --- /dev/null +++ b/QuickFIXn/Logger/ILogFactory.cs @@ -0,0 +1,16 @@ +#nullable enable + +namespace QuickFix.Logger; + +/// +/// Used by a session to create a log implementation +/// +public interface ILogFactory +{ + /// + /// Create a log implementation + /// + /// session ID usually used for configuration access + /// + ILog Create(SessionID sessionId); +} diff --git a/QuickFIXn/Logger/NullLog.cs b/QuickFIXn/Logger/NullLog.cs new file mode 100755 index 000000000..cccf6cdac --- /dev/null +++ b/QuickFIXn/Logger/NullLog.cs @@ -0,0 +1,27 @@ + +namespace QuickFix.Logger; + +/// +/// Log implementation that does not do anything +/// +public sealed class NullLog : ILog +{ + #region ILog Members + + public void Clear() + { } + + public void OnIncoming(string msg) + { } + + public void OnOutgoing(string msg) + { } + + public void OnEvent(string s) + { } + + public void Dispose() + { } + + #endregion +} diff --git a/QuickFIXn/Logger/NullLogFactory.cs b/QuickFIXn/Logger/NullLogFactory.cs new file mode 100644 index 000000000..90b65025e --- /dev/null +++ b/QuickFIXn/Logger/NullLogFactory.cs @@ -0,0 +1,13 @@ +#nullable enable + +namespace QuickFix.Logger; + +public class NullLogFactory : ILogFactory +{ + public NullLogFactory() { } + + public ILog Create(SessionID _x) + { + return new NullLog(); + } +} diff --git a/QuickFIXn/Logger/ScreenLog.cs b/QuickFIXn/Logger/ScreenLog.cs new file mode 100755 index 000000000..1dc8bd6f2 --- /dev/null +++ b/QuickFIXn/Logger/ScreenLog.cs @@ -0,0 +1,73 @@ +#nullable enable + +namespace QuickFix.Logger; + +/// +/// FIXME - needs to log sessionIDs, timestamps, etc. +/// +public class ScreenLog : ILog +{ + private readonly object _sync = new (); + private readonly bool _logIncoming; + private readonly bool _logOutgoing; + private readonly bool _logEvent; + + public ScreenLog(bool logIncoming, bool logOutgoing, bool logEvent) + { + _logIncoming = logIncoming; + _logOutgoing = logOutgoing; + _logEvent = logEvent; + } + + #region ILog Members + + public void Clear() + { } + + public void OnIncoming(string msg) + { + if (!_logIncoming) + return; + + lock (_sync) + { + System.Console.WriteLine(" " + msg); + } + } + + public void OnOutgoing(string msg) + { + if (!_logOutgoing) + return; + + lock (_sync) + { + System.Console.WriteLine(" " + msg); + } + } + + public void OnEvent(string s) + { + if (!_logEvent) + return; + + lock (_sync) + { + System.Console.WriteLine(" " + s); + } + } + #endregion + + #region IDisposable implementation + public void Dispose() + { + Dispose(true); + System.GC.SuppressFinalize(this); + } + protected virtual void Dispose(bool disposing) + { + // Nothing to dispose of... + } + ~ScreenLog() => Dispose(false); + #endregion +} diff --git a/QuickFIXn/Logger/ScreenLogFactory.cs b/QuickFIXn/Logger/ScreenLogFactory.cs new file mode 100755 index 000000000..15d13ca03 --- /dev/null +++ b/QuickFIXn/Logger/ScreenLogFactory.cs @@ -0,0 +1,40 @@ +#nullable enable + +namespace QuickFix.Logger; + +public class ScreenLogFactory : ILogFactory +{ + private const string SCREEN_LOG_SHOW_INCOMING = "ScreenLogShowIncoming"; + private const string SCREEN_LOG_SHOW_OUTGOING = "ScreenLogShowOutgoing"; + private const string SCREEN_LOG_SHOW_EVENTS = "ScreenLogShowEvents"; + + private readonly SessionSettings _settings; + + public ScreenLogFactory(SessionSettings settings) + { + _settings = settings; + } + + #region LogFactory Members + + public ILog Create(SessionID sessionId) { + bool logIncoming = false; + bool logOutgoing = false; + bool logEvent = false; + + if(_settings.Has(sessionId)) + { + Dictionary dict = _settings.Get(sessionId); + if (dict.Has(SCREEN_LOG_SHOW_INCOMING)) + logIncoming = dict.GetBool(SCREEN_LOG_SHOW_INCOMING); + if (dict.Has(SCREEN_LOG_SHOW_OUTGOING)) + logOutgoing = dict.GetBool(SCREEN_LOG_SHOW_OUTGOING); + if (dict.Has(SCREEN_LOG_SHOW_EVENTS)) + logEvent = dict.GetBool(SCREEN_LOG_SHOW_EVENTS); + } + + return new ScreenLog(logIncoming, logOutgoing, logEvent); + } + + #endregion +} diff --git a/QuickFIXn/MemoryStore.cs b/QuickFIXn/MemoryStore.cs deleted file mode 100755 index a32a25af3..000000000 --- a/QuickFIXn/MemoryStore.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace QuickFix -{ - /// - /// In-memory message store implementation - /// - public class MemoryStore : IMessageStore - { - #region Private Members - - System.Collections.Generic.Dictionary messages_; - DateTime? creationTime; - - #endregion - - public MemoryStore() - { - messages_ = new System.Collections.Generic.Dictionary(); - Reset(); - } - - public void Get(SeqNumType begSeqNo, SeqNumType endSeqNo, List messages) - { - for (SeqNumType current = begSeqNo; current <= endSeqNo; current++) - { - if (messages_.ContainsKey(current)) - messages.Add(messages_[current]); - } - } - - #region MessageStore Members - - public bool Set(SeqNumType msgSeqNum, string msg) - { - messages_[msgSeqNum] = msg; - return true; - } - - public SeqNumType NextSenderMsgSeqNum { get; set; } - public SeqNumType NextTargetMsgSeqNum { get; set; } - - public void IncrNextSenderMsgSeqNum() - { ++NextSenderMsgSeqNum; } - - public void IncrNextTargetMsgSeqNum() - { ++NextTargetMsgSeqNum; } - - public System.DateTime? CreationTime - { - get { return creationTime; } - internal set { creationTime = value; } - } - - public void Reset() - { - NextSenderMsgSeqNum = 1; - NextTargetMsgSeqNum = 1; - messages_.Clear(); - creationTime = DateTime.UtcNow; - } - - public void Refresh() - { } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - private bool _disposed = false; - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - if (disposing) - { - messages_ = null; - } - _disposed = true; - } - - ~MemoryStore() => Dispose(false); - #endregion - } -} diff --git a/QuickFIXn/MemoryStoreFactory.cs b/QuickFIXn/MemoryStoreFactory.cs deleted file mode 100755 index f6c5ac129..000000000 --- a/QuickFIXn/MemoryStoreFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace QuickFix -{ - /// - /// Creates a message store that stores all data in memory - /// - public class MemoryStoreFactory : IMessageStoreFactory - { - #region MessageStoreFactory Members - - public IMessageStore Create(SessionID sessionID) - { - return new MemoryStore(); - } - - #endregion - } -} diff --git a/QuickFIXn/NullLog.cs b/QuickFIXn/NullLog.cs deleted file mode 100755 index ab5ef47e6..000000000 --- a/QuickFIXn/NullLog.cs +++ /dev/null @@ -1,28 +0,0 @@ - -namespace QuickFix -{ - /// - /// Log implementation that does not do anything - /// - public sealed class NullLog : ILog - { - #region ILog Members - - public void Clear() - { } - - public void OnIncoming(string msg) - { } - - public void OnOutgoing(string msg) - { } - - public void OnEvent(string s) - { } - - public void Dispose() - { } - - #endregion - } -} diff --git a/QuickFIXn/NullLogFactory.cs b/QuickFIXn/NullLogFactory.cs deleted file mode 100644 index 17700fe11..000000000 --- a/QuickFIXn/NullLogFactory.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace QuickFix -{ - public class NullLogFactory : ILogFactory - { - public NullLogFactory() { } - - public ILog Create(SessionID _x) - { - return new NullLog(); - } - } -} diff --git a/QuickFIXn/ScreenLog.cs b/QuickFIXn/ScreenLog.cs deleted file mode 100755 index c6b6ed8c4..000000000 --- a/QuickFIXn/ScreenLog.cs +++ /dev/null @@ -1,73 +0,0 @@ - -namespace QuickFix -{ - /// - /// FIXME - needs to log sessionIDs, timestamps, etc. - /// - public class ScreenLog : ILog - { - private object sync_ = new object(); - private bool logIncoming_; - private bool logOutgoing_; - private bool logEvent_; - - public ScreenLog(SessionID sessionID, bool logIncoming, bool logOutgoing, bool logEvent) - { - logIncoming_ = logIncoming; - logOutgoing_ = logOutgoing; - logEvent_ = logEvent; - } - - #region ILog Members - - public void Clear() - { } - - public void OnIncoming(string msg) - { - if (!logIncoming_) - return; - - lock (sync_) - { - System.Console.WriteLine(" " + msg); - } - } - - public void OnOutgoing(string msg) - { - if (!logOutgoing_) - return; - - lock (sync_) - { - System.Console.WriteLine(" " + msg); - } - } - - public void OnEvent(string s) - { - if (!logEvent_) - return; - - lock (sync_) - { - System.Console.WriteLine(" " + s); - } - } - #endregion - - #region IDisposable implementation - public void Dispose() - { - Dispose(true); - System.GC.SuppressFinalize(this); - } - protected virtual void Dispose(bool disposing) - { - // Nothing to dispose of... - } - ~ScreenLog() => Dispose(false); - #endregion - } -} diff --git a/QuickFIXn/ScreenLogFactory.cs b/QuickFIXn/ScreenLogFactory.cs deleted file mode 100755 index 36501ab60..000000000 --- a/QuickFIXn/ScreenLogFactory.cs +++ /dev/null @@ -1,51 +0,0 @@ - -namespace QuickFix -{ - public class ScreenLogFactory : ILogFactory - { - public const string SCREEN_LOG_SHOW_INCOMING = "ScreenLogShowIncoming"; - public const string SCREEN_LOG_SHOW_OUTGOING = "ScreenLogShowOutgoing"; - public const string SCREEN_LOG_SHOW_EVENTS = "ScreenLogShowEvents"; - - private SessionSettings settings_ = null; - private bool logIncoming_ = true; - private bool logOutgoing_ = true; - private bool logEvent_ = true; - - public ScreenLogFactory(SessionSettings settings) - { - settings_ = settings; - } - - public ScreenLogFactory(bool logIncoming, bool logOutgoing, bool logEvent) - { - logIncoming_ = logIncoming; - logOutgoing_ = logOutgoing; - logEvent_ = logEvent; - } - - #region LogFactory Members - - public ILog Create(SessionID sessionID) - { - bool logIncoming = logIncoming_; - bool logOutgoing = logOutgoing_; - bool logEvent = logEvent_; - - if(settings_ != null && settings_.Has(sessionID)) - { - Dictionary dict = settings_.Get(sessionID); - if (dict.Has(SCREEN_LOG_SHOW_INCOMING)) - logIncoming = dict.GetBool(SCREEN_LOG_SHOW_INCOMING); - if (dict.Has(SCREEN_LOG_SHOW_OUTGOING)) - logOutgoing = dict.GetBool(SCREEN_LOG_SHOW_OUTGOING); - if (dict.Has(SCREEN_LOG_SHOW_EVENTS)) - logEvent = dict.GetBool(SCREEN_LOG_SHOW_EVENTS); - } - - return new ScreenLog(sessionID, logIncoming, logOutgoing, logEvent); - } - - #endregion - } -} diff --git a/QuickFIXn/Session.cs b/QuickFIXn/Session.cs index a4251cf85..8b3beb119 100755 --- a/QuickFIXn/Session.cs +++ b/QuickFIXn/Session.cs @@ -4,6 +4,8 @@ using System.Threading; using QuickFix.Fields; using QuickFix.Fields.Converters; +using QuickFix.Logger; +using QuickFix.Store; namespace QuickFix { diff --git a/QuickFIXn/SessionFactory.cs b/QuickFIXn/SessionFactory.cs index 7ceca116d..bd7055e8b 100755 --- a/QuickFIXn/SessionFactory.cs +++ b/QuickFIXn/SessionFactory.cs @@ -1,6 +1,8 @@ #nullable enable using System; using System.Collections.Generic; +using QuickFix.Logger; +using QuickFix.Store; using QuickFix.Util; namespace QuickFix diff --git a/QuickFIXn/SessionState.cs b/QuickFIXn/SessionState.cs index e6524410f..7742a41ff 100755 --- a/QuickFIXn/SessionState.cs +++ b/QuickFIXn/SessionState.cs @@ -1,6 +1,8 @@ #nullable enable using System; using System.Collections.Generic; +using QuickFix.Logger; +using QuickFix.Store; using MessagesBySeqNum = System.Collections.Generic.Dictionary; namespace QuickFix diff --git a/QuickFIXn/Store/FileStore.cs b/QuickFIXn/Store/FileStore.cs new file mode 100755 index 000000000..4a9651dc6 --- /dev/null +++ b/QuickFIXn/Store/FileStore.cs @@ -0,0 +1,316 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Text; +using QuickFix.Util; + +namespace QuickFix.Store; + +/// +/// File store implementation +/// +public class FileStore : IMessageStore +{ + private class MsgDef + { + public long Index { get; } + public int Size { get; } + + public MsgDef(long index, int size) + { + Index = index; + Size = size; + } + } + + private readonly string _seqNumsFileName; + private readonly string _msgFileName; + private readonly string _headerFileName; + private readonly string _sessionFileName; + + private System.IO.FileStream _seqNumsFile; + private System.IO.FileStream _msgFile; + private System.IO.StreamWriter _headerFile; + + private readonly MemoryStore _cache = new(); + + private readonly Dictionary _offsets = new(); + + public static string Prefix(SessionID sessionId) + { + StringBuilder prefix = new StringBuilder(sessionId.BeginString) + .Append('-').Append(sessionId.SenderCompID); + if (SessionID.IsSet(sessionId.SenderSubID)) + prefix.Append('_').Append(sessionId.SenderSubID); + if (SessionID.IsSet(sessionId.SenderLocationID)) + prefix.Append('_').Append(sessionId.SenderLocationID); + prefix.Append('-').Append(sessionId.TargetCompID); + if (SessionID.IsSet(sessionId.TargetSubID)) + prefix.Append('_').Append(sessionId.TargetSubID); + if (SessionID.IsSet(sessionId.TargetLocationID)) + prefix.Append('_').Append(sessionId.TargetLocationID); + + if (SessionID.IsSet(sessionId.SessionQualifier)) + prefix.Append('-').Append(sessionId.SessionQualifier); + + return prefix.ToString(); + } + + /// + /// + /// + /// + /// All back or forward slashes in this path will be converted as needed to the running platform's preferred + /// path separator (i.e. "/" will become "\" on windows, else "\" will become "/" on all other platforms) + /// + /// + public FileStore(string path, SessionID sessionId) + { + string normalizedPath = StringUtil.FixSlashes(path); + + if (!System.IO.Directory.Exists(normalizedPath)) + System.IO.Directory.CreateDirectory(normalizedPath); + + string prefix = Prefix(sessionId); + + _seqNumsFileName = System.IO.Path.Combine(normalizedPath, prefix + ".seqnums"); + _msgFileName = System.IO.Path.Combine(normalizedPath, prefix + ".body"); + _headerFileName = System.IO.Path.Combine(normalizedPath, prefix + ".header"); + _sessionFileName = System.IO.Path.Combine(normalizedPath, prefix + ".session"); + + // The compiler isn't smart enough to see that Open() initializes these 3 vars, + // but we can use "= null!" to make it accept that these are non-null + _seqNumsFile = null!; + _msgFile = null!; + _headerFile = null!; + Open(); + } + + private void Open() + { + Close(); + + ConstructFromFileCache(); + InitializeSessionCreateTime(); + + _seqNumsFile = new System.IO.FileStream(_seqNumsFileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); + _msgFile = new System.IO.FileStream(_msgFileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); + _headerFile = new System.IO.StreamWriter(_headerFileName, true); + } + + private void Close() + { + // these vars will be null only during construction (ctor()->Open()->Close()) + _seqNumsFile?.Dispose(); + _msgFile?.Dispose(); + _headerFile?.Dispose(); + } + + private static void PurgeSingleFile(System.IO.Stream stream, string filename) + { + stream.Close(); + if (System.IO.File.Exists(filename)) + System.IO.File.Delete(filename); + } + + private static void PurgeSingleFile(System.IO.StreamWriter stream, string filename) + { + stream.Close(); + if (System.IO.File.Exists(filename)) + System.IO.File.Delete(filename); + } + + private static void PurgeSingleFile(string filename) + { + if (System.IO.File.Exists(filename)) + System.IO.File.Delete(filename); + } + + private void PurgeFileCache() + { + PurgeSingleFile(_seqNumsFile, _seqNumsFileName); + PurgeSingleFile(_msgFile, _msgFileName); + PurgeSingleFile(_headerFile, _headerFileName); + PurgeSingleFile(_sessionFileName); + } + + + private void ConstructFromFileCache() + { + _offsets.Clear(); + if (System.IO.File.Exists(_headerFileName)) + { + using (System.IO.StreamReader reader = new System.IO.StreamReader(_headerFileName)) + { + while (reader.ReadLine() is { } line) + { + string[] headerParts = line.Split(','); + if (headerParts.Length == 3) + { + _offsets[Convert.ToUInt64(headerParts[0])] = new MsgDef( + Convert.ToInt64(headerParts[1]), Convert.ToInt32(headerParts[2])); + } + } + } + } + + if (System.IO.File.Exists(_seqNumsFileName)) + { + using (System.IO.StreamReader seqNumReader = new System.IO.StreamReader(_seqNumsFileName)) + { + string[] parts = seqNumReader.ReadToEnd().Split(':'); + if (parts.Length == 2) + { + _cache.NextSenderMsgSeqNum = Convert.ToUInt64(parts[0]); + _cache.NextTargetMsgSeqNum = Convert.ToUInt64(parts[1]); + } + } + } + } + + private void InitializeSessionCreateTime() + { + if (System.IO.File.Exists(_sessionFileName) && new System.IO.FileInfo(_sessionFileName).Length > 0) + { + using (System.IO.StreamReader reader = new System.IO.StreamReader(_sessionFileName)) + { + string s = reader.ReadToEnd(); + _cache.CreationTime = UtcDateTimeSerializer.FromString(s); + } + } + else + { + using (System.IO.StreamWriter writer = new System.IO.StreamWriter(_sessionFileName, false)) { + writer.Write(UtcDateTimeSerializer.ToString(_cache.CreationTime ?? new DateTime())); + } + } + } + + + #region MessageStore Members + + /// + /// Get messages within the range of sequence numbers + /// + /// + /// + /// + public void Get(SeqNumType startSeqNum, SeqNumType endSeqNum, List messages) + { + for (SeqNumType i = startSeqNum; i <= endSeqNum; i++) + { + if (_offsets.ContainsKey(i)) + { + _msgFile.Seek(_offsets[i].Index, System.IO.SeekOrigin.Begin); + byte[] msgBytes = new byte[_offsets[i].Size]; + _msgFile.Read(msgBytes, 0, msgBytes.Length); + + messages.Add(CharEncoding.DefaultEncoding.GetString(msgBytes)); + } + } + + } + + /// + /// Store a message + /// + /// + /// + /// + public bool Set(SeqNumType msgSeqNum, string msg) + { + _msgFile.Seek(0, System.IO.SeekOrigin.End); + + long offset = _msgFile.Position; + byte[] msgBytes = CharEncoding.DefaultEncoding.GetBytes(msg); + int size = msgBytes.Length; + + StringBuilder b = new StringBuilder(); + b.Append(msgSeqNum).Append(',').Append(offset).Append(',').Append(size); + _headerFile.WriteLine(b.ToString()); + _headerFile.Flush(); + + _offsets[msgSeqNum] = new MsgDef(offset, size); + + _msgFile.Write(msgBytes, 0, size); + _msgFile.Flush(); + + + return true; + } + + public SeqNumType NextSenderMsgSeqNum { + get => _cache.NextSenderMsgSeqNum; + set { + _cache.NextSenderMsgSeqNum = value; + SetSeqNum(); + } + } + + public SeqNumType NextTargetMsgSeqNum { + get => _cache.NextTargetMsgSeqNum; + set { + _cache.NextTargetMsgSeqNum = value; + SetSeqNum(); + } + } + + public void IncrNextSenderMsgSeqNum() + { + _cache.IncrNextSenderMsgSeqNum(); + SetSeqNum(); + } + + public void IncrNextTargetMsgSeqNum() + { + _cache.IncrNextTargetMsgSeqNum(); + SetSeqNum(); + } + + private void SetSeqNum() + { + _seqNumsFile.Seek(0, System.IO.SeekOrigin.Begin); + System.IO.StreamWriter writer = new System.IO.StreamWriter(_seqNumsFile); + + writer.Write(NextSenderMsgSeqNum.ToString("D20") + " : " + NextTargetMsgSeqNum.ToString("D20") + " "); + writer.Flush(); + } + + public DateTime? CreationTime => _cache.CreationTime; + + public void Reset() + { + _cache.Reset(); + PurgeFileCache(); + Open(); + } + + public void Refresh() + { + _cache.Reset(); + Open(); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + private bool _disposed = false; + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + if (disposing) + { + Close(); + } + _disposed = true; + } + + ~FileStore() => Dispose(false); + #endregion +} diff --git a/QuickFIXn/Store/FileStoreFactory.cs b/QuickFIXn/Store/FileStoreFactory.cs new file mode 100755 index 000000000..c3ecc945d --- /dev/null +++ b/QuickFIXn/Store/FileStoreFactory.cs @@ -0,0 +1,30 @@ +#nullable enable + +namespace QuickFix.Store; + +/// +/// Creates a message store that stores messages in a file +/// +public class FileStoreFactory : IMessageStoreFactory +{ + private readonly SessionSettings _settings; + + /// + /// Create the factory with configuration in session settings + /// + /// + public FileStoreFactory(SessionSettings settings) + { + _settings = settings; + } + + /// + /// Creates a file-based message store + /// + /// session ID for the message store + /// + public IMessageStore Create(SessionID sessionId) + { + return new FileStore(_settings.Get(sessionId).GetString(SessionSettings.FILE_STORE_PATH), sessionId); + } +} diff --git a/QuickFIXn/Store/IMessageStore.cs b/QuickFIXn/Store/IMessageStore.cs new file mode 100755 index 000000000..0a77f3539 --- /dev/null +++ b/QuickFIXn/Store/IMessageStore.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace QuickFix.Store; + +/// +/// Used by a Session to store and retrieve messages for resend purposes +/// +public interface IMessageStore : IDisposable +{ + /// + /// Get messages within sequence number range (inclusive). Used for + /// message resend requests + /// + /// the starting message sequence number + /// the ending message sequence number + /// the retrieved messages (out parameter) + void Get(SeqNumType startSeqNum, SeqNumType endSeqNum, List messages); + + /// + /// Adds a raw fix message to the store with the give sequence number + /// + /// the sequence number + /// the raw FIX message string + /// true if successful, false otherwise + bool Set(SeqNumType msgSeqNum, string msg); + + SeqNumType NextSenderMsgSeqNum { get; set; } + SeqNumType NextTargetMsgSeqNum { get; set; } + + void IncrNextSenderMsgSeqNum(); + void IncrNextTargetMsgSeqNum(); + + + DateTime? CreationTime { get; } + + /// + /// Reset the message store. Sequence numbers are set back to 1 and stored + /// messages are erased. The session creation time is also set to the time of + /// the reset + /// + void Reset(); + + /// + /// Refreshes session state from a shared state storage (e.g. database, + /// file, ...). Refresh will not work for message stores without shared state + /// (e.g. MemoryStore). These stores should log a session error, at a minimum, + /// or throw an exception. + /// + void Refresh(); +} diff --git a/QuickFIXn/Store/IMessageStoreFactory.cs b/QuickFIXn/Store/IMessageStoreFactory.cs new file mode 100755 index 000000000..2fab87937 --- /dev/null +++ b/QuickFIXn/Store/IMessageStoreFactory.cs @@ -0,0 +1,14 @@ +namespace QuickFix.Store; + +/// +/// Used by a Session to create a message store implementation +/// +public interface IMessageStoreFactory +{ + /// + /// Creates a message store implementation + /// + /// the session ID, often used to access session configurations + /// the message store implementation + IMessageStore Create(SessionID sessionId); +} diff --git a/QuickFIXn/Store/MemoryStore.cs b/QuickFIXn/Store/MemoryStore.cs new file mode 100755 index 000000000..573f82db7 --- /dev/null +++ b/QuickFIXn/Store/MemoryStore.cs @@ -0,0 +1,77 @@ +#nullable enable +using System; +using System.Collections.Generic; + +namespace QuickFix.Store; + +/// +/// In-memory message store implementation +/// +public class MemoryStore : IMessageStore +{ + private readonly Dictionary _messages; + + public MemoryStore() + { + _messages = new Dictionary(); + Reset(); + } + + public void Get(SeqNumType begSeqNo, SeqNumType endSeqNo, List messages) + { + for (SeqNumType current = begSeqNo; current <= endSeqNo; current++) + { + if (_messages.TryGetValue(current, out var message)) + messages.Add(message); + } + } + + #region MessageStore Members + + public bool Set(SeqNumType msgSeqNum, string msg) + { + _messages[msgSeqNum] = msg; + return true; + } + + public SeqNumType NextSenderMsgSeqNum { get; set; } + public SeqNumType NextTargetMsgSeqNum { get; set; } + + public void IncrNextSenderMsgSeqNum() + { ++NextSenderMsgSeqNum; } + + public void IncrNextTargetMsgSeqNum() + { ++NextTargetMsgSeqNum; } + + public DateTime? CreationTime { get; internal set; } + + public void Reset() + { + NextSenderMsgSeqNum = 1; + NextTargetMsgSeqNum = 1; + _messages.Clear(); + CreationTime = DateTime.UtcNow; + } + + public void Refresh() + { } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + private bool _disposed = false; + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + if (disposing) + { + _messages.Clear(); + } + _disposed = true; + } + + ~MemoryStore() => Dispose(false); + #endregion +} diff --git a/QuickFIXn/Store/MemoryStoreFactory.cs b/QuickFIXn/Store/MemoryStoreFactory.cs new file mode 100755 index 000000000..9f338c070 --- /dev/null +++ b/QuickFIXn/Store/MemoryStoreFactory.cs @@ -0,0 +1,16 @@ +namespace QuickFix.Store; + +/// +/// Creates a message store that stores all data in memory +/// +public class MemoryStoreFactory : IMessageStoreFactory +{ + #region MessageStoreFactory Members + + public IMessageStore Create(SessionID sessionId) + { + return new MemoryStore(); + } + + #endregion +} diff --git a/QuickFIXn/ThreadedSocketAcceptor.cs b/QuickFIXn/ThreadedSocketAcceptor.cs index ce9993aa3..735dcb432 100755 --- a/QuickFIXn/ThreadedSocketAcceptor.cs +++ b/QuickFIXn/ThreadedSocketAcceptor.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Net; using System; +using QuickFix.Logger; +using QuickFix.Store; namespace QuickFix { diff --git a/QuickFIXn/Transport/SocketInitiator.cs b/QuickFIXn/Transport/SocketInitiator.cs index af1b5dc51..a150dc69a 100755 --- a/QuickFIXn/Transport/SocketInitiator.cs +++ b/QuickFIXn/Transport/SocketInitiator.cs @@ -6,6 +6,8 @@ using System.Net; using System.Threading; using System.IO; +using QuickFix.Logger; +using QuickFix.Store; namespace QuickFix.Transport { diff --git a/QuickFIXn/Transport/StreamFactory.cs b/QuickFIXn/Transport/StreamFactory.cs index 8b637fea9..d25f6edad 100644 --- a/QuickFIXn/Transport/StreamFactory.cs +++ b/QuickFIXn/Transport/StreamFactory.cs @@ -9,6 +9,7 @@ using System.Net.Security; using System.Diagnostics; using System.Net; +using QuickFix.Logger; namespace QuickFix.Transport { diff --git a/QuickFIXn/Util/StringUtil.cs b/QuickFIXn/Util/StringUtil.cs index 89b40b743..7df33d047 100644 --- a/QuickFIXn/Util/StringUtil.cs +++ b/QuickFIXn/Util/StringUtil.cs @@ -1,11 +1,16 @@ -using System; +#nullable enable using System.Runtime.InteropServices; -using QuickFix.Fields; namespace QuickFix.Util { public static class StringUtil { + /// + /// Convert forward-slashes to backslashes (windows) or backslashes to forward-slashes (not windows) + /// and return the result + /// + /// + /// public static string FixSlashes(string s) { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? s.Replace('/', '\\') diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6cbc6dac4..f5bc6a31b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -44,7 +44,12 @@ What's New * #827 - cleanup/nullable-ize StreamFactory, SessionID, Settings, SessionSettings, SessionSchedule (gbirchmeier) * StreamFactory: privatized a lot of members; I don't think users are inheriting from this * SessionSchedule: remove unused LastEndTime() - +* #831 - cleanup/nullable-ize Logging/Store classes, fix path-separator bug (gbirchmeier) + * Move all logger classes to new QuickFix.Logger namespace + * Move all store classes to new QuickFix.Store namespace + * FileLog: remove the single-param ctor, no reason for anyone to use it + * ScreenLog ctor: removed unused sessionId param + * ScreenLogFactory: remove public vars and a ctor that no one should be using **Non-breaking changes** * #400 - added DDTool, a C#-based codegen, and deleted Ruby-based generator (gbirchmeier) diff --git a/UnitTests/FileLogTests.cs b/UnitTests/FileLogTests.cs deleted file mode 100644 index 7fd950341..000000000 --- a/UnitTests/FileLogTests.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using NUnit.Framework; - -namespace UnitTests -{ - [TestFixture] - public class FileLogTests - { - QuickFix.FileLog log; - - [SetUp] - public void setup() - { } - - [TearDown] - public void teardown() - { - if (log != null) - { - log.Dispose(); - log = null; - } - } - - [Test] - public void testPrefix() - { - QuickFix.SessionID someSessionID = new QuickFix.SessionID("FIX.4.4", "sender", "target"); - QuickFix.SessionID someSessionIDWithQualifier = new QuickFix.SessionID("FIX.4.3", "sender", "target", "foo"); - - Assert.AreEqual("FIX.4.4-sender-target", QuickFix.FileLog.Prefix(someSessionID)); - Assert.AreEqual("FIX.4.3-sender-target-foo", QuickFix.FileLog.Prefix(someSessionIDWithQualifier)); - } - - [Test] - public void testPrefixForSubsAndLocation() - { - QuickFix.SessionID sessionIDWithSubsAndLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "SENDERLOC", "TARGETCOMP", "TARGETSUB", "TARGETLOC"); - Assert.That(QuickFix.FileLog.Prefix(sessionIDWithSubsAndLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB_SENDERLOC-TARGETCOMP_TARGETSUB_TARGETLOC")); - - QuickFix.SessionID sessionIDWithSubsNoLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "TARGETCOMP", "TARGETSUB"); - Assert.That(QuickFix.FileLog.Prefix(sessionIDWithSubsNoLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB-TARGETCOMP_TARGETSUB")); - } - - [Test] - public void testGeneratedFileName() - { - var logDirectory = Path.Combine(TestContext.CurrentContext.TestDirectory, "log"); - - if (System.IO.Directory.Exists(logDirectory)) - System.IO.Directory.Delete(logDirectory, true); - - QuickFix.SessionID sessionID = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); - QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); - - QuickFix.Dictionary config = new QuickFix.Dictionary(); - config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); - config.SetString(QuickFix.SessionSettings.FILE_LOG_PATH, logDirectory); - - settings.Set(sessionID, config); - - QuickFix.FileLogFactory factory = new QuickFix.FileLogFactory(settings); - log = (QuickFix.FileLog)factory.Create(sessionID); - - log.OnEvent("some event"); - log.OnIncoming("some incoming"); - log.OnOutgoing("some outgoing"); - - Assert.That(System.IO.File.Exists(Path.Combine(logDirectory, "FIX.4.2-SENDERCOMP-TARGETCOMP.event.current.log"))); - Assert.That(System.IO.File.Exists(Path.Combine(logDirectory, "FIX.4.2-SENDERCOMP-TARGETCOMP.messages.current.log"))); - } - - [Test] - public void testThrowsIfNoConfig() - { - QuickFix.SessionID sessionID = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); - QuickFix.Dictionary config = new QuickFix.Dictionary(); - config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); - QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); - settings.Set(sessionID, config); - - QuickFix.FileLogFactory factory = new QuickFix.FileLogFactory(settings); - - Assert.Throws(delegate { factory.Create(sessionID); }); - } - } -} diff --git a/UnitTests/FileStoreTests.cs b/UnitTests/FileStoreTests.cs index e6a8ea92a..165945e2d 100755 --- a/UnitTests/FileStoreTests.cs +++ b/UnitTests/FileStoreTests.cs @@ -3,14 +3,15 @@ using System.IO; using NUnit.Framework; using System.Threading; +using QuickFix.Store; namespace UnitTests { [TestFixture] public class FileStoreTests { - private QuickFix.FileStore _store; - private QuickFix.FileStoreFactory _factory; + private FileStore _store; + private FileStoreFactory _factory; private QuickFix.SessionSettings _settings; private QuickFix.SessionID _sessionID; @@ -33,9 +34,9 @@ public void Setup() _settings = new QuickFix.SessionSettings(); _settings.Set(_sessionID, config); - _factory = new QuickFix.FileStoreFactory(_settings); + _factory = new FileStoreFactory(_settings); - _store = (QuickFix.FileStore)_factory.Create(_sessionID); + _store = (FileStore)_factory.Create(_sessionID); } void RebuildStore() @@ -45,7 +46,7 @@ void RebuildStore() _store.Dispose(); } - _store = (QuickFix.FileStore)_factory.Create(_sessionID); + _store = (FileStore)_factory.Create(_sessionID); } @@ -60,10 +61,10 @@ public void Teardown() public void TestPrefixForSessionWithSubsAndLoc() { QuickFix.SessionID sessionIDWithSubsAndLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "SENDERLOC", "TARGETCOMP", "TARGETSUB", "TARGETLOC"); - Assert.That(QuickFix.FileStore.Prefix(sessionIDWithSubsAndLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB_SENDERLOC-TARGETCOMP_TARGETSUB_TARGETLOC")); + Assert.That(FileStore.Prefix(sessionIDWithSubsAndLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB_SENDERLOC-TARGETCOMP_TARGETSUB_TARGETLOC")); QuickFix.SessionID sessionIDWithSubsNoLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "TARGETCOMP", "TARGETSUB"); - Assert.That(QuickFix.FileStore.Prefix(sessionIDWithSubsNoLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB-TARGETCOMP_TARGETSUB")); + Assert.That(FileStore.Prefix(sessionIDWithSubsNoLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB-TARGETCOMP_TARGETSUB")); } [Test] diff --git a/UnitTests/Logger/FileLogTests.cs b/UnitTests/Logger/FileLogTests.cs new file mode 100644 index 000000000..20c5a2e98 --- /dev/null +++ b/UnitTests/Logger/FileLogTests.cs @@ -0,0 +1,86 @@ +#nullable enable + +using System.IO; +using NUnit.Framework; +using QuickFix.Logger; + +namespace UnitTests.Logger; + +[TestFixture] +public class FileLogTests +{ + private FileLog? _log; + + [SetUp] + public void Setup() + { } + + [TearDown] + public void Teardown() + { + _log?.Dispose(); + _log = null; + } + + [Test] + public void TestPrefix() + { + QuickFix.SessionID someSessionId = new QuickFix.SessionID("FIX.4.4", "sender", "target"); + QuickFix.SessionID someSessionIdWithQualifier = new QuickFix.SessionID("FIX.4.3", "sender", "target", "foo"); + + Assert.AreEqual("FIX.4.4-sender-target", FileLog.Prefix(someSessionId)); + Assert.AreEqual("FIX.4.3-sender-target-foo", FileLog.Prefix(someSessionIdWithQualifier)); + } + + [Test] + public void TestPrefixForSubsAndLocation() + { + QuickFix.SessionID sessionIdWithSubsAndLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "SENDERLOC", "TARGETCOMP", "TARGETSUB", "TARGETLOC"); + Assert.That(FileLog.Prefix(sessionIdWithSubsAndLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB_SENDERLOC-TARGETCOMP_TARGETSUB_TARGETLOC")); + + QuickFix.SessionID sessionIdWithSubsNoLocation = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "SENDERSUB", "TARGETCOMP", "TARGETSUB"); + Assert.That(FileLog.Prefix(sessionIdWithSubsNoLocation), Is.EqualTo("FIX.4.2-SENDERCOMP_SENDERSUB-TARGETCOMP_TARGETSUB")); + } + + [Test] + public void TestGeneratedFileName() + { + var logDirectory = Path.Combine(TestContext.CurrentContext.TestDirectory, "log"); + + if (Directory.Exists(logDirectory)) + Directory.Delete(logDirectory, true); + + QuickFix.SessionID sessionId = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); + QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); + + QuickFix.Dictionary config = new QuickFix.Dictionary(); + config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); + config.SetString(QuickFix.SessionSettings.FILE_LOG_PATH, logDirectory); + + settings.Set(sessionId, config); + + FileLogFactory factory = new FileLogFactory(settings); + _log = (FileLog)factory.Create(sessionId); + + _log.OnEvent("some event"); + _log.OnIncoming("some incoming"); + _log.OnOutgoing("some outgoing"); + + Assert.That(File.Exists(Path.Combine(logDirectory, "FIX.4.2-SENDERCOMP-TARGETCOMP.event.current.log"))); + Assert.That(File.Exists(Path.Combine(logDirectory, "FIX.4.2-SENDERCOMP-TARGETCOMP.messages.current.log"))); + } + + [Test] + public void TestThrowsIfNoConfig() + { + QuickFix.SessionID sessionId = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); + QuickFix.Dictionary config = new QuickFix.Dictionary(); + config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); + QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); + settings.Set(sessionId, config); + + FileLogFactory factory = new FileLogFactory(settings); + + Assert.Throws(delegate { factory.Create(sessionId); }); + } +} diff --git a/UnitTests/MemoryStoreTest.cs b/UnitTests/MemoryStoreTest.cs index 81042c5b3..9d153e2bd 100644 --- a/UnitTests/MemoryStoreTest.cs +++ b/UnitTests/MemoryStoreTest.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using QuickFix; using QuickFix.Fields; +using QuickFix.Store; namespace UnitTests { diff --git a/UnitTests/SessionDynamicTest.cs b/UnitTests/SessionDynamicTest.cs index 94112da31..a29dc3e51 100644 --- a/UnitTests/SessionDynamicTest.cs +++ b/UnitTests/SessionDynamicTest.cs @@ -8,6 +8,8 @@ using NUnit.Framework; using QuickFix; +using QuickFix.Logger; +using QuickFix.Store; using QuickFix.Transport; namespace UnitTests diff --git a/UnitTests/SessionFactoryTest.cs b/UnitTests/SessionFactoryTest.cs index 46515c975..cab6bcd62 100755 --- a/UnitTests/SessionFactoryTest.cs +++ b/UnitTests/SessionFactoryTest.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using NUnit.Framework; using QuickFix; +using QuickFix.Store; namespace UnitTests { diff --git a/UnitTests/SessionStateTest.cs b/UnitTests/SessionStateTest.cs index 28722cff2..614458a51 100755 --- a/UnitTests/SessionStateTest.cs +++ b/UnitTests/SessionStateTest.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.IO; using System.Threading; +using QuickFix.Logger; +using QuickFix.Store; namespace UnitTests { diff --git a/UnitTests/SessionTest.cs b/UnitTests/SessionTest.cs index ccfa316f4..808796eb7 100755 --- a/UnitTests/SessionTest.cs +++ b/UnitTests/SessionTest.cs @@ -4,6 +4,8 @@ using System.Text.RegularExpressions; using NUnit.Framework; using System.Threading; +using QuickFix.Logger; +using QuickFix.Store; namespace UnitTests { @@ -194,16 +196,16 @@ public void Setup() config.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); settings.Set(sessionID, config); - var logFactory = new QuickFix.NullLogFactory(); // use QuickFix.ScreenLogFactory(settings) if you need to see output + var logFactory = new NullLogFactory(); // use QuickFix.ScreenLogFactory(settings) if you need to see output // acceptor - session = new QuickFix.Session(false, application, new QuickFix.MemoryStoreFactory(), sessionID, + session = new QuickFix.Session(false, application, new MemoryStoreFactory(), sessionID, new QuickFix.DataDictionaryProvider(),new QuickFix.SessionSchedule(config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); session.SetResponder(responder); session.CheckLatency = false; // initiator - session2 = new QuickFix.Session(true, application, new QuickFix.MemoryStoreFactory(), new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"), + session2 = new QuickFix.Session(true, application, new MemoryStoreFactory(), new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"), new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); session2.SetResponder(responder); session2.CheckLatency = false; @@ -919,8 +921,8 @@ public void TestToAppResendDoNotSend() public void TestApplicationExtension() { var mockApp = new MockApplicationExt(); - session = new QuickFix.Session(true, mockApp, new QuickFix.MemoryStoreFactory(), sessionID, - new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(config), 0, new QuickFix.NullLogFactory(), new QuickFix.DefaultMessageFactory(), "blah"); + session = new QuickFix.Session(true, mockApp, new MemoryStoreFactory(), sessionID, + new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(config), 0, new NullLogFactory(), new QuickFix.DefaultMessageFactory(), "blah"); session.SetResponder(responder); session.CheckLatency = false; diff --git a/UnitTests/ThreadedSocketAcceptorTests.cs b/UnitTests/ThreadedSocketAcceptorTests.cs index 229a65108..1f334b31c 100644 --- a/UnitTests/ThreadedSocketAcceptorTests.cs +++ b/UnitTests/ThreadedSocketAcceptorTests.cs @@ -5,6 +5,8 @@ using System.Text; using NUnit.Framework; using QuickFix; +using QuickFix.Logger; +using QuickFix.Store; namespace UnitTests {