Initiator.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) 2001-2014
00003 **
00004 ** This file is part of the QuickFIX FIX Engine
00005 **
00006 ** This file may be distributed under the terms of the quickfixengine.org
00007 ** license as defined by quickfixengine.org and appearing in the file
00008 ** LICENSE included in the packaging of this file.
00009 **
00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 **
00013 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00014 **
00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00016 ** not clear to you.
00017 **
00018 ****************************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 
00026 #include "Initiator.h"
00027 #include "Utility.h"
00028 #include "Session.h"
00029 #include "SessionFactory.h"
00030 #include "HttpServer.h"
00031 #include <algorithm>
00032 #include <fstream>
00033 
00034 namespace FIX
00035 {
00036 Initiator::Initiator( Application& application,
00037                       MessageStoreFactory& messageStoreFactory,
00038                       const SessionSettings& settings ) throw( ConfigError )
00039 : m_threadid( 0 ),
00040   m_application( application ),
00041   m_messageStoreFactory( messageStoreFactory ),
00042   m_settings( settings ),
00043   m_pLogFactory( 0 ),
00044   m_pLog( 0 ),
00045   m_firstPoll( true ),
00046   m_stop( true )
00047 { initialize(); }
00048 
00049 Initiator::Initiator( Application& application,
00050                       MessageStoreFactory& messageStoreFactory,
00051                       const SessionSettings& settings,
00052                       LogFactory& logFactory ) throw( ConfigError )
00053 : m_threadid( 0 ),
00054   m_application( application ),
00055   m_messageStoreFactory( messageStoreFactory ),
00056   m_settings( settings ),
00057   m_pLogFactory( &logFactory ),
00058   m_pLog( logFactory.create() ),
00059   m_firstPoll( true ),
00060   m_stop( true )
00061 { initialize(); }
00062 
00063 void Initiator::initialize() throw ( ConfigError )
00064 {
00065   std::set < SessionID > sessions = m_settings.getSessions();
00066   std::set < SessionID > ::iterator i;
00067 
00068   if ( !sessions.size() )
00069     throw ConfigError( "No sessions defined" );
00070 
00071   SessionFactory factory( m_application, m_messageStoreFactory,
00072                           m_pLogFactory );
00073 
00074   for ( i = sessions.begin(); i != sessions.end(); ++i )
00075   {
00076     if ( m_settings.get( *i ).getString( "ConnectionType" ) == "initiator" )
00077     {
00078       m_sessionIDs.insert( *i );
00079       m_sessions[ *i ] = factory.create( *i, m_settings.get( *i ) );
00080       setDisconnected( *i );
00081     }
00082   }
00083 
00084   if ( !m_sessions.size() )
00085     throw ConfigError( "No sessions defined for initiator" );
00086 }
00087 
00088 Initiator::~Initiator()
00089 {
00090   Sessions::iterator i;
00091   for ( i = m_sessions.begin(); i != m_sessions.end(); ++i )
00092     delete i->second;
00093 
00094   if( m_pLogFactory && m_pLog )
00095     m_pLogFactory->destroy( m_pLog );
00096 }
00097 
00098 Session* Initiator::getSession( const SessionID& sessionID,
00099                                 Responder& responder )
00100 {
00101   Sessions::iterator i = m_sessions.find( sessionID );
00102   if ( i != m_sessions.end() )
00103   {
00104     i->second->setResponder( &responder );
00105     return i->second;
00106   }
00107   return 0;
00108 }
00109 
00110 Session* Initiator::getSession( const SessionID& sessionID ) const
00111 {
00112   Sessions::const_iterator i = m_sessions.find( sessionID );
00113   if( i != m_sessions.end() )
00114     return i->second;
00115   else
00116     return 0;
00117 }
00118 
00119 const Dictionary* const Initiator::getSessionSettings( const SessionID& sessionID ) const
00120 {
00121   try
00122   {
00123     return &m_settings.get( sessionID );
00124   }
00125   catch( ConfigError& )
00126   {
00127     return 0;
00128   }
00129 }
00130 
00131 void Initiator::connect()
00132 {
00133   Locker l(m_mutex);
00134 
00135   SessionIDs disconnected = m_disconnected;
00136   SessionIDs::iterator i = disconnected.begin();
00137   for ( ; i != disconnected.end(); ++i )
00138   {
00139     Session* pSession = Session::lookupSession( *i );
00140     if ( pSession->isEnabled() && pSession->isSessionTime(UtcTimeStamp()) )
00141       doConnect( *i, m_settings.get( *i ));
00142   }
00143 }
00144 
00145 void Initiator::setPending( const SessionID& sessionID )
00146 {
00147   Locker l(m_mutex);
00148 
00149   m_pending.insert( sessionID );
00150   m_connected.erase( sessionID );
00151   m_disconnected.erase( sessionID );
00152 }
00153 
00154 void Initiator::setConnected( const SessionID& sessionID )
00155 {
00156   Locker l(m_mutex);
00157 
00158   m_pending.erase( sessionID );
00159   m_connected.insert( sessionID );
00160   m_disconnected.erase( sessionID );
00161 }
00162 
00163 void Initiator::setDisconnected( const SessionID& sessionID )
00164 {
00165   Locker l(m_mutex);
00166 
00167   m_pending.erase( sessionID );
00168   m_connected.erase( sessionID );
00169   m_disconnected.insert( sessionID );
00170 }
00171 
00172 bool Initiator::isPending( const SessionID& sessionID )
00173 {
00174   Locker l(m_mutex);
00175   return m_pending.find( sessionID ) != m_pending.end();
00176 }
00177 
00178 bool Initiator::isConnected( const SessionID& sessionID )
00179 {
00180   Locker l(m_mutex);
00181   return m_connected.find( sessionID ) != m_connected.end();
00182 }
00183 
00184 bool Initiator::isDisconnected( const SessionID& sessionID )
00185 {
00186   Locker l(m_mutex);
00187   return m_disconnected.find( sessionID ) != m_disconnected.end();
00188 }
00189 
00190 void Initiator::start() throw ( ConfigError, RuntimeError )
00191 {
00192   m_stop = false;
00193   onConfigure( m_settings );
00194   onInitialize( m_settings );
00195 
00196   HttpServer::startGlobal( m_settings );
00197 
00198   if( !thread_spawn( &startThread, this, m_threadid ) )
00199     throw RuntimeError("Unable to spawn thread");
00200 }
00201 
00202 
00203 void Initiator::block() throw ( ConfigError, RuntimeError )
00204 {
00205   m_stop = false;
00206   onConfigure( m_settings );
00207   onInitialize( m_settings );
00208 
00209   startThread(this);
00210 }
00211 
00212 bool Initiator::poll( double timeout ) throw ( ConfigError, RuntimeError )
00213 {
00214   if( m_firstPoll )
00215   {
00216     m_stop = false;
00217     onConfigure( m_settings );
00218     onInitialize( m_settings );
00219     connect();
00220     m_firstPoll = false;
00221   }
00222 
00223   return onPoll( timeout );
00224 }
00225 
00226 void Initiator::stop( bool force )
00227 {
00228   if( isStopped() ) return;
00229 
00230   HttpServer::stopGlobal();
00231 
00232   std::vector<Session*> enabledSessions;
00233 
00234   SessionIDs connected = m_connected;
00235   SessionIDs::iterator i = connected.begin();
00236   for ( ; i != connected.end(); ++i )
00237   {
00238     Session* pSession = Session::lookupSession(*i);
00239     if( pSession && pSession->isEnabled() )
00240     {
00241       enabledSessions.push_back( pSession );
00242       pSession->logout();
00243     }
00244   }
00245 
00246   if( !force )
00247   {
00248     for ( int second = 1; second <= 10 && isLoggedOn(); ++second )
00249       process_sleep( 1 );
00250   }
00251 
00252   {
00253     Locker l(m_mutex);
00254     for ( i = connected.begin(); i != connected.end(); ++i )
00255       setDisconnected( Session::lookupSession(*i)->getSessionID() );
00256   }
00257 
00258   m_stop = true;
00259   onStop();
00260   if( m_threadid )
00261     thread_join( m_threadid );
00262   m_threadid = 0;
00263 
00264   std::vector<Session*>::iterator session = enabledSessions.begin();
00265   for( ; session != enabledSessions.end(); ++session )
00266     (*session)->logon();
00267 }
00268 
00269 bool Initiator::isLoggedOn()
00270 {
00271   Locker l(m_mutex);
00272 
00273   SessionIDs connected = m_connected;
00274   SessionIDs::iterator i = connected.begin();
00275   for ( ; i != connected.end(); ++i )
00276   {
00277     if( Session::lookupSession(*i)->isLoggedOn() )
00278       return true;
00279   }
00280   return false;
00281 }
00282 
00283 THREAD_PROC Initiator::startThread( void* p )
00284 {
00285   Initiator * pInitiator = static_cast < Initiator* > ( p );
00286   pInitiator->onStart();
00287   return 0;
00288 }
00289 }

Generated on Mon Sep 15 2014 01:23:54 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001