Пример #1
0
        /// <summary>
        /// This implementation of the ReleaseSession method is
        /// invoked to simultaneously release any locks that are
        /// currently being held on a session and update the info
        /// for the session in the database.
        /// </summary>
        /// <param name="sessionId">
        /// The session id of the session being released.
        /// </param>
        /// <param name="record">
        /// The updated record for the session being released.
        /// </param>
        public void ReleaseSession(string sessionId, VfxFixDatabaseRecord record)
        {
            string sessionPath = Path.Combine(_rootPath, sessionId);
            string sessionFile = Path.Combine(sessionPath, "Session.xml");

            // REC: Write the updated session details out to
            // the session record file:
            XmlFixDatabaseRecord xmlRecord = new XmlFixDatabaseRecord();

            xmlRecord.TxSequence = record.TxSequence;
            xmlRecord.RxSequence = record.RxSequence;

            FileStream    fsSession = new FileStream(sessionFile, FileMode.Create, FileAccess.Write, FileShare.None);
            XmlSerializer xsSession = new XmlSerializer(typeof(XmlFixDatabaseRecord));

            xsSession.Serialize(fsSession, xmlRecord);
            fsSession.Close();

            // REC: Close the index and message database files since
            // they are no longer needed:
            SessionDetails sessionDetails = _mapSessions[sessionId];

            sessionDetails.IdxWriter.Close();
            sessionDetails.MsgWriter.Close();

            // REC: Delete the session's lock file:
            string lockPath = Path.Combine(_rootPath, sessionId);
            string lockFile = Path.Combine(lockPath, "Locked.txt");

            if (File.Exists(lockFile))
            {
                File.Delete(lockFile);
            }

            // REC: Remove the session details from the map:
            _mapSessions.Remove(sessionId);
        }
Пример #2
0
        /// <summary>
        /// The HandleSession_Logon method is invoked to handle
        /// a logon message that has been received from the peer
        /// session that this session is communicating with.
        /// </summary>
        /// <param name="msg">
        /// The FIX logon message received from the peer.
        /// </param>
        private void HandleSession_Logon(FixMessage msg)
        {
            // REC: Ensure that we're in the appropriate state
            // to handle a logon message:
            if (_currentState == SessionStates.Session_Pending || _currentState == SessionStates.Session_Closed)
            {
                // REC: Retrieve the FIX SenderCompID of the peer
                // from the logon message:
                FixField fldSenderCompID = msg.Header.GetField(49);
                if (fldSenderCompID != null)
                {
                    // REC: The SenderCompID from the peer becomes the
                    // session's TargetCompID for outgoing messages:
                    _fixTargetCompID = fldSenderCompID.Content;

                    // REC: Now that the FIX SenderCompID of the peer
                    // session is known, it is used to construct the
                    // identifier for the session - used to retrieve
                    // the session's details from the database:
                    _sessionId = string.Format("{0}-{1}", _fixSenderCompID, _fixTargetCompID);

                    // REC: Attempt to retrieve the session details
                    // from the session database:
                    if (_fixDatabase != null)
                    {

                        // REC: Note that once a session record is acquired
                        // from the database, it must be released when it is
                        // no longer needed by the session instance...
                        _sessionRecord = _fixDatabase.AcquireSession(_sessionId);
                        if (this._resetSequence == true)
                        {
                            _sessionRecord.RxSequence = 1;
                            _sessionRecord.TxSequence = 1;
                        }

                    }

                    // REC: Register the peer session's SenderCompID as
                    // the TargetCompID for outgoing messages:
                    _fixAssembler.SetField(new FixField(56, _fixTargetCompID));

                    // REC: Assemble the response message:
                    FixMessage response = _fixAssembler.CreateMessage(_sxVersion, _axVersion, "A");

                    // REC: Handle the sequence number reset flag
                    // if it is present in the logon message:
                    FixField fieldReset = msg.GetField(141);
                    if (fieldReset != null)
                    {
                        response.AddField(new FixField(141, "Y"));
                    }

                    // REC: Transition to the opened state:
                    _currentState = SessionStates.Session_Opened;

                    // REC: Notify the session's owner that the peer
                    // session has sent the logon request:
                    _handler.OnSessionLogon(this, msg);

                    // REC: Dispatch the administrative message out
                    // to the session's owner:
                    Dispatch_AdmMessage(response);
                }
                else
                {
                    // REC: Throw an exception since the session has not
                    // yet been established and there will be no handler
                    // at the application level that can deal with this:
                    throw new ArgumentException("Logon message missing required field - SenderCompID.");
                }
            }
            else
            {
                // REC: Notify the session handler that an
                // administrative message has been received
                // from the peer session:
                _handler.OnSessionRxAdmMessage(this, msg);

                // REC: Throw an exception that indicates the
                // session is not in the appropriate state to
                // handle the received message:

                //throw new InvalidOperationException("Session state invalid for received message.");
            }
        }
Пример #3
0
        /// <summary>
        /// The HandleConnect_Entrypoint method is the asynchronous
        /// entrypoint for the session's connect handling logic.
        /// </summary>
        /// <param name="state">
        /// Ignored parameter; required for the method to meet the
        /// required signature for use with the sequencer.
        /// </param>
        private void HandleConnect_Entrypoint(object state)
        {
            // REC: Transition the session to the active state so
            // that it can begin handling messages:
            _currentState = SessionStates.Session_Pending;

            // REC: Reset the receive timestamp:
            this._lastRxTicks = DateTime.Now.Ticks;

            // REC: Reset the transmit timestamp:
            this._lastTxTicks = DateTime.Now.Ticks;

            // REC: Acquire the session's persisted session
            // state from the database:
            if (_fixDatabase != null)
            {
                _sessionRecord = _fixDatabase.AcquireSession(_sessionId);
            }

            // REC: The session's timer is started in order
            // to drive the heartbeat and timeout logic:
            this._fixTimer.Start();

            _handler.OnSessionOpened(this);

            // REC: The client session needs to dispatch a logon
            // message to the peer as soon as it connects:
            FixMessage msgLogon = _fixAssembler.CreateMessage(_sxVersion, _axVersion, "A");
            if (msgLogon != null)
            {
                Dispatch_AdmMessage(msgLogon);
            }
        }
Пример #4
0
        /// <summary>
        /// The AcquireSession method is invoked to request exclusive
        /// access to a session's information in the database.
        /// </summary>
        /// <param name="sessionId">
        /// The session's unique identifier.
        /// </param>
        /// <returns>
        /// The persisted information that is maintained for
        /// the specified session identifier.
        /// </returns>
        public VfxFixDatabaseRecord AcquireSession(string sessionId)
        {
            VfxFixDatabaseRecord result = new VfxFixDatabaseRecord();

            // REC: Determine if the session's file path exists:
            string sessionPath = Path.Combine(_rootPath, sessionId);

            if (!Directory.Exists(sessionPath))
            {
                Directory.CreateDirectory(sessionPath);
            }

            // REC: Attempt to open and load the database entry
            // for the specified session:
            string sessionFile = Path.Combine(sessionPath, "Session.xml");

            if (!File.Exists(sessionFile))
            {
                ResetSession(sessionId);
            }

            // REC: Attempt to read the session's details from
            // the persisted information in the session file:
            FileStream           fsSession     = new FileStream(sessionFile, FileMode.Open, FileAccess.Read, FileShare.None);
            XmlSerializer        xsSession     = new XmlSerializer(typeof(XmlFixDatabaseRecord));
            XmlFixDatabaseRecord sessionRecord = xsSession.Deserialize(fsSession) as XmlFixDatabaseRecord;

            result.TxSequence = sessionRecord.TxSequence;
            result.RxSequence = sessionRecord.RxSequence;
            fsSession.Close();

            // REC: Create the session's lock file:
            string     lockFile = Path.Combine(sessionPath, "Locked.txt");
            FileStream fs       = new FileStream(lockFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None);

            fs.Close();

            // REC: Create a new instance of the SessionDetails class
            // that will be used to maintain the session's information:
            SessionDetails sessionDetails = new SessionDetails();

            // REC: Attempt to open the index file for the session:
            string     idxFile   = Path.Combine(sessionPath, "Index.xml");
            FileStream idxStream = new FileStream(idxFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

            // REC: Maintain a reference to the index file stream
            // in the session's details record:
            sessionDetails.IdxWriter = new StreamWriter(idxStream);

            // REC: Read all of the index entries from the index file
            // and store them in the session's details structure:
            StreamReader idxReader = new StreamReader(idxStream);

            while (idxReader.EndOfStream == false)
            {
                string   idxLine   = idxReader.ReadLine();
                string[] idxTokens = idxLine.Split(new char[] { ':' });

                IndexEntry idxEntry = new IndexEntry();
                idxEntry.msgOffset   = int.Parse(idxTokens[1]);
                idxEntry.msgLength   = int.Parse(idxTokens[2]);
                idxEntry.msgSequence = int.Parse(idxTokens[0]);

                sessionDetails.Index.Add(idxEntry);
            }

            // REC: Attempt to open the message file for the session:
            string     msgFile   = Path.Combine(sessionPath, "Messages.txt");
            FileStream msgStream = new FileStream(msgFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

            // REC: Maintain a reference to the message file stream
            // in the session's details record:
            sessionDetails.MsgWriter = new StreamWriter(msgStream);

            // REC: Add the session details record to the internal
            // map, keyed by the session identifier:
            _mapSessions.Add(sessionId, sessionDetails);

            // REC: Return the session's specifics to the caller:
            return(result);
        }