ThreadedSocketInitiator.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 "ThreadedSocketInitiator.h"
00027 #include "Session.h"
00028 #include "Settings.h"
00029 
00030 namespace FIX
00031 {
00032 ThreadedSocketInitiator::ThreadedSocketInitiator(
00033   Application& application,
00034   MessageStoreFactory& factory,
00035   const SessionSettings& settings ) throw( ConfigError )
00036 : Initiator( application, factory, settings ),
00037   m_lastConnect( 0 ), m_reconnectInterval( 30 ), m_noDelay( false ), 
00038   m_sendBufSize( 0 ), m_rcvBufSize( 0 ) 
00039 { 
00040   socket_init(); 
00041 }
00042 
00043 ThreadedSocketInitiator::ThreadedSocketInitiator(
00044   Application& application,
00045   MessageStoreFactory& factory,
00046   const SessionSettings& settings,
00047   LogFactory& logFactory ) throw( ConfigError )
00048 : Initiator( application, factory, settings, logFactory ),
00049   m_lastConnect( 0 ), m_reconnectInterval( 30 ), m_noDelay( false ), 
00050   m_sendBufSize( 0 ), m_rcvBufSize( 0 ) 
00051 { 
00052   socket_init(); 
00053 }
00054 
00055 ThreadedSocketInitiator::~ThreadedSocketInitiator()
00056 { 
00057   socket_term(); 
00058 }
00059 
00060 void ThreadedSocketInitiator::onConfigure( const SessionSettings& s )
00061 throw ( ConfigError )
00062 {
00063   const Dictionary& dict = s.get();
00064 
00065   if( dict.has( RECONNECT_INTERVAL ) )
00066     m_reconnectInterval = dict.getInt( RECONNECT_INTERVAL );
00067   if( dict.has( SOCKET_NODELAY ) )
00068     m_noDelay = dict.getBool( SOCKET_NODELAY );
00069   if( dict.has( SOCKET_SEND_BUFFER_SIZE ) )
00070     m_sendBufSize = dict.getInt( SOCKET_SEND_BUFFER_SIZE );
00071   if( dict.has( SOCKET_RECEIVE_BUFFER_SIZE ) )
00072     m_rcvBufSize = dict.getInt( SOCKET_RECEIVE_BUFFER_SIZE );
00073 }
00074 
00075 void ThreadedSocketInitiator::onInitialize( const SessionSettings& s )
00076 throw ( RuntimeError )
00077 {
00078 }
00079 
00080 void ThreadedSocketInitiator::onStart()
00081 {
00082   while ( !isStopped() )
00083   {
00084     time_t now;
00085     ::time( &now );
00086 
00087     if ( (now - m_lastConnect) >= m_reconnectInterval )
00088     {
00089       Locker l( m_mutex );
00090       connect();
00091       m_lastConnect = now;
00092     }
00093 
00094     process_sleep( 1 );
00095   }
00096 }
00097 
00098 bool ThreadedSocketInitiator::onPoll( double timeout )
00099 {
00100   return false;
00101 }
00102 
00103 void ThreadedSocketInitiator::onStop()
00104 {
00105   SocketToThread threads;
00106   SocketToThread::iterator i;
00107   
00108   {
00109     Locker l(m_mutex);
00110 
00111     time_t start = 0;
00112     time_t now = 0;
00113 
00114     ::time( &start );
00115     while ( isLoggedOn() )
00116     {
00117       if( ::time(&now) -5 >= start )
00118         break;
00119     }
00120 
00121     threads = m_threads;
00122     m_threads.clear();
00123   }   
00124 
00125   for ( i = threads.begin(); i != threads.end(); ++i )
00126     socket_close( i->first );
00127   
00128   for ( i = threads.begin(); i != threads.end(); ++i )
00129     thread_join( i->second );
00130   threads.clear();
00131 }
00132 
00133 void ThreadedSocketInitiator::doConnect( const SessionID& s, const Dictionary& d )
00134 {
00135   try
00136   {
00137     Session* session = Session::lookupSession( s );
00138     if( !session->isSessionTime(UtcTimeStamp()) ) return;
00139 
00140     Log* log = session->getLog();
00141 
00142     std::string address;
00143     short port = 0;
00144     getHost( s, d, address, port );
00145 
00146     int socket = socket_createConnector();
00147     if( m_noDelay )
00148       socket_setsockopt( socket, TCP_NODELAY );
00149     if( m_sendBufSize )
00150       socket_setsockopt( socket, SO_SNDBUF, m_sendBufSize );
00151     if( m_rcvBufSize )
00152       socket_setsockopt( socket, SO_RCVBUF, m_rcvBufSize );
00153 
00154     setPending( s );
00155     log->onEvent( "Connecting to " + address + " on port " + IntConvertor::convert((unsigned short)port) );
00156 
00157     ThreadedSocketConnection* pConnection =
00158       new ThreadedSocketConnection( s, socket, address, port, getLog() );
00159 
00160     ThreadPair* pair = new ThreadPair( this, pConnection );
00161 
00162     {
00163       Locker l( m_mutex );
00164       thread_id thread;
00165       if ( thread_spawn( &socketThread, pair, thread ) )
00166       {
00167         addThread( socket, thread );
00168       }
00169       else
00170       {
00171         delete pair;
00172         pConnection->disconnect();
00173         delete pConnection;
00174         setDisconnected( s );
00175       }
00176     }
00177   }
00178   catch ( std::exception& ) {}
00179 }
00180 
00181 void ThreadedSocketInitiator::addThread( int s, thread_id t )
00182 {
00183   Locker l(m_mutex);
00184 
00185   m_threads[ s ] = t;
00186 }
00187 
00188 void ThreadedSocketInitiator::removeThread( int s )
00189 {
00190   Locker l(m_mutex);
00191   SocketToThread::iterator i = m_threads.find( s );
00192 
00193   if ( i != m_threads.end() )
00194   {
00195     thread_detach( i->second );
00196     m_threads.erase( i );
00197   }
00198 }
00199 
00200 THREAD_PROC ThreadedSocketInitiator::socketThread( void* p )
00201 {
00202   ThreadPair * pair = reinterpret_cast < ThreadPair* > ( p );
00203 
00204   ThreadedSocketInitiator* pInitiator = pair->first;
00205   ThreadedSocketConnection* pConnection = pair->second;
00206   FIX::SessionID sessionID = pConnection->getSession()->getSessionID();
00207   FIX::Session* pSession = FIX::Session::lookupSession( sessionID );
00208   int socket = pConnection->getSocket();
00209   delete pair;
00210 
00211   pInitiator->lock();
00212 
00213   if( !pConnection->connect() )
00214   {
00215     pInitiator->getLog()->onEvent( "Connection failed" );
00216     pConnection->disconnect();
00217     delete pConnection;
00218     pInitiator->removeThread( socket );
00219     pInitiator->setDisconnected( sessionID );
00220     return 0;
00221   }
00222 
00223   pInitiator->setConnected( sessionID );
00224   pInitiator->getLog()->onEvent( "Connection succeeded" );
00225 
00226   pSession->next();
00227 
00228   while ( pConnection->read() ) {}
00229 
00230   delete pConnection;
00231   if( !pInitiator->isStopped() )
00232     pInitiator->removeThread( socket );
00233   
00234   pInitiator->setDisconnected( sessionID );
00235   return 0;
00236 }
00237 
00238 void ThreadedSocketInitiator::getHost( const SessionID& s, const Dictionary& d,
00239                                        std::string& address, short& port )
00240 {
00241   int num = 0;
00242   SessionToHostNum::iterator i = m_sessionToHostNum.find( s );
00243   if ( i != m_sessionToHostNum.end() ) num = i->second;
00244 
00245   std::stringstream hostStream;
00246   hostStream << SOCKET_CONNECT_HOST << num;
00247   std::string hostString = hostStream.str();
00248 
00249   std::stringstream portStream;
00250   portStream << SOCKET_CONNECT_PORT << num;
00251   std::string portString = portStream.str();
00252 
00253   if( d.has(hostString) && d.has(portString) )
00254   {
00255     address = d.getString( hostString );
00256     port = ( short ) d.getInt( portString );
00257   }
00258   else
00259   {
00260     num = 0;
00261     address = d.getString( SOCKET_CONNECT_HOST );
00262     port = ( short ) d.getInt( SOCKET_CONNECT_PORT );
00263   }
00264 
00265   m_sessionToHostNum[ s ] = ++num;
00266 }
00267 
00268 }

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